SpringBoot整合Redis 之 lettuce #私藏项目实操分享#
Posted 梁云亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot整合Redis 之 lettuce #私藏项目实操分享#相关的知识,希望对你有一定的参考价值。
功能说明
SpringBoot2.2.6整合Redis,实现
- 对Redis各种类型数据的操作
- 业务层查改删缓存的管理
代码下载地址:<a rel="nofollow" href="https://github.com/hcitlife/IntegrateRedis">代码</a>
第一步:创建项目
maven依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!-- 解决java8新日期API反序列化异常:com.fasterxml.jackson.databind.exc.InvalidDefinitionException-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.1</version>
</dependency>
<!--redis默认使用的Lettuce客户端-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--使用默认的Lettuce时,若配置spring.redis.lettuce.pool则必须配置该依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
application.yml
server:
port: 80
servlet:
context-path: /ir
spring:
redis:
database: 0
host: 172.16.85.140
port: 6379
password: 1234
timeout: 10000ms # 超时时间
lettuce:
pool:
max-idle: 8 # 最大空闲连接数,默认值为8
max-wait: -1ms # 最大连接阻塞等待时间,默认值-1
min-idle: 2 # 最小空闲连接数
max-active: 20 #最大连接数
第二步:Redis配置文件
@Configuration
//继承CachingConfigurerSupport,为了自定义生成KEY的策略,可以不继承。
public class RedisConfig extends CachingConfigurerSupport
private Duration timeToLive = Duration.ofDays(1); //过期时间1天
private StringRedisSerializer keySerializer = new StringRedisSerializer();
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
private Jackson2JsonRedisSerializer valueSerializer = new
Jackson2JsonRedisSerializer(Dept.class);
//解决缓存转换异常的问题
ObjectMapper objectMapper = new ObjectMapper();
//下面两行解决Java8新日期API序列化问题
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
//设置所有访问权限以及所有的实际类型都可序列化和反序列化
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
valueSerializer.setObjectMapper(objectMapper);
System.out.println("--------------------");
@Bean(name = "cacheManager")
public RedisCacheManager cacheManager(RedisConnectionFactory factory)
// 配置序列化(解决乱码的问题),通过config对象对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(this.timeToLive)// 设置缓存的默认过期时间
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
.disableCachingNullValues();// 不缓存空值
//缓存配置
Map<String,RedisCacheConfiguration> cacheConfig=new HashMap<>();
//自定义缓存名,后面使用的@Cacheable的CacheName
cacheConfig.put("dept",config);
//根据redis缓存配置和reid连接工厂生成redis缓存管理器
RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.withInitialCacheConfigurations(cacheConfig)
.build();
return redisCacheManager;
//缓存键自动生成器
@Override
@Bean(name = "myKeyGen")
public KeyGenerator keyGenerator() //设置自定义keyClassName + methodName + params
return (target, method, params) ->
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
sb.append(method.getName());
sb.append("(");
for (int i = 0; i < params.length; i++)
sb.append(params[i].toString());
if (i != (params.length - 1))
sb.append(",");
sb.append(")");
return sb.toString();
;
//自定义keyGenerator,Key生成器
@Bean(name = "updateByIdKeyGen")
public KeyGenerator updateByIdkeyGenerator()
return (target, method, params) ->
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
sb.append("findDeptByDeptno(");
try
Field id = params[0].getClass().getDeclaredField("deptno");
id.setAccessible(true);
sb.append(id.get(params[0]).toString());
catch (IllegalAccessException e)
e.printStackTrace();
catch (NoSuchFieldException e)
e.printStackTrace();
sb.append(")");
return sb.toString();
;
//自定义keyGenerator,Key生成器
@Bean(name = "deleteByIdKeyGen")
public KeyGenerator deleteByIdkeyGenerator()
return (target, method, params) ->
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
sb.append("findDeptByDeptno(");
for (int i = 0; i < params.length; i++)
sb.append(params[i].toString());
if (i != (params.length - 1))
sb.append(",");
sb.append(")");
return sb.toString();
;
/**
* @param factory
* @return
*/
@Bean(name = "redisTemplate")
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory)
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
//配置连接工厂
redisTemplate.setConnectionFactory(factory);
//设置key的序列化规则
redisTemplate.setKeySerializer(keySerializer);
// hash的key也采用String的序列化方式
redisTemplate.setHashKeySerializer(keySerializer);
//设置value的序列化规则
redisTemplate.setValueSerializer(valueSerializer);
// hash的value序列化方式采用jackson
redisTemplate.setHashValueSerializer(valueSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
在SpringBoot2.0之后,spring容器自动的生成了StringRedisTemplate和RedisTemplate<Object,Object>,可以直接注入。但是在实际使用中,大多情况下不会直接使用RedisTemplate<Object,Object>,而是会对key和value进行序列化,所以我们还需要新增一个配置类。
第三步:Redis工具类
第四步:实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Dept implements Serializable
private static final long serialVersionUID = -1092294594385392402L;
private Integer deptno;
private String dname;
private String loc;
第五步:Service 接口及实现类:
DeptService.java
public interface DeptService
Dept findDeptByDeptno(Integer deptno);
Dept updateDept(Dept dept);
Dept deleteDeptByDeptno(Integer deptno);
DeptServiceImpl.java
@Service
@CacheConfig(cacheManager = "cacheManager", cacheNames = "dept")
public class DeptServiceImpl implements DeptService
@Override
@Cacheable(keyGenerator = "myKeyGen")
public Dept findDeptByDeptno(Integer deptno)
System.out.println("DeptService findDeptByDeptno ...");
return new Dept(10, "aa", "aaaaaaa");
@CachePut(keyGenerator = "updateByIdKeyGen")
@Override
public Dept updateDept(Dept dept)
System.out.println("DeptService updateDept ...");
return new Dept(10, "123", "rewrweq");
@CacheEvict(keyGenerator = "deleteByIdKeyGen")
@Override
public Dept deleteDeptByDeptno(Integer deptno)
System.out.println("DeptService deleteDeptByDeptno ...");
return new Dept(10, "aa", "aaaaaaa");
第六步:Controller层:
@RestController
@RequestMapping("/redis")
public class DemoController
@Autowired
private RedisUtil redisUtil;
//http://localhost:8080/redis/setStr?key=ab&value=aaabbb
@RequestMapping("/setStr")
public String setStr(String key, String value)
redisUtil.set(key, value);
return "success";
//http://localhost:8080/redis/getStr?key=ab
@RequestMapping("/getStr")
public Object getStr(String key)
return redisUtil.get(key);
//http://localhost:8080/redis/setList?key=abc&value1=aa&value2=bb&value3=cc
@RequestMapping("/setList")
public String setList(String key, String value1, String value2, String value3)
List<String> list = new ArrayList<>();
list.add(value1);
list.add(value2);
list.add(value3);
redisUtil.lSets(key, Collections.singletonList(list));
return "success";
@Resource
private DeptService deptService;
@RequestMapping("/findDeptByDeptno/deptno")
public Dept getEmpByEmpno(@PathVariable("deptno") int deptno)
return deptService.findDeptByDeptno(deptno);
测试
运行程序,在网页中进行测试。
DeptService测试
@RunWith(SpringRunner.class)
@SpringBootTest
class DeptServiceImplTest
@Resource
private DeptService deptService;
@Test
void findDeptByDeptno()
Dept dept = deptService.findDeptByDeptno(10);
System.out.println(dept);
@Test
void updateDept()
Dept dept0 = new Dept(10,"abc","cba");
Dept dept = deptService.updateDept(dept0);
System.out.println(dept);
@Test
void deleteDeptByDeptno()
Dept dept = deptService.deleteDeptByDeptno(10);
System.out.println(dept);
以上是关于SpringBoot整合Redis 之 lettuce #私藏项目实操分享#的主要内容,如果未能解决你的问题,请参考以下文章