Spring Boot整合Redis
spring boot提供了spring-data-redis库来整合 Redis的操作,并通过简单的配置信息实现与Redis的整合。
PS:个人还是习惯于使用 Jedis 面向 Java 客户端操作 Redis
废话不多说,上代码。 :-)
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- <!-- Spring Boot项目里不用加版本号,加入 spring-boot-starter-data-redis 即可 -->
- <!-- 非Spring Boot项目下,可在 maven repository 中选合适的版本号 -->
- <!-- 面向java客户端Redis操作 -->
- <dependency>
- <groupId>redis.clients</groupId>
- <artifactId>jedis</artifactId>
- </dependency>
- ########################## redis ###################################
- # Redis服务器地址
- spring.redis.host=127.0.0.1
- # Redis服务器连接密码(默认为空)
- spring.redis.password=123456
- # Redis服务器连接端口
- spring.redis.port=6379
- # 连接超时时间(毫秒)
- spring.redis.timeout=3000
- # redis 连接池配置
- # 池中最大链接数
- spring.redis.pool-config.max-total=256
- # 连接池中的最大空闲连接
- spring.redis.pool-config.max-idle=3000
- # 连接池中的最小空闲连接
- spring.redis.pool-config.min-idle=8
- # 连接池最大阻塞等待时间(使用负值表示没有限制)
- spring.redis.pool-config.max-wait-millis=1000
- # 调用者获取链接时,是否检测当前链接有效性
- spring.redis.pool-config.test-on-borrow=false
- # 向链接池中归还链接时,是否检测链接有效性
- spring.redis.pool-config.test-on-return=false
- # 调用者获取链接时,是否检测空闲超时, 如果超时,则会被移除
- spring.redis.pool-config.test-while-idle=true
- # 空闲链接检测线程一次运行检测多少条链接
- spring.redis.pool-config.num-tests-per-eviction-run=8
- # 空闲链接检测线程检测周期。如果为负值,表示不运行检测线程。(单位:毫秒,默认为-layer)
- spring.redis.pool-config.time-between-eviction-runs-millis=60000
- # 配置一个连接在池中最小生存的时间,单位是毫秒
- spring.redis.pool-config.min-evictable-idle-time-millis=300000
注:properties中的配置可根据项目实际情况自己调整,我不敢保证以上配置所有项目都适用
- @Configuration
- @ConfigurationProperties(prefix = "spring.redis")
- public class RedisProperties {
-
- private String host;
-
- private String password;
-
- private int port;
-
- private int timeout;
-
- // 此对象的句柄命名要和 Properties 中一一对应
- // Properties 中为 “pool-config” 那么这里应为 “poolConfig”
- private RedisPoolConfigProperties poolConfig = new RedisPoolConfigProperties();
-
- public String getHost() {
- return host;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public int getPort() {
- return port;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
-
- public int getTimeout() {
- return timeout;
- }
-
- public void setTimeout(int timeout) {
- this.timeout = timeout;
- }
-
- public RedisPoolConfigProperties getPoolConfig() {
- return poolConfig;
- }
-
- public void setPoolConfig(RedisPoolConfigProperties poolConfig) {
- this.poolConfig = poolConfig;
- }
-
- @Override
- public String toString() {
- return "RedisProperties{" +
- "host='" + host + '\'' +
- ", password='" + password + '\'' +
- ", port=" + port +
- ", timeout=" + timeout +
- ", poolConfig=" + poolConfig +
- '}';
- }
- }
- // 该对象为 上面 RedisProperties 中的一个属性
- public class RedisPoolConfigProperties {
-
- private int maxTotal;
-
- private int maxIdle;
-
- private int minIdle;
-
- private int maxWaitMillis;
-
- private Boolean testOnBorrow;
-
- private Boolean testOnReturn;
-
- private Boolean testWhileIdle;
-
- private int numTestsPerEvictionRun;
-
- private int timeBetweenEvictionRunsMillis;
-
- private int minEvictableIdleTimeMillis;
-
- public int getMaxTotal() {
- return maxTotal;
- }
-
- public void setMaxTotal(int maxTotal) {
- this.maxTotal = maxTotal;
- }
-
- public int getMaxIdle() {
- return maxIdle;
- }
-
- public void setMaxIdle(int maxIdle) {
- this.maxIdle = maxIdle;
- }
-
- public int getMinIdle() {
- return minIdle;
- }
-
- public void setMinIdle(int minIdle) {
- this.minIdle = minIdle;
- }
-
- public int getMaxWaitMillis() {
- return maxWaitMillis;
- }
-
- public void setMaxWaitMillis(int maxWaitMillis) {
- this.maxWaitMillis = maxWaitMillis;
- }
-
- public Boolean getTestOnBorrow() {
- return testOnBorrow;
- }
-
- public void setTestOnBorrow(Boolean testOnBorrow) {
- this.testOnBorrow = testOnBorrow;
- }
-
- public Boolean getTestOnReturn() {
- return testOnReturn;
- }
-
- public void setTestOnReturn(Boolean testOnReturn) {
- this.testOnReturn = testOnReturn;
- }
-
- public Boolean getTestWhileIdle() {
- return testWhileIdle;
- }
-
- public void setTestWhileIdle(Boolean testWhileIdle) {
- this.testWhileIdle = testWhileIdle;
- }
-
- public int getNumTestsPerEvictionRun() {
- return numTestsPerEvictionRun;
- }
-
- public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
- this.numTestsPerEvictionRun = numTestsPerEvictionRun;
- }
-
- public int getTimeBetweenEvictionRunsMillis() {
- return timeBetweenEvictionRunsMillis;
- }
-
- public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
- this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
- }
-
- public int getMinEvictableIdleTimeMillis() {
- return minEvictableIdleTimeMillis;
- }
-
- public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
- this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
- }
-
- @Override
- public String toString() {
- return "RedisPoolConfigProperties{" +
- "maxTotal=" + maxTotal +
- ", maxIdle=" + maxIdle +
- ", minIdle=" + minIdle +
- ", maxWaitMillis=" + maxWaitMillis +
- ", testOnBorrow=" + testOnBorrow +
- ", testOnReturn=" + testOnReturn +
- ", testWhileIdle=" + testWhileIdle +
- ", numTestsPerEvictionRun=" + numTestsPerEvictionRun +
- ", timeBetweenEvictionRunsMillis=" + timeBetweenEvictionRunsMillis +
- ", minEvictableIdleTimeMillis=" + minEvictableIdleTimeMillis +
- '}';
- }
- }
注:封装对象时一定要注意,在Properties中的每个属性对应在JavaBean中要一一对应,并使用驼峰是命名。
max-total 对应 Java Bean 属性为 maxTotal;password 对应 Java Bean 属性为 password
- @Configuration
- public class RedisConfig {
-
- private static final Logger log = LoggerFactory.getLogger(RedisConfig.class);
-
- // 此处通过构造方法注入了 RedisProperties
- // 也可改成:
- // @Autowired
- // private RedisProperties redis;
- private final RedisProperties redis;
- public RedisConfig(RedisProperties redis) {
- this.redis = redis;
- }
-
- @Bean
- public JedisPool jedisPool() {
- RedisPoolConfigProperties poolConfig = redis.getPoolConfig();
- final JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
- jedisPoolConfig.setMaxTotal(poolConfig.getMaxTotal());
- jedisPoolConfig.setMaxIdle(poolConfig.getMaxIdle());
- jedisPoolConfig.setMaxWaitMillis(poolConfig.getMaxWaitMillis());
- jedisPoolConfig.setMinIdle(poolConfig.getMinIdle());
- jedisPoolConfig.setMinEvictableIdleTimeMillis(poolConfig.getMinEvictableIdleTimeMillis());
- jedisPoolConfig.setNumTestsPerEvictionRun(poolConfig.getNumTestsPerEvictionRun());
- jedisPoolConfig.setTestOnBorrow(poolConfig.getTestOnBorrow());
- jedisPoolConfig.setTestOnReturn(poolConfig.getTestOnReturn());
- jedisPoolConfig.setTestWhileIdle(poolConfig.getTestWhileIdle());
- jedisPoolConfig.setTimeBetweenEvictionRunsMillis(poolConfig.getTimeBetweenEvictionRunsMillis());
- log.info("JedisPoolConfig Initialize ........");
- log.info("JedisPoolConfig Info ........ {}", poolConfig);
- String host = redis.getHost();
- String password = redis.getPassword();
- int port = redis.getPort();
- int timeout = redis.getTimeout();
- final JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
- log.info("JedisPool Initialize ........");
- log.info("redis address---> {}:{}", host, port);
- return jedisPool;
- }
- }
至此,JedisPool已经纳入了Spring中,如果中间有错误,细心检查一下。 :-)
- public interface JedisClient {
-
- /**
- * 将字符串值 value 关联到 key
- */
- void set(String key, String value);
-
- /**
- * 返回 key 所关联的字符串值。
- * 如果 key 不存在那么返回特殊值 nil 。
- * 假如 key 储存的值不是字符串类型,返回一个错误,因为 GET 只能用于处理字符串值。
- */
- String get(String key);
-
- /**
- * 检查给定 key 是否存在。
- */
- Boolean exists(String key);
-
- /**
- * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
- * 单位:秒
- */
- void expire(String key, int seconds);
-
- /**
- * 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
- */
- Long ttl(String key);
-
- /**
- * 将 key 中储存的数字值增一。
- * 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
- */
- Long incr(String key);
-
- /**
- * 将 key 中储存的数字值减一。
- * 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。
- * 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
- */
- Long decr(String key);
-
- /**
- * 将哈希表 key 中的域 field 的值设为 value 。
- * 如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。
- * 如果域 field 已经存在于哈希表中,旧值将被覆盖。
- */
- Long hset(String key, String field, String value);
-
- /**
- * 返回哈希表 key 中给定域 field 的值。
- */
- String hget(String key, String field);
-
- /**
- * 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
- */
- Long hdel(String key, String... field);
-
- /**
- * 查看哈希表 key 中,给定域 field 是否存在。
- */
- Boolean hexists(String key, String field);
-
- /**
- * 返回哈希表 key 中所有域的值。
- */
- List<String> hvals(String key);
-
- /**
- * 删除给定的一个 key 。
- */
- Long del(String key);
-
- /**
- * 存储数据到缓存中,并制定过期时间和当Key存在时是否覆盖。
- * @param nxxx 值只能取NX或者XX,如果取NX,则只有当key不存在是才进行set,如果取XX,则只有当key已经存在时才进行set
- * @param expx expx的值只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒。
- * @param time 过期时间,单位是expx所代表的单位。
- */
- String set(String key, String value, String nxxx, String expx, long time);
-
- /**
- * redis 脚本扩展器
- */
- Object eval(String script, List<String> keys, List<String> args);
-
- /**
- * 将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。
- * 如果 key 已经存在, SETEX 命令将覆写旧值。
- * 原子性(atomic)操作,关联值和设置生存时间两个动作会在同一时间内完成
- * @param seconds 以秒为单位
- */
- boolean setex(String key, String value, int seconds);
-
- /**
- * 订阅一个或多个符合给定模式的频道。
- * 每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等),
- * news.* 匹配所有以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类。
- */
- <T extends JedisPubSub> void psubscribe(T jedisPubSub, String... patterns);
- }
- /**
- * Redis实现
- */
- @Configuration
- public class JedisClientPool implements JedisClient {
-
- private final JedisPool jedisPool;
-
- private static final Logger logger = LoggerFactory.getLogger(JedisClientPool.class);
-
- @Autowired
- public JedisClientPool(JedisPool jedisPool) {
- this.jedisPool = jedisPool;
- }
-
- @Override
- public void set(String key, String value) {
- Jedis jedis = jedisPool.getResource();
- jedis.set(key, value);
- jedis.close();
- }
-
- @Override
- public String get(String key) {
- Jedis jedis = jedisPool.getResource();
- String result = jedis.get(key);
- jedis.close();
- return result;
- }
-
- @Override
- public Boolean exists(String key) {
- Jedis jedis = jedisPool.getResource();
- Boolean result = jedis.exists(key);
- jedis.close();
- return result;
- }
-
- @Override
- public void expire(String key, int seconds) {
- Jedis jedis = jedisPool.getResource();
- jedis.expire(key, seconds);
- jedis.close();
- }
-
- @Override
- public Long ttl(String key) {
- Jedis jedis = jedisPool.getResource();
- Long result = jedis.ttl(key);
- jedis.close();
- return result;
- }
-
- @Override
- public Long incr(String key) {
- Jedis jedis = jedisPool.getResource();
- Long result = jedis.incr(key);
- jedis.close();
- return result;
- }
-
- @Override
- public Long decr(String key) {
- Jedis jedis = jedisPool.getResource();
- Long result = jedis.decr(key);
- jedis.close();
- return result;
- }
-
- @Override
- public Long hset(String key, String field, String value) {
- Jedis jedis = jedisPool.getResource();
- Long result = jedis.hset(key, field, value);
- jedis.close();
- return result;
- }
-
- @Override
- public String hget(String key, String field) {
- Jedis jedis = jedisPool.getResource();
- String result = jedis.hget(key, field);
- jedis.close();
- return result;
- }
-
- @Override
- public Long hdel(String key, String... field) {
- Jedis jedis = jedisPool.getResource();
- Long result = jedis.hdel(key, field);
- jedis.close();
- return result;
- }
-
- @Override
- public Boolean hexists(String key, String field) {
- Jedis jedis = jedisPool.getResource();
- Boolean result = jedis.hexists(key, field);
- jedis.close();
- return result;
- }
-
- @Override
- public List<String> hvals(String key) {
- Jedis jedis = jedisPool.getResource();
- List<String> result = jedis.hvals(key);
- jedis.close();
- return result;
- }
-
- @Override
- public Long del(String key) {
- Jedis jedis = jedisPool.getResource();
- Long result = jedis.del(key);
- jedis.close();
- return result;
- }
-
- @Override
- public String set(String key, String value, String nxxx, String expx, long time) {
- Jedis jedis = jedisPool.getResource();
- String result = jedis.set(key, value, nxxx, expx, time);
- jedis.close();
- return result;
- }
-
- @Override
- public Object eval(String script, List<String> keys, List<String> args) {
- Jedis jedis = jedisPool.getResource();
- Object result = jedis.eval(script, keys, args);
- jedis.close();
- return result;
- }
-
- @Override
- public boolean setex(String key, String value, int seconds) {
- Jedis jedis = jedisPool.getResource();
- String result = jedis.setex(key, seconds, value);
- jedis.close();
- return "ok".equalsIgnoreCase(result);
- }
-
- @Override
- public <T extends JedisPubSub> void psubscribe(T jedisPubSub, String... patterns) {
- Jedis jedis = jedisPool.getResource();
- String parameter = "notify-keyspace-events";
- List<String> notify = jedis.configGet(parameter);
- if(StringUtils.isBlank(notify.get(1))) {
- logger.info("重新设置过期事件 -->"+parameter);
- // 过期事件
- jedis.configSet(parameter, "Ex");
- }
- jedis.psubscribe(jedisPubSub, patterns);
- jedis.close();
- }
- }
至此,所有流程OK,测试一下~
- @RunWith(SpringRunner.class)
- @SpringBootTest
- public class ZjH5ApplicationTests {
-
- @Autowired
- private JedisClient jedis;
-
- @Test
- public void contextLoads() {
- jedis.set("test..........", String.valueOf(System.currentTimeMillis()));
- }
-
- }

测试OK,可以开心的撸代码啦~~~
注:如果流程中出现什么问题记得耐心的查看日志。