博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Springboot2.1.3 + redis 实现 cache序列化乱码问题
阅读量:5990 次
发布时间:2019-06-20

本文共 10130 字,大约阅读时间需要 33 分钟。

redis安装

systemctl start docker

docker pull registry.docker-cn.com/library/redis

查看镜像

docker images

启动

docker run -d -p 6379:6379 --name myredis registry.docker-cn.com/library/redis

代码

/** * @author liwen406 * @Title: MyRedisConfig * @Description: * @date 2019/2/17 / 22:13 */@Configuration@EnableCachingpublic class MyRedisConfig extends CachingConfigurerSupport {    @Bean    public RedisTemplate
empRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate
template = new RedisTemplate
(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer
ser = new Jackson2JsonRedisSerializer
(Employee.class); template.setDefaultSerializer(ser); return template; } @Bean public RedisTemplate
deptRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate
template = new RedisTemplate
(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer
ser = new Jackson2JsonRedisSerializer
(Department.class); template.setDefaultSerializer(ser); return template; } @Bean(name = "redisTemplate") public RedisTemplate
redisTemplate(RedisConnectionFactory factory) { RedisTemplate
template = new RedisTemplate<>(); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); RedisSerializer stringSerializer = new StringRedisSerializer(); template.setKeySerializer(stringSerializer); template.setValueSerializer(stringSerializer); template.setHashKeySerializer(stringSerializer); template.setHashValueSerializer(stringSerializer); template.setConnectionFactory(factory); return template; } @Bean /** cache key generation strategy */ public KeyGenerator KeyGenerator() { 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(); } }; } @Bean /** redis-cache configuration */ public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer
redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化(解决乱码的问题) RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() // 7 天缓存过期 .entryTtl(Duration.ofDays(7)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; }}

Springboot2.1.3 + redis 实现 cache序列化乱码问题

老师笔记留给自己以后查找方便:

