1 注解
@EnableCaching
@Cacheable
@CacheEvict
@CachePut
@Caching
@CacheConfig
序号 | 注解 | 描述 |
---|---|---|
1 | EnableCaching | 开启注解缓存 |
2 | CacheConfig | 配置注解公共参数,如cacheNames,keyGenerator |
3 | Cacheable | 注解在类或方法上,目标执行前,根据key先从缓存中查询数据,若有则直接返回,若没有,则将该方法返回值存入缓存value中,即将查询的数据自动放入缓存 |
4 | CachePut | 注解在类或方法上,执行方法后,将方法返回值存入缓存value中 |
5 | CacheEvict | 注解在类或方法上,执行方法后,清除缓存中对应key的数据 |
2 启动配置
启动文件添加注解:@EnableCaching使用
package com.sb;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SpringBootApplication
@MapperScan("com.sb.mapper")
@EnableCaching
public class SbUsageApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application){
return application.sources(SbUsageApplication.class);
}
public static void main(String[] args){
SpringApplication.run(SbUsageApplication.class, args);
}
}
3 服务方法注解
3.1 数据库数据缓存
提取变量字符串使用#(井号)获取变量名称,类似于mybatis中取值#{name},Mapper获取数据库数据。
@CacheConfig(cacheNames=“peopleInfos”)配置全局key前缀,使用Redis客户端获取数据时使用,其中xiaoxiao为name值,标记数据键的后缀。
get peopleInfos::xiaoxiao
package com.sb.service.impl;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import com.sb.service.PeopleInfosService;
import com.sb.mapper.PeopleInfosMapper;
import com.sb.po.PeopleInfos;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@CacheConfig(cacheNames="peopleInfos")
@Service
@Transactional
public class PeopleInfosServiceImpl implements PeopleInfosService{
@Autowired
private PeopleInfosMapper peopleInfosMapper;
static Logger logger = LoggerFactory.getLogger(PeopleInfosServiceImpl.class);
@Override
public List<PeopleInfos> getAllPeopleInfos(){
// List<PeopleInfos> infos = peopleInfosDao.selectAllPeopleInfos();
List<PeopleInfos> infos = peopleInfosMapper.selectAllPeopleInfos();
logger.info("test");
return infos;
}
@Cacheable(key="#name")
@Override
public Map getPeopleInfosByName(String name){
Map tempMap = new HashMap();
List<PeopleInfos> peopleInfos = peopleInfosMapper.selectPeopleInfosByName(name);
tempMap.put("code", 250);
tempMap.put("infos", peopleInfos);
return tempMap;
}
@CacheEvict(key="#name")
@Override
public Map deletePeopleInfosByName(String name){
Map tempMap = new HashMap();
peopleInfosMapper.deletePeopleInfosByName(name);
tempMap.put("code", 200);
tempMap.put("infos", "删除成功");
return tempMap;
}
@CachePut(key="#peopleInfos.name")
@Override
public Map addPeopleInfos(PeopleInfos peopleInfos){
Map tempMap = new HashMap();
peopleInfosMapper.addPeopleInfos(peopleInfos);
tempMap.put("code", 200);
tempMap.put("infos", "添加成功");
tempMap.put("datas", peopleInfos);
return tempMap;
}
}
3.2 普通数据缓存
缓存普通数据,将获取的数据放到缓存中,如token数据,有时间期限,不用随时调用,当数据过期时,再重新获取。
package com.company.web.service.impl;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import com.company.web.util.GetToken;
import com.company.web.po.NatureInfos;
import com.company.web.service.GetTokenService;
@CacheConfig(cacheNames = "natureInfos")
@Service
@Transactional
public class GetTokenServiceImpl implements GetTokenService {
/**
* 缓存数据 在缓存中存储token
*/
@Cacheable(key = "#name")
@Override
public String getTokenFromCache(String name) {
Map returnMap = new HashMap();
GetToken getToken = new GetToken();
String token = getToken.tokenStr();
returnMap.put("token", token);
return token;
}
/**
* 更新token
*/
@CachePut(key = "#name")
@Override
public String getTokenFromAPI(String name) {
GetToken getToken = new GetToken();
String token = getToken.tokenStr();
return token;
}
/**
* 清除缓存数据
*/
@CacheEvict(key = "#name")
@Override
public String clearTokenFromCache(String name) {
return "success";
}
}
3.3 缓存普通数据Impl
package com.company.web.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.company.web.util.GetToken;
import com.company.web.po.NatureInfos;
@Service
@Transactional
public interface GetTokenService {
public String getTokenFromAPI(String name);
public String getTokenFromCache(String name);
public String clearTokenFromCache(String name);
}
4 配置过期时间
使用Redis缓存管理配置缓存过期时间.
package com.sb.config;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import java.io.Serializable;
import java.time.Duration;
import java.lang.reflect.Method;
@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport{
@Bean
public KeyGenerator wiselyKeyGenerator(){
return new KeyGenerator(){
@Override
public Object generate(Object target, Method method, Object... params){
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for(Object obj:params){
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* springboot 2.x Reidis缓存管理,设置缓存过期时间
* @param ConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60));
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory){
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
5 接口
package com.sb.controller;
import com.sb.po.PeopleInfos;
import com.sb.service.PeopleInfosService;
import com.sb.util.TimeGeneratorUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.PathVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/api")
public class PeopleInfosController{
static Logger logger = LoggerFactory.getLogger(PeopleInfosController.class);
@Autowired
private PeopleInfosService peopleInfosService;
@Autowired
private RedisTemplate redisTemplate;
@RequestMapping(value="/get-infos/all", method=RequestMethod.GET)
@ResponseBody
public List<PeopleInfos> getAllInfos(){
List<PeopleInfos> infos = peopleInfosService.getAllPeopleInfos();
return infos;
}
@RequestMapping(value="/add-infos", method=RequestMethod.POST)
@ResponseBody
public Map addPeopleInfos(@RequestBody PeopleInfos peopleInfos){
return peopleInfosService.addPeopleInfos(peopleInfos);
}
@RequestMapping(value="/delete-by-name", method=RequestMethod.POST)
@ResponseBody
public Map deletePeopleInfosByName(@RequestBody PeopleInfos peopleInfos){
// String name = peopleInfos.get("name").toString();
String name = peopleInfos.getName();
return peopleInfosService.deletePeopleInfosByName(name);
}
@RequestMapping(value="/get-infos-by-name", method=RequestMethod.POST)
@ResponseBody
public Map getInfosByName(@RequestBody PeopleInfos peopleInfos){
Map tempMap = new HashMap();
String name = peopleInfos.getName();
boolean hasKey = redisTemplate.hasKey("people1");
logger.info("key:{}", hasKey);
String timeFormat = TimeGeneratorUtil.timeFormatGen("yyyy-MM-dd HH:mm:ss");
tempMap.put("time", timeFormat);
tempMap.put("infos", peopleInfosService.getPeopleInfosByName(name));
return tempMap;
}
@RequestMapping(value = "/token-from-api", method = RequestMethod.GET)
public String getTokenFromAPI(@RequestParam("name") String name) {
String token = getTokenService.getTokenFromAPI(name);
return token;
}
@RequestMapping(value = "/token-from-cache", method = RequestMethod.GET)
public String getTokenFromCache(@RequestParam("name") String name) {
String token = getTokenService.getTokenFromCache(name);
Cache cache = cacheManager.getCache("natureInfos");
System.out.println("cache:" + cache);
System.out.println("token:" + cache.get("123").toString());
return token;
// return cache.get;
}
@RequestMapping(value = "/token-clear", method = RequestMethod.DELETE)
public String clearTokenFromCache(@RequestParam("name") String name) {
String token = getTokenService.clearTokenFromCache(name);
return token;
}
}
6 小结
序号 | 描述 |
---|---|
1 | 启动文件使用注解@EnableCaching开启缓存注解功能 |
2 | 注解在方法上,实现方法返回值:添加到缓存中,从缓存中删除,获取缓存数据 |
3 | 通过Redis缓存管理器配置缓存中数据过期时间,当缓存中数据过期时,获取数据时,先从数据库(MySQL)获取,并将返回值存到缓存中,待获取相同key值时从缓存中获取 |
4 | cacheName和key是为Redis客户端查询数据准备的,通过Springboot将数据存储到缓存中,可以直接从缓存中获取数据,若缓存中没有数据, 则执行函数 |
5 | 过期时间,将缓存中的数据通过Redis持久化到硬盘中,当数据到达存储期限时,从缓存和Redis删除 |
6 | 缓存中可以存储非类的数据,如String |
【参考文献】
[1]https://blog.csdn.net/justry_deng/article/details/89283664
[2]https://www.cnblogs.com/7788IT/p/11626845.html
[3]https://blog.csdn.net/f641385712/article/details/95169002