sugren 2023-08-30 16:50 采纳率: 0%
浏览 21

Springboot整合 shiro+redis报错JedisException: Could not return the broken resource to the pool

springboot整合shiro+redis 整合完成以后 功能是正常的 但是控制台每隔一段时间就报错

2023-08-30 16:38:36.959 WARN [commons-pool-evictor]redis.clients.jedis.JedisFactory.destroyObject:168 -Error while close
redis.clients.jedis.exceptions.JedisException: Could not return the broken resource to the pool
    at redis.clients.jedis.util.Pool.returnBrokenResourceObject(Pool.java:126)
    at redis.clients.jedis.util.Pool.returnBrokenResource(Pool.java:103)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:389)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:15)
    at redis.clients.jedis.Jedis.close(Jedis.java:4081)
    at redis.clients.jedis.JedisFactory.destroyObject(JedisFactory.java:166)
    at org.apache.commons.pool2.PooledObjectFactory.destroyObject(PooledObjectFactory.java:127)
    at org.apache.commons.pool2.impl.GenericObjectPool.destroy(GenericObjectPool.java:611)
    at org.apache.commons.pool2.impl.GenericObjectPool.evict(GenericObjectPool.java:729)
    at org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor.run(BaseGenericObjectPool.java:160)
    at org.apache.commons.pool2.impl.EvictionTimer$WeakRunner.run(EvictionTimer.java:113)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Invalidated object not currently part of this pool
    at org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:936)
    at org.apache.commons.pool2.impl.GenericObjectPool.invalidateObject(GenericObjectPool.java:914)
    at redis.clients.jedis.util.Pool.returnBrokenResourceObject(Pool.java:124)
    ... 18 common frames omitted
2023-08-30 16:38:36.961 WARN [commons-pool-evictor]redis.clients.jedis.JedisFactory.destroyObject:168 -Error while close
redis.clients.jedis.exceptions.JedisException: Could not return the broken resource to the pool
    at redis.clients.jedis.util.Pool.returnBrokenResourceObject(Pool.java:126)
    at redis.clients.jedis.util.Pool.returnBrokenResource(Pool.java:103)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:389)
    at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:15)
    at redis.clients.jedis.Jedis.close(Jedis.java:4081)
    at redis.clients.jedis.JedisFactory.destroyObject(JedisFactory.java:166)
    at org.apache.commons.pool2.PooledObjectFactory.destroyObject(PooledObjectFactory.java:127)
    at org.apache.commons.pool2.impl.GenericObjectPool.destroy(GenericObjectPool.java:611)
    at org.apache.commons.pool2.impl.GenericObjectPool.evict(GenericObjectPool.java:729)
    at org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor.run(BaseGenericObjectPool.java:160)
    at org.apache.commons.pool2.impl.EvictionTimer$WeakRunner.run(EvictionTimer.java:113)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)

下面是我的配置文件

package com.kth.basicadmin.common.config.shiro;

import com.alibaba.druid.support.http.StatViewServlet;
import com.kth.basicadmin.common.utils.LoadPackageClasses;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.filter.DelegatingFilterProxy;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;



/**
 * @author 10412
 */
@Configuration
public class ShiroConfig implements EnvironmentAware{



    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new CustomShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager());
        // 没有登录的用户只能访问登录页面,设置
        factoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        factoryBean.setSuccessUrl("/index");
        // 未授权界面; ----这个配置了没卵用,具体原因想深入了解的可以自行百度
