Jedis封装使用

2020-09-18  本文已影响0人  樱花舞

Jedis是Redis的Java实现客户端,提供了比较全面的Redis操作方法,且与Redis的命令很接近。这是在spring boot框架下的,对jedis封装成工具,方便调用。

<dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>3.3.0</version>
</dependency>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

1、单机模式封装
单机模式下使用jedis的例子是这样的:

        JedisPool pool = JedisFactory.createJedisPool(new RedisProperties());
        Jedis jedis = pool.getResource();
        try {
            jedis = pool.getResource();
            return method.invoke(jedis, args);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }

但这样就会有try catch finally的结构来关闭jedis,如果每次调用都需要这样写就会有很多重复代码,可以用代理模式来优化。创建JedisHandler实现InvocationHandler。

public class JedisHandler implements InvocationHandler {
    private JedisPool pool;

    public JedisHandler(JedisPool pool) {
        this.pool = pool;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Jedis jedis = null;
        try {
            System.out.println("进入代理");
            jedis = pool.getResource();
            return method.invoke(jedis, args);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
}

然后创建一个工厂类,用来创建jedis的实例。RedisProperties是pring-boot-autoconfigure的配置类,对应yml配置的spring.redis的配置。Jedis类实现JedisCommands接口,所以调用createJedis方法最后返回的是代理类,而不用重复写try这些重复代码,每次调用JedisCommands的方法,代理类都会自动关闭jedis。

public class JedisFactory {

    /**
     * 创建单机连接池
     *
     * @param properties
     * @return
     */
    public static JedisPool createJedisPool(RedisProperties properties) {
        JedisPoolConfig config = setConfig(properties);
        return new JedisPool(config, properties.getHost(), properties.getPort(), 3000,
                properties.getPassword(), properties.getDatabase());
    }

    /**
     * 创建单机客户端
     *
     * @param properties
     * @return
     */
    public static JedisCommands createJedis(RedisProperties properties) {
        JedisPoolConfig config = setConfig(properties);
        JedisPool jedisPool = new JedisPool(config, properties.getHost(), properties.getPort(), 3000,
                properties.getPassword(), properties.getDatabase());
        return createJedis(jedisPool);
    }

    /**
     * 创建单机客户端
     *
     * @param pool
     * @return
     */
    public static JedisCommands createJedis(JedisPool pool) {
        JedisHandler handler = new JedisHandler(pool);
        return (JedisCommands) Proxy.newProxyInstance(JedisCommands.class.getClassLoader(), new Class[]{JedisCommands.class}, handler);
    }

    /**
     * 创建集群客户端
     *
     * @param properties
     * @return
     */
    public static JedisCluster createCluster(RedisProperties properties) {
        List<String> nodeStr = properties.getCluster().getNodes();
        Set<HostAndPort> nodes = new HashSet<>();
        for (String node : nodeStr) {
            String[] hostPort = node.split(":");
            nodes.add(new HostAndPort(hostPort[0], Integer.valueOf(hostPort[1])));
        }
        JedisPoolConfig config = setConfig(properties);
        // 利用上面的集群节点nodes和poolConfig,创建redis集群连接池,并获取一个redis连接
        return new JedisCluster(nodes, 3000, 3000, 5, properties.getPassword(), config);
    }

    /**
     * 获取配置
     *
     * @param properties
     * @return
     */
    private static JedisPoolConfig setConfig(RedisProperties properties) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(properties.getJedis().getPool().getMaxIdle());
        config.setMaxIdle(properties.getJedis().getPool().getMaxIdle());
        config.setMinIdle(properties.getJedis().getPool().getMinIdle());
        config.setMaxWaitMillis(3000);
        config.setTestOnBorrow(false);
        config.setTestOnReturn(false);
        return config;
    }
}

使用时创建JedisCommands的bean,然后用@Autowired注解调用即可。

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class JedisConfig {
    private static final Logger LOGGER = LoggerFactory.getLogger(JedisAutoConfiguration.class);
    private JedisPool pool;

    @Bean
    public JedisCommands jedisCommands(RedisProperties properties) {
        //单机模式
        LOGGER.info("redis connect {}", properties.getHost());
        pool = JedisFactory.createJedisPool(properties);
        JedisCommands commands = JedisFactory.createJedis(pool);
        return commands;
    }


    @PreDestroy
    public void destroy() {
        if (pool != null) {
            LOGGER.info("close redis pool");
            pool.close();
        }
    }
}

上面的使用例子需要手动创建bean,但可以更进一步,使用spring boot 的自动注入,把jedis封装成依赖包,当其他应用使用时,只需依赖此依赖包,并在配置文件yml配置连接等,就可直接调用了。

@Configuration
@ConditionalOnClass({Jedis.class, JedisCluster.class})
@EnableConfigurationProperties(RedisProperties.class)
public class JedisAutoConfiguration {
    private static final Logger LOGGER = LoggerFactory.getLogger(JedisAutoConfiguration.class);
    private JedisPool pool;

    @Bean
    @ConditionalOnMissingBean
    public JedisCommands jedisCommands(RedisProperties properties) {
        //单机模式
        LOGGER.info("redis connect {}", properties.getHost());
        pool = JedisFactory.createJedisPool(properties);
        JedisCommands commands = JedisFactory.createJedis(pool);

        return commands;
    }


    @PreDestroy
    public void destroy() {
        if (pool != null) {
            LOGGER.info("close redis pool");
            pool.close();
        }
    }
}

自定义启动使用jedis的注解@EnableJedis

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({JedisAutoConfiguration.class})
public @interface EnableJedis {

}

使用时只需在@SpringCloudApplication 注解的启动类上加入@EnableJedis就默认使用jedis,然后在需要调用时用@Autowired注解调用即可。

上一篇 下一篇

猜你喜欢

热点阅读