引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--处理Java8 日期类型-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
- @Cacheable : 用于查询
- @CacheEvict : allEntries 这个注解的特有属性。如果触发该注解解,会清空该类型(value) 下的所有缓存。默认为false, 若要使用需要设为true。不能与key共存。
- @CachePut:用来接收方法的返回值,并将其添加到缓存。(不常用)
属性:
- value:指明缓存的类型。
- key:用于标记某次缓存,一般通过id标记,查询条件标记。删除缓存时,通过标记去删除。
- conditon:是否缓存的判断条件,可以用来指明查询结果为null时不缓存。
- unless:与condition相反。
注意:主类上添加 @EnableCaching 注解,开启缓存
配置类
用于处理返回前端的数据,序列化和反序列化的格式
public class JacksonObjectMapper extends ObjectMapper {
@Serial
private static final long serialVersionUID = 2220067913562288238L;
public static final String DATE_TIME_FORMATTER= "yyyy-MM-dd HH:mm:ss";
public static final String TIME_FORMATTER= "HH:mm:ss";
public static final String DATE_FORMATTER= "yyyy-MM-dd";
public JacksonObjectMapper() {
this.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
this.setSerializationInclusion(JsonInclude.Include.ALWAYS);
this.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,true);
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
this.configure(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS,false);
this.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,false);
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
this.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
SimpleModule simpleModule = new SimpleModule()
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMATTER)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FORMATTER)))
//防止Long类型在前端精度缺失
.addSerializer(Long.class, new ToStringSerializer())
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMATTER)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_FORMATTER)));
this.registerModule(simpleModule);
}
}
配置类
扩展转换器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(new JacksonObjectMapper());
converters.add(0,converter);
}
}
配置类
利用redis进行缓存时,对数据进行序列化,解决乱码。
Configuration
public class RedisConfig extends CachingConfigurerSupport{
@Bean
@Primary
public GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer(){
ObjectMapper om = new ObjectMapper();
// 解决查询缓存转换异常的问题
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 将类的信息随数据存入Redis,在反序列化时,恢复对象信息。
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 支持 jdk 1.8 日期 ---- start ---
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
om.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.registerModule(new ParameterNamesModule());
// --end --
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
return genericJackson2JsonRedisSerializer;
}
/**
* 对redisTemplate 进行Json序列化
* @param factory
* @return
*/
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory,GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
return redisTemplate;
}
/**
* 对redis缓存管理器进行配置
* 主要作用于缓存得统一管理,搭配 @Cacheable注解使用
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory,GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30)) // 配置缓存时长
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
接口类
注意:key的书写格式,双引号内部的是变量,再加个单引号才能表示字符串。
通过#,可以获得参数的信息。
@RestController
@RequestMapping("/wuxia")
public class UserController {
@Resource
private WuXiaService wuXiaService;
/**
* 缓存整个列表的数据
* @return
*/
@Cacheable(value = "wuxia",key = "'wuxiaList'")
@GetMapping
public Result list(){
return Result.ok(wuXiaService.list());
}
/**
* 缓存该id对应的数据到redis
* @param id
* @return
*/
@Cacheable(value = "wuxia",key = "'wuxia'+'_'+#id")
@GetMapping("/{id}")
public Result getWuxiaById(@PathVariable("id") Integer id){
return Result.ok(wuXiaService.getById(id));
}
/**
* 有数据修改时,就会删除这个分组的所有缓存,防止list出现假数据
* @param wuXia
* @return
*/
@CacheEvict(value = "wuxia",allEntries = true)
@PutMapping
public Result updateById(@RequestBody WuXia wuXia){
wuXiaService.updateById(wuXia);
return Result.ok("更新成功");
}
/**
* 有数据删除时,就会删除这个分组的所有缓存,防止list出现假数据
* @param id
* @return
*/
@CacheEvict(value = "wuxia",allEntries = true)
@DeleteMapping("/{id}")
public Result deleteById(@PathVariable("id") Integer id){
wuXiaService.removeById(id);
return Result.ok("删除成功");
}
}
测试类
@SpringBootTest
public class CacheAppTest {
@Resource
private WuXiaService wuXiaService;
@Test
public void testSelect(){
wuXiaService.list().forEach(System.out::println);
}
@Resource
private RedisTemplate redisTemplate;
@Test
public void testRedis(){
redisTemplate.opsForValue().set("age","23");
System.out.println(redisTemplate.opsForValue().get("age"));
}
@Resource
RestTemplate restTemplate;
@Test
public void testList(){
Object object = restTemplate.getForObject("http://localhost:8080/wuxia", Object.class);
System.out.println(object);
}
@Test
public void testSelectById(){
ResponseEntity<Object> forEntity = restTemplate.getForEntity("http://localhost:8080/wuxia/3", Object.class);
System.out.println(forEntity.getBody());
}
@Test
public void testUpdateById(){
HashMap<String, Object> map = new HashMap<>();
map.put("id",1);
map.put("name","lisi");
map.put("age",14);
map.put("inSchoolTime",LocalDate.now().plusDays(1));
restTemplate.put("http://localhost:8080/wuxia",map);
}
@Test
public void testDeleteById(){
restTemplate.delete("http://localhost:8080/wuxia/2");
}
}