import com.atguigu.cache.bean.Employee;import com.atguigu.cache.mapper.EmployeeMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.*;import org.springframework.stereotype.Service;@CacheConfig(cacheNames="emp"/*,cacheManager = "employeeCacheManager"*/) //抽取缓存的公共配置@Servicepublic class EmployeeService {    @Autowired    EmployeeMapper employeeMapper;    /**     * 将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法;     * CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;     *     *     * 原理:     *   1、自动配置类;CacheAutoConfiguration     *   2、缓存的配置类     *   org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration     *   org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】     *   org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration     *   3、哪个配置类默认生效:SimpleCacheConfiguration;     *     *   4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager     *   5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中;     *     *   运行流程:     *   @Cacheable:     *   1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;     *      (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。     *   2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;     *      key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;     *          SimpleKeyGenerator生成key的默认策略;     *                  如果没有参数;key=new SimpleKey();     *                  如果有一个参数:key=参数的值     *                  如果有多个参数:key=new SimpleKey(params);     *   3、没有查到缓存就调用目标方法;     *   4、将目标方法返回的结果,放进缓存中     *     *   @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,     *   如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;     *     *   核心:     *      1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件     *      2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator     *     *     *   几个属性:     *      cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;     *     *      key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值  1-方法的返回值     *              编写SpEL; #i d;参数id的值   #a0  #p0  #root.args[0]     *              getEmp[2]     *     *      keyGenerator:key的生成器;可以自己指定key的生成器的组件id     *              key/keyGenerator:二选一使用;     *     *     *      cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器     *     *      condition:指定符合条件的情况下才缓存;     *              ,condition = "#id>0"     *          condition = "#a0>1":第一个参数的值》1的时候才进行缓存     *     *      unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断     *              unless = "#result == null"     *              unless = "#a0==2":如果第一个参数的值是2,结果不缓存;     *      sync:是否使用异步模式     * @param id     * @return     *     */    @Cacheable(value = {"emp"}/*,keyGenerator = "myKeyGenerator",condition = "#a0>1",unless = "#a0==2"*/)    public Employee getEmp(Integer id){        System.out.println("查询"+id+"号员工");        Employee emp = employeeMapper.getEmpById(id);        return emp;    }    /**     * @CachePut:既调用方法,又更新缓存数据;同步更新缓存     * 修改了数据库的某个数据,同时更新缓存;     * 运行时机:     *  1、先调用目标方法     *  2、将目标方法的结果缓存起来     *     * 测试步骤:     *  1、查询1号员工;查到的结果会放在缓存中;     *          key:1  value:lastName:张三     *  2、以后查询还是之前的结果     *  3、更新1号员工;【lastName:zhangsan;gender:0】     *          将方法的返回值也放进缓存了;     *          key:传入的employee对象  值:返回的employee对象;     *  4、查询1号员工?     *      应该是更新后的员工;     *          key = "#employee.id":使用传入的参数的员工id;     *          key = "#result.id":使用返回后的id     *             @Cacheable的key是不能用#result     *      为什么是没更新前的?【1号员工没有在缓存中更新】     *     */    @CachePut(/*value = "emp",*/key = "#result.id")    public Employee updateEmp(Employee employee){        System.out.println("updateEmp:"+employee);        employeeMapper.updateEmp(employee);        return employee;    }    /**     * @CacheEvict:缓存清除     *  key:指定要清除的数据     *  allEntries = true:指定清除这个缓存中所有的数据     *  beforeInvocation = false:缓存的清除是否在方法之前执行     *      默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除     *     *  beforeInvocation = true:     *      代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除     *     *     */    @CacheEvict(value="emp",beforeInvocation = true/*key = "#id",*/)    public void deleteEmp(Integer id){        System.out.println("deleteEmp:"+id);        //employeeMapper.deleteEmpById(id);        int i = 10/0;    }    // @Caching 定义复杂的缓存规则    @Caching(         cacheable = {             @Cacheable(/*value="emp",*/key = "#lastName")         },         put = {             @CachePut(/*value="emp",*/key = "#result.id"),             @CachePut(/*value="emp",*/key = "#result.email")         }    )    public Employee getEmpByLastName(String lastName){        return employeeMapper.getEmpByLastName(lastName);    }
import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cache.annotation.EnableCaching;/** * 一、搭建基本环境 * 1、导入数据库文件 创建出department和employee表 * 2、创建javaBean封装数据 * 3、整合MyBatis操作数据库 *      1.配置数据源信息 *      2.使用注解版的MyBatis; *          1)、@MapperScan指定需要扫描的mapper接口所在的包 * 二、快速体验缓存 *      步骤: *          1、开启基于注解的缓存 @EnableCaching *          2、标注缓存注解即可 *              @Cacheable *              @CacheEvict *              @CachePut * 默认使用的是ConcurrentMapCacheManager==ConcurrentMapCache;将数据保存在   ConcurrentMap
中 * 开发中使用缓存中间件;redis、memcached、ehcache; * 三、整合redis作为缓存 * Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 * 1、安装redis:使用docker; * 2、引入redis的starter * 3、配置redis * 4、测试缓存 * 原理:CacheManager===Cache 缓存组件来实际给缓存中存取数据 * 1)、引入redis的starter,容器中保存的是 RedisCacheManager; * 2)、RedisCacheManager 帮我们创建 RedisCache 来作为缓存组件;RedisCache通过操作redis缓存数据的 * 3)、默认保存数据 k-v 都是Object;利用序列化保存;如何保存为json * 1、引入了redis的starter,cacheManager变为 RedisCacheManager; * 2、默认创建的 RedisCacheManager 操作redis的时候使用的是 RedisTemplate
* 3、RedisTemplate
是 默认使用jdk的序列化机制 * 4)、自定义CacheManager; * */@MapperScan("com.atguigu.cache.mapper")@SpringBootApplication@EnableCachingpublic class Springboot01CacheApplication { public static void main(String[] args) { SpringApplication.run(Springboot01CacheApplication.class, args); }}

转载于:https://blog.51cto.com/357712148/2351538

你可能感兴趣的文章
(四)整合spring cloud云服务架构 - 企业分布式微服务云架构构建
查看>>
Unity(刚体)
查看>>
构建dubbo分布式平台-dubbo简介
查看>>
前端优化
查看>>
38. SQL -- 自动维护计划和管理表
查看>>
电脑常见小技巧
查看>>
usb安全管理
查看>>
我的友情链接
查看>>
树莓派配置小记1:系统篇
查看>>
HDFS详解
查看>>
linux编程指导
查看>>
正则表达式中的任意字符
查看>>
Open-Falcon安装使用笔记
查看>>
一道有关路由器的实验题 寻找前辈指导
查看>>
项目启动会发言稿(范文一)
查看>>
Linux常用命令
查看>>
对之前用PHP写接口,与APP对接一些问题汇总
查看>>
VMware vSphere 6简单部署---VCSA简单使用
查看>>
春节回家
查看>>
Easy ×××实验
查看>>