背景:手下新人在初次使用springboot整合redis,大部分人习惯从网上检索到一份配置,然后不知其所以然的复制粘贴到项目中,网上搜索到的配置良莠不齐但又万变不离其宗。由于springboot最大化地简化了整合redis需要的配置,在用户只需要在配置文件(application.*)中配置少量参数就可以使用官方默认提供的RedisTemplate和StringRedisTemplate来操作redis。由于官方提供的*RedisTemplate提供的功能有限,难以针对java的复杂数据类型进行序列化,且采用直连的方式以及没有对连接数进行限制等诸多因素在现代引用中制约较大,所以项目中一般需要提供一个RedisConfig类来针对redisTemplate做进一步配置。在此把自己之前项目中用到的一份基于redis的配置和封装类贴出来,以便抛砖引玉!
下面开始编码:
1、新建一个springboot项目,pom.xml做如下依赖,注意jedis版本与spring-boot-starter-data-redis版本对应,一般来说2.1.x对应jedis 2.9.x,2.2.x对应jedis 3.x,切记,否则可能出现莫名其妙的错误。
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.1.RELEASE
thinking-in-spring-boot
first-app-by-gui
0.0.1-SNAPSHOT
first-app-by-gui
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-redis
redis.clients
jedis
3.2.0
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
新建的项目结构如下:
2、在application.yml配置文件中新增关于redis配置,内容如下:
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
password: # 如果未单独配置默认为空即可
timeout: 1000
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
3、编写redis配置类,内容如下,在该类中完成Jedis池、Redis连接和RedisTemplate序列化三个配置完成springboot整合redis的进一步配置。其中RedisTemplate对key和value的序列化类,各人结合自己项目情况进行选择即可。
package com.dongnao.config;
import com.dongnao.cache.IGlobalCache;
import com.dongnao.cache.impl.AppRedisCacheManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
@EnableCaching
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.database}")
private Integer database;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.password}")
private String pwd;
@Primary
@Bean(name = "jedisPoolConfig")
@ConfigurationProperties(prefix = "spring.redis.pool")
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxWaitMillis(10000);
return jedisPoolConfig;
}
@Bean
public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setDatabase(database);
redisStandaloneConfiguration.setPassword(pwd);
redisStandaloneConfiguration.setPort(port);
JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
jpcb.poolConfig(jedisPoolConfig);
JedisClientConfiguration jedisClientConfiguration = jpcb.build();
return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
}
/**
* 配置redisTemplate针对不同key和value场景下不同序列化的方式
*
* @param factory Redis连接工厂
* @return
*/
@Primary
@Bean(name = "redisTemplate")
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate<>();
template.setConnectionFactory(factory);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer(Object.class);
template.setValueSerializer(redisSerializer);
template.setHashValueSerializer(redisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
IGlobalCache cache(RedisTemplate redisTemplate) {
return new AppRedisCacheManager(redisTemplate);
}
}
4、网络上大部分配置都到此为止,但在实际使用redis缓存的场景,一般由于redisTemplate使用不便、需要解决将java数据类型和redis六种数据结构命令的对应以及不应该直接暴露redisTemplate给service等因素考虑,需要进行进一步对redisTemplate进行封装,封装后代码如下:
package com.dongnao.cache;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 系统全局Cache接口,具体缓存方式需要实现该接口
*
* @author YuXD
* @date 2021-01-05 10:38
* @since v1.0
*/
public interface IGlobalCache {
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
boolean expire(String key, long time);
/**
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
long getExpire(String key);
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
boolean hasKey(String key);
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
void del(String... key);
// ============================String=============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
Object get(String key);
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
boolean set(String key, Object value);
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
boolean set(String key, Object value, long time);
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
long incr(String key, long delta);
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
long decr(String key, long delta);
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
Object hget(String key, String item);
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
Map
package com.dongnao.cache.impl;
import com.dongnao.cache.IGlobalCache;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @description: 移动端Redis缓存实现类
* @author: YuXD
* @create: 2021-01-05 10:40
**/
@Getter
@AllArgsConstructor
public final class AppRedisCacheManager implements IGlobalCache {
private RedisTemplate redisTemplate;
@Override
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
@Override
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
@Override
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
@Override
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
@Override
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
@Override
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
@Override
public Map hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
@Override
public boolean hmset(String key, Map map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean hmset(String key, Map map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
@Override
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
@Override
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
@Override
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
@Override
public Set sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public List lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public boolean lSetAll(String key, List value) {
try {
redisTemplate.opsForList().leftPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().leftPushIfPresent(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().leftPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean lSetAll(String key, List value, long time) {
try {
redisTemplate.opsForList().leftPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean rSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean rSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean rSetAll(String key, List value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean rSetAll(String key, List value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public void rangeRemove(String key, Long stard, Long end) {
try {
redisTemplate.opsForList().trim(key, stard, end);
} catch (Exception e) {
e.printStackTrace();
}
}
}
5、下面是简单使用的例子,其它结合实际情况使用即可。
package com.dongnao;
import com.dongnao.cache.IGlobalCache;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class FirstAppByGuiApplicationTests {
@Autowired
private IGlobalCache globalCache;
@Test
public void test() {
globalCache.set("key2", "value3");
globalCache.lSetAll("list", Arrays.asList("hello", "redis"));
List list = globalCache.lGet("list", 0, -1);
System.out.println(globalCache.get("key2"));
}
}
以上,完了!
博客整理不易,路过的小伙伴点赞评论下~