欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring boot开发web api应用实践(五)集成Redis客户端 博客分类: spring boot 实践笔记 spring bootredis 

程序员文章站 2024-03-13 19:06:45
...

    本篇主要记录如何在spring boot开发中,集成redis操作。按照spring boot的惯例,开发一个redis starter模块,借此记录如何开发一个spring boot starter模块。

     在java ide中新建maven工程,按照spring boot starter约定的规则命名为ecode-redis-spring-boot-starter,并引入依赖:

  <dependencies>
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
      </dependency>
      <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-configuration-processor</artifactId>
           <optional>true</optional>
      </dependency>
      <dependency>
      	  <groupId>redis.clients</groupId>
      	  <artifactId>jedis</artifactId>
      </dependency>
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId> 
	  </dependency>
  </dependencies>
  <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot,not include plugin
                    management as the parent import style -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
  </dependencyManagement>

 完整的pom.xml参考源码文件。工程结构如下图:

spring boot开发web api应用实践(五)集成Redis客户端
            
    
    博客分类: spring boot 实践笔记 spring bootredis 

     本redis-starter模块主要java文件只有三个:

     (1)redis连接池配置类:RedisProperties.java

        redis连接池的配置项主要有(下面配置项主要配置在application.properties中):             

ecode.redis.host=redis服务端主机地址(如192.168.1.110)
ecode.redis.port=redis服务连接端口(默认6379)
ecode.redis.timeout=3000
ecode.redis.password=redis_password
ecode.redis.max-active=50
ecode.redis.max-idle=5
ecode.redis.min-idle=0
ecode.redis.max-waitMillis=5000
ecode.redis.test-on-borrow=false
ecode.redis.test-on-return=false
ecode.redis.dbidx=0

   对应的java配置类为RedisProperties.java,代码片段:

import org.springframework.boot.context.properties.ConfigurationProperties;
 
@ConfigurationProperties(prefix = "ecode.redis")
public class RedisProperties {
    private String host;
    private int port = 6379;
    private int timeout = 3000;
    private String password;
    private int maxActive = 10;
    private int maxIdle = 5;
    private int minIdle = 0;
    private long maxWaitMillis = 5000;
    private boolean testOnBorrow = false;
    private boolean testOnReturn = false;
    private int dbidx;

   //属性字段对应的set、get方法
}

    @ConfigurationProperties注解指定该类为spring boot的属性配置类,prefix属性指定配置项的前缀。

   (2)redis连接池自动初始化类:RedisAutoConfiguration.java

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass({ JedisPoolConfig.class, JedisPool.class, Jedis.class })
public class RedisAutoConfiguration {
    @Autowired
    private RedisProperties properties;
    
    private JedisPool jedisPool;
    
    @PostConstruct
    public void initJedisPool() {
        System.out.print("------初始化JedisPool.....host=" + properties.getHost());
        boolean hostExist = properties.getHost() != null && properties.getHost().trim().length() > 0;
        Assert.isTrue(hostExist, "Redis主机地址不能为空,请配置[ecode.redis.host]");
        
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(properties.getMaxActive());
        config.setMaxIdle(properties.getMaxIdle());
        config.setMinIdle(properties.getMinIdle());
        config.setMaxWaitMillis(properties.getMaxWaitMillis());
        config.setTestOnBorrow(properties.isTestOnBorrow());
        config.setTestOnReturn(properties.isTestOnReturn()); 
        
        if (properties.getPassword() == null || properties.getPassword().trim().length() <= 0){
            jedisPool = new JedisPool(config, properties.getHost(), properties.getPort(), 
                                        properties.getTimeout(), null, properties.getDbidx());
        }else{
            jedisPool = new JedisPool(config, properties.getHost(), properties.getPort(), properties.getTimeout(), 
                                        properties.getPassword(), properties.getDbidx());
        }
        
        System.out.println(".....ok!");
    }

    //........初始化redis操作客户端实例并注入spring容器
}

   (3)redis命令操作类:RedisClient.java

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;

public class RedisClient {
    private JedisPool pool;

    public void setPool(JedisPool pool){ this.pool = pool; }
    
    public RedisClient(){}
    public RedisClient(JedisPool pool){ this.pool = pool;}
    
    public Jedis getJedis() { return pool.getResource(); }
    
    public void release(Jedis jedis) {  if (jedis != null) jedis.close(); }
    
    public Set<String> getAllKeys(String pattern){
        Jedis jedis = null;  
        try {  
            jedis = getJedis();  
            return jedis.keys(pattern);
        } catch (Exception e) {
            String err = "从Redis里获取所有匹配("+pattern+")的KEY值发生异常";
            //LOG.error(err, e);
            throw new RuntimeException(err, e);
        }finally{
            release(jedis);
        }
    }
    
    /**
     * 以秒为单位返回 key的剩余过期时间。<br><br>
     * 注:当 key不存在时,返回 -2 。 当 key存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key的剩余生存时间。<br>
     *    在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 
     * @param key
     * @return 
     * 
     */
    public Long ttl(String key) { 
        Jedis jedis = null;  
        try {  
            jedis = getJedis();  
            return jedis.ttl(key);
        } catch (Exception e) {
            String err = "从Redis里获取key="+key+"的剩余过期时长发生异常";
            //LOG.error(err, e);
            throw new RuntimeException(err, e);
        }finally{
            release(jedis);
        }
    }
    
    public void set(String key, String value) {  
        if (value == null){
            return;
        }
        
        Jedis jedis = null;  
        try {  
            jedis = getJedis();  
            jedis.set(key, value);
        } catch (Exception e) {
            //LOG.error("往Redis里set[key={}, value={}]的值发生异常", key, value, e);
            throw new RuntimeException("往Redis里设置key="+key+"的值发生异常", e);
        }finally{
            release(jedis);
        }
    }

   //....其他redis命令操作

}

   

    然后在第(2)步的redis连接池自动初始化类(RedisAutoConfiguration.java)中增加RedisClient的初始化方法:

    @Bean
    @ConditionalOnMissingBean
    public RedisClient redisClient(){
        Assert.isTrue(jedisPool != null, "JedisPool尚未初始化,无法初始化RedisClient");
        return new RedisClient(jedisPool);
    }

 

   代码完成后,要使项目运行时,redis连接池自动初始化类(RedisAutoConfiguration.java)生效,也就是真正做到redis的auto configure,还需要在spring.factories文件中注册RedisAutoConfiguration.java,该文件位于resources/META-INF路径下面。注册内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jsecode.springboot.redis.RedisAutoConfiguration

 很多道友初次创建自己的spring boot starter模块时,发现配置类并没有auto configure,原因就是忘了在spring.factories文件中注册自己的AutoConfiguration类。

 

(4)在应用中使用redis客户端,只需要在应用的pom.xml中引入ecode-redis-spring-boot-starter模块的依赖,然后在需要使用redis的类中注入RedisClient的实例:

      @Autowired
      RedisClient redisClient;

 然后调用redisClient来操作redis命令。

 

完整工程源码参考github

相关标签: spring boot redis