mybatis+springboot整合redis实现缓存查询(解决@Cacheable默认为二进制格式)
程序员文章站
2022-05-21 14:37:54
...
1.导入依赖
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--mybatis起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--返回json字符窜的支持 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
#添加项目名
server.servlet.context-path=/redis
server.port=80
#数据库连接信息(useUnicode=true&characterEncoding=UTF-8不加中文查询不到)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.password=root
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/cloud?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
#配置mybatis
#别名扫描包
mybatis.type-aliases-package=com.dxf.redis.pojo
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
#redis配置
#Redis服务器地址
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
spring.redis.password=myroot
#Redis数据库索引(默认为0)
spring.redis.database=0
#连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=50
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=3000
#连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=20
#连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=2
#连接超时时间(毫秒)
spring.redis.timeout=5000
logging.level.com.dxf.redis.mapper:debug
2.RedisConfig
在此省略mapper和实体类
//注意实体类实现序列化
public class User implements Serializable {
@Configuration
@EnableCaching //开启spring缓存注解
public class RedisConfig extends CachingConfigurerSupport {
/**
* 自定义生成key的规则
*/
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
//格式化缓存key字符串
StringBuilder sb = new StringBuilder();
//追加类名
sb.append(o.getClass().getName());
//追加方法名
sb.append(method.getName());
//遍历参数并且追加
for (Object obj : objects) {
sb.append(obj.toString());
}
System.out.println("调用Redis缓存Key : " + sb.toString());
return sb.toString();
}
};
}
/**
* @Description: 使用@Cacheable注解的时候会将返回的对象缓存起来,默认缓存的值是二进制的,
* 为此我们自定义序列化配置,改成JSON格式的
* @Auther: dxf
* @Date: 20:31 2020/5/20
*/
@Bean
public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))// 设置缓存有效期一小时
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
/**
*自己的RedisTemplate
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(factory);
//序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);过时
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
3.UserServiceImpl
几个关键注解
1,@Cacheable
标注在方法上, 将方法返回的结果存入缓存中
可以指定 cachename 或 value 来对 ConcurrentMapCache 的 name 属性进行设置
也可以通过指定 keyGenerator 来制定缓存键值对中生成 key 的规则
默认情况: name 为传入的参数, 键值对中的值为方法返回结果
2,@CachePut
标注在方法上, 先执行方法, 再用方法返回的值来更新缓存内容
3,@CacheEvict
清除缓存
4,@Caching
复杂的 cache 配置, 可以在里面配置上面的几个注解
5,@CacheConfig
标注在类上, 对类中的缓存操作作统一配置
@Service
public class UserServiceImpl implements UserService {
@Resource
UserMapper userMapper;
@Cacheable(value = "user")
@Override
public User getUserById(Integer id) {
return userMapper.selectByPrimaryKey(id);
}
@Override
public int insUser(User user) {
return userMapper.insertSelective(user);
}
@CacheEvict(value = "user",allEntries = true)
@Override
public int delUserById(Integer id) {
return userMapper.deleteByPrimaryKey(id);
}
@CacheEvict(value = "user",allEntries = true)
@Override
public int updUser(User user) {
return userMapper.updateByPrimaryKeySelective(user);
}
}
成功
查询已删除内容
4.修改版
//@Cacheable(value = "user")
@Cacheable(value = "user_details", key = "#id", unless="#result == null")
@Override
public User getUserById(Integer id) {
return userMapper.selectByPrimaryKey(id);
}
//@CacheEvict(value = "user",allEntries = true)
@CacheEvict(value = "user_details", key = "#id")
@Override
public int delUserById(Integer id) {
return userMapper.deleteByPrimaryKey(id);
}
//@CacheEvict(value = "user",allEntries = true)
@CachePut(value = "user_details", key = "#user.id")
@Override
public User updUser(User user) {
if(userMapper.updateByPrimaryKeySelective(user)> 0) {
//返回user填入缓存
return userMapper.selectByPrimaryKey(user.getId());
}else{
return null;
}
}
上一篇: Python编码和Unicode
下一篇: 从0自学C#10--在线绘制类图