无需反射API通过Spring Data Redis获取Redis连接池监控数据的方案
无反射Redis连接池监控实现方案
方案1:高版本Spring Data Redis直接调用公开API
Spring Data Redis 2.5.0及以上版本中,JedisConnectionFactory已经提供了公开的getPool()方法,不需要反射即可直接获取连接池实例,修改后的代码如下:
@Autowired private RedisConnectionFactory redisConnectionFactory; private void logData(HttpServletRequest request, Exception e) { try { HttpSession session = request.getSession(); // 校验连接工厂类型 if (redisConnectionFactory instanceof JedisConnectionFactory factory) { Pool<Jedis> jedisPool = factory.getPool(); if (jedisPool != null) { int activeNum = jedisPool.getNumActive(); int idleNum = jedisPool.getNumIdle(); int waitNum = jedisPool.getNumWaiters(); long maxBorrowWaitMs = jedisPool.getMaxBorrowWaitTimeMillis(); long meanBorrowWaitMs = jedisPool.getMeanBorrowWaitTimeMillis(); redisMonitorDetails = redisMonitorDetails + "getNumActive=" + activeNum + " NumIdle=" + idleNum + " NumWaiters=" + waitNum + " MaxBorrowWaitTimeMillis=" + maxBorrowWaitMs + " MeanBorrowWaitTimeMillis=" + meanBorrowWaitMs; } } } catch (Exception exe) { loggingService.error("Exception during logging in ExceptionHandlerController: ", exe); } }
该方案无需额外配置,仅需确认你的spring-data-redis依赖版本符合要求即可,完全规避反射调用的安全风险。
方案2:低版本自定义配置暴露连接池
如果你使用的Spring Data Redis版本低于2.5.0,可在自定义Redis配置类中手动构建连接池并注入到Spring容器,监控代码直接注入该连接池实例即可:
第一步:自定义Redis配置类
@Configuration public class RedisConfig { @Bean public JedisPoolConfig jedisPoolConfig() { JedisPoolConfig poolConfig = new JedisPoolConfig(); // 这里替换为你实际的连接池配置,比如最大连接数、最大空闲时间等 poolConfig.setMaxTotal(200); poolConfig.setMaxIdle(50); poolConfig.setMinIdle(10); poolConfig.setMaxWait(Duration.ofMillis(3000)); return poolConfig; } // 单独将JedisPool注入容器,供监控逻辑直接调用 @Bean public JedisPool jedisPool(JedisPoolConfig poolConfig) { // 替换为你实际的Redis连接信息 return new JedisPool(poolConfig, "127.0.0.1", 6379, 3000, "your-redis-password", 0); } @Bean public RedisConnectionFactory redisConnectionFactory(JedisPool jedisPool) { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("127.0.0.1", 6379); // 替换为你实际的Redis密码、库号等配置 config.setPassword(RedisPassword.of("your-redis-password")); config.setDatabase(0); return new JedisConnectionFactory(config, JedisClientConfiguration.builder() .usePooling() .poolConfig(jedisPool.getPoolConfig()) .build()); } }
第二步:监控代码直接注入连接池实例
@Autowired private JedisPool jedisPool; private void logData(HttpServletRequest request, Exception e) { try { HttpSession session = request.getSession(); int activeNum = jedisPool.getNumActive(); int idleNum = jedisPool.getNumIdle(); int waitNum = jedisPool.getNumWaiters(); long maxBorrowWaitMs = jedisPool.getMaxBorrowWaitTimeMillis(); long meanBorrowWaitMs = jedisPool.getMeanBorrowWaitTimeMillis(); redisMonitorDetails = redisMonitorDetails + "getNumActive=" + activeNum + " NumIdle=" + idleNum + " NumWaiters=" + waitNum + " MaxBorrowWaitTimeMillis=" + maxBorrowWaitMs + " MeanBorrowWaitTimeMillis=" + meanBorrowWaitMs; } catch (Exception exe) { loggingService.error("Exception during logging in ExceptionHandlerController: ", exe); } }
该方案完全不需要通过反射访问私有字段,从根源上避免SAST扫描的安全告警,同时兼容所有Spring Data Redis版本。
如果你使用的是Redis哨兵、集群模式,仅需调整RedisConfiguration的实现类为
RedisSentinelConfiguration、RedisClusterConfiguration即可,核心的连接池暴露逻辑不变。
内容的提问来源于stack exchange,提问作者Abhiram S
相关产品推荐
相关产品推荐