//        factoryBean.setUnauthorizedUrl("/unauth");

        // 权限控制map.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        //配置不登录可以访问的资源,anon 表示资源都可以匿名访问
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/auth/login", "anon");
        /**
         * 其他资源都需要认证  authc 表示需要认证才能进行访问 user表示配置记住我或认证通过可以访问的地址
         *如果开启限制同一账号登录,改为 .put("/**", "kickout,user");
         **/
        filterChainDefinitionMap.put("/*Controller/*", "user");
        filterChainDefinitionMap.put("/index", "authc");

        factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return factoryBean;
    }

    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean() {
        MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean();
        bean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        bean.setArguments(securityManager());
        return bean;
    }



    @Bean(name = "rememberAuthFilter")
    public RememberAuthenticationFilter rememberAuthenticationFilter() {
        RememberAuthenticationFilter filter = new RememberAuthenticationFilter();
        filter.setUsernameParam("userName");
        return filter;
    }
    /**
     * cookie对象;会话Cookie模板 ,默认为: JSESSIONID 问题: 与SERVLET容器名冲突,重新定义为sid或rememberMe,自定义
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //setcookie的httponly属性如果设为true的话,会增加对xss防护的安全系数。它有以下特点:
        //setcookie()的第七个参数
        //设为true后,只能通过http访问,javascript无法访问
        //防止xss读取cookie
        simpleCookie.setHttpOnly(true);
        simpleCookie.setPath("/");
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        simpleCookie.setMaxAge(2592000);
        return simpleCookie;
    }

    /**
     * cookie管理对象;记住我功能,rememberMe管理器
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("************"));
        return cookieRememberMeManager;
    }

    /**
     * FormAuthenticationFilter 过滤器 过滤记住我
     * @return
     */
    @Bean
    public FormAuthenticationFilter formAuthenticationFilter(){
        FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
        //对应前端的checkbox的name = rememberMe
        formAuthenticationFilter.setRememberMeParam("rememberMe");
        return formAuthenticationFilter;
    }

    @Bean
    public FilterRegistrationBean registrationBean() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
        //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
        // 可以自己灵活的定义很多,避免一些根本不需要被Shiro处理的请求被包含进来
        filterRegistration.addUrlPatterns("/*");
        filterRegistration.addUrlPatterns("/WEB-INF/jsp/*");
        filterRegistration.addUrlPatterns("/login");
        filterRegistration.addUrlPatterns("/index");
        filterRegistration.addUrlPatterns("/logout");
        return filterRegistration;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(myShiroRealm());
        // 自定义缓存实现 使用redis
        securityManager.setCacheManager(cacheManager());
        // 自定义session管理 使用redis
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    /**
     * 身份认证realm; (这个需要自己写,账号密码校验;权限等)
     *
     * @return
     */
    @Bean
    public CustomRealm myShiroRealm() {
        CustomRealm customRealm = new CustomRealm();
        return customRealm;
    }

    /**
     * cacheManager 缓存 redis实现
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    /**
     * 配置shiro redisManager
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        Optional<String> hostOpt = Optional.ofNullable(environment.getProperty("spring.redis.host"));
        String host = hostOpt.orElse("localhost");
        Optional<String> portOpt = Optional.ofNullable(environment.getProperty("spring.redis.port"));
        int port = Integer.parseInt(portOpt.orElse("6379"));
        Optional<String> timeoutOpt = Optional.ofNullable(environment.getProperty("spring.redis.timeout"));
        int timeout = Integer.parseInt(timeoutOpt.orElse("2000"));
        Optional<String> expireOpt = Optional.ofNullable(environment.getProperty("spring.redis.expire"));
        int expire = Integer.parseInt(expireOpt.orElse("2000"));
        Optional<String> passwordOpt = Optional.ofNullable(environment.getProperty("spring.redis.password"));
        String password = passwordOpt.orElse("");
        redisManager.setHost(host);
        redisManager.setPort(port);
        // 配置缓存过期时间
        redisManager.setExpire(expire);
        redisManager.setTimeout(timeout);
        if(password!=null&&!"".equals(password)){
            redisManager.setPassword(password);
        }

        return redisManager;
    }

    /**
     * Session Manager
     * 使用的是shiro-redis开源插件
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        sessionManager.setGlobalSessionTimeout(Long.valueOf(environment.getProperty("core.sessionMaxTimeout")));
        return sessionManager;
    }

    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     * 使用的是shiro-redis开源插件
     */
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        Optional<String> property = Optional.ofNullable(environment.getProperty("server.servlet.context-path"));
        String context = property.orElse("/sso");
        redisSessionDAO.setKeyPrefix("shiro:session:" + context.replace("/","") + ":");
        return redisSessionDAO;
    }




    /***
     * 授权所用配置
     *
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    /***
     * 使授权注解起作用不如不想配置可以在pom文件中加入
     * <dependency>
     *<groupId>org.springframework.boot</groupId>
     *<artifactId>spring-boot-starter-aop</artifactId>
     *</dependency>
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * Shiro生命周期处理器
     *
     */
    @Bean
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }



  @Bean
  public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() {
    ServletRegistrationBean<StatViewServlet> registrationBean =
        new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
    // IP白名单 (没有配置或者为空,则允许所有访问)
//    registrationBean.addInitParameter("allow", "127.0.0.1");
    // IP黑名单 (存在共同时,deny优先于allow)
//    registrationBean.addInitParameter("deny", "");
//    registrationBean.addInitParameter("loginUsername", "root");
//    registrationBean.addInitParameter("loginPassword", "kth54321");
//    registrationBean.addInitParameter("resetEnable", "false");
    return registrationBean;
  }


}

  • 写回答

3条回答 默认 最新

  • bug菌¹ Java领域优质创作者 2023-09-04 14:44
    关注

    题主,这个问题我来替你解决,若有帮助,还望采纳,点击回答右侧采纳即可。


    这个错误通常是由于Jedis连接池中的某些连接已经失效导致的。要解决这个问题,可以尝试以下几种方法:

    1. 增大连接池的大小

    可以尝试将连接池的大小调大,以保证连接数足够满足应用的需求。在Spring Boot中,可以在application.yml或application.properties中配置相应的属性,如下所示:

    spring.redis.jedis.pool.max-active=100
    spring.redis.jedis.pool.max-idle=50
    spring.redis.jedis.pool.min-idle=10
    
    1. 重新配置redis服务器

    如果连接池的大小已经足够大,可以考虑检查redis服务器的配置,以确保它能够支持应用程序所需的连接数。可以尝试增加redis服务器的内存或调整一些其他配置参数。

    1. 检查网络环境

    如果服务器和redis服务器之间的网络环境不稳定或者延迟较高,也可能导致连接池中的连接失效。可以使用ping命令或其他网络测试工具检查网络的连通性和稳定性,并在必要时优化网络环境。

    1. 更新jedis版本

    可能是jedis版本与redis版本不相适应,需要根据redis服务器的版本更新jedis的版本号。

    评论

报告相同问题?

问题事件

  • 创建了问题 8月30日

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题