SpringBoot+Mybatis+Redis 实现缓存
2019-07-31 本文已影响195人
盼旺
环境版本
Mysql-8.0
springboot-2.1.6
jdk-1.8
1.新建项目
新建项目2.采用mybatis-generator自动生成mapper,dao,entity
链接:https://www.jianshu.com/p/b519e9ef605f
3.首先实现springboot+mybatis
链接:https://www.jianshu.com/p/16f910aa4cf4
4.先安装redis数据库
Linux下和Win10下:https://www.jianshu.com/p/1299f5754d74
5.项目中配置redis
1.添加redis的properties的配置
# ==============================
# redis configurations
# ==============================
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
# Redis数据库索引(默认为0)
spring.redis.database=0
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
添加依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.Redis Java配置(RedisConfig.java)
package com.wglvzyx.mybatisredis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.*;
/**
* @description redis配置 配置序列化方式以及缓存管理器
*/
@EnableCaching // 开启缓存
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport {
/**
* 配置自定义redisTemplate
*
* @param connectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setValueSerializer(jackson2JsonRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* json序列化
* @return
*/
@Bean
public RedisSerializer<Object> jackson2JsonRedisSerializer() {
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
return serializer;
}
/**
* 缓存管理器配置
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存的默认过期时间,也是使用Duration设置
config = config.entryTtl(Duration.ofMinutes(1))
// 设置 key为string序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
// 设置value为json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
// 不缓存空值
.disableCachingNullValues();
// 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("timeGroup");
cacheNames.add("user");
// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("timeGroup", config);
configMap.put("user", config.entryTtl(Duration.ofSeconds(120)));
// 使用自定义的缓存配置初始化一个cacheManager
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
// 一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
/**
* 缓存的key是 包名+方法名+参数列表
*/
@Bean
public KeyGenerator keyGenerator() {
return (target, method, objects) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append("::" + method.getName() + ":");
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString();
};
}
}
3.介绍缓存注解
- 常用的缓存注解
@Cacheable – 表明对应方法的返回结果可以被缓存,首次调用后,下次就从缓存中读取结果,方法不会再被执行了。
@CachePut – 更新缓存,方法每次都会执行
@CacheEvict – 清除缓存,方法每次都会执行
...等等
因为主要的业务逻辑在服务层实现,一般会把缓存注解加在服务层的方法上。
4.缓存举例子
-
序列化实体类
Student
implements Serializable
-
在StudentService服务类中,给查询单个学生方法添加
@Cacheable
注解
表示:方法的返回结果会被缓存到redis
//key 是学生id value 是学生这个实体
@Cacheable(key = "#stuid", value = "Student")
public Student SelectOneStuById(int stuid){
return studentMapper.selectByPrimaryKey(stuid);
}
- 在StudentService服务类中,给更改单个学生信息方法添加
@CacheEvict
注解
表示:原始数据被更新了,废弃缓存数据
@CacheEvict(key = "#stuid", value = "Student")
public Student updateStuName(int stuid, String stuname) {
Student oldstu = studentMapper.selectByPrimaryKey(stuid);
oldstu.setUsername(stuname);
int f = studentMapper.updateByPrimaryKey(oldstu);
return oldstu;
}
控制器中添加俩个访问地址来测试
// 读取学生信息,测试缓存使用:除了首次读取,接下来都应该从缓存中读取
@RequestMapping(value="{id}")
@ResponseBody
public Student getStu(@PathVariable long id){
System.out.println(id);
Student onestu = studentService.SelectOneStuById((int) id);
return onestu;
}
/***************************'或者'*****************************/
// 读取学生信息,测试缓存使用:除了首次读取,接下来都应该从缓存中读取
//用http://localhost:8080/GetOneStu?uid=1访问
@GetMapping(value="/GetOneStu")
@ResponseBody
public Student getOneStu(String uid){
int id = Integer.parseInt(uid);
System.out.println(id);
Student onestu = studentService.SelectOneStuById(id);
return onestu;
}
/****************************************************************/
// 更新学生信息
@RequestMapping(value="{id}/wgname")
@ResponseBody
public Student UpdateStu(@PathVariable long id){
System.out.println(id);
String name = "ceshi";
Student onestu = studentService.updateStuName((int) id,name);
return onestu;
}
5.运行测试
监控redis服务器,打开redis-cli.exe
,然后使用monitor
命令开始监控:
获取用户信息
修改用户信息
6.使用RedisTemplate访问redis服务器
- 在控制层添加访问路径
//@Resource的作用相当于@Autowired,只不过@Autowired按byType(按类型)自动注入,而@Resource默认按 byName(按名称)自动注入罢了
@Resource(name = "redisTemplate")
RedisTemplate<String,Object> redis;
// 使用RedisTemplate访问redis服务器
@RequestMapping(value="/redis", method=RequestMethod.GET, produces="application/json")
@ResponseBody
public String redis() throws Exception {
// 设置键"ceshi-key=wg",值"ceshi-value=zyx"
redis.opsForValue().set("ceshi-key=wg", "ceshi-value=zyx");
String value = (String) redis.opsForValue().get("ceshi-key=wg");
return value;
}
在软件Postman中测试
redis数据库存入了指定的键值对
- RedisTemplate常用方法
//向redis里存入数据和设置缓存时间
wgRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);
//value做-1操作
wgRedisTemplate.boundValueOps("test").increment(-1);
//根据key获取缓存中的value
wgRedisTemplate.opsForValue().get("test")
//value做+1操作
wgRedisTemplate.boundValueOps("test").increment(1);
//根据key获取过期时间
wgRedisTemplate.getExpire("test")
//根据key获取过期时间并换算成指定单位
wgRedisTemplate.getExpire("test",TimeUnit.SECONDS)
//根据key删除缓存
wgRedisTemplate.delete("test");
//检查key是否存在,返回boolean值
wgRedisTemplate.hasKey("546545");
//向指定key中存放set集合
wgRedisTemplate.opsForSet().add("red_123", "1","2","3");
//设置过期时间
wgRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS);
//根据key查看集合中是否存在指定数据
wgRedisTemplate.opsForSet().isMember("red_123", "1")
//根据key获取set集合
wgRedisTemplate.opsForSet().members("red_123");