您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“SpringBoot集成Redis并自定義對象序列化操作的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“SpringBoot集成Redis并自定義對象序列化操作的示例分析”這篇文章吧。
SpringBoot項目使用redis非常簡單,pom里面引入redis的場景啟動器,在啟動類上加@EnableCaching注解,項目啟動會自動匹配上redis,這樣項目中就可以愉快地使用了,
使用方法:要么使用@Cacheable一類的注解自動緩存,要么使用RedisTemplate手動緩存。
(前提是你的本機或者是遠程主機要先搭好redis環境)
雖然SpringBoot好用,但這里也有好多坑,
下面,我將詳細記錄整合步驟
pom文件中引入cache和redis依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
寫好DAO,service,controller,配置文件application.yml中配好數據源和redis地址
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3305/cache username: root password: 123456 redis: host: 127.0.0.1 port: 6379 password: hehuiredis177 mybatis: configuration: map-underscore-to-camel-case: true mapper-locations: - classpath:mybatis/mapper/*.xml debug: true
service類@Cacheable(cacheNames=“employee”)注解
@Service public class EmployeeService { @Autowired private EmployeeDao employeeDao; @Cacheable(cacheNames="employee") public List<Employee> findAll(){ System.out.println("查詢所有員工......"); return employeeDao.findAll(); } @Cacheable(cacheNames="employee--id") public Employee selectEmp(Integer id){ System.out.println("查詢員工:"+id); return employeeDao.selectById(id); } }
項目啟動時,自動配置報告提示Redis已經matched(這里說一下,你如果沒有引入redis而又在啟動類上加了@EnableCaching注解,SpringBoot會自動給你匹配一個SimpleCacheConfiguration緩存,它的底層用了一個key-value的Map,不能像redis一樣持久化,您得注意,好好權衡一下用不用,筆者不建議使用,像SQLite、H2這些一樣,玩具型的,只適合個人博客等非正式場合使用,有輕量級的優點,也有不可靠,不好管理的缺點)
500錯誤,服務端有問題,仔細閱讀報錯信息,是實體類沒有序列化導致的,好吧,那我就實現Serializable接口
是可以了,但這只是巧合,再去訪問,確實可以
去看redis
什么東西啊,看不懂…
但第二次以后確實走了緩存,離成功又近了一步
再去試一下查所有
也可以
緩存也有
去看RedisTemplate這個類
對象默認實現序列化
怎么實現的呢?
接著往下看
默認用的是jdk的序列化機制
所以實現Serializable接口就可以,巧合!!!
redis里這么亂,看不懂,這顯然不是我們想要的,我們要的是json,輕量易讀的json才是我們的目標,欲存json,必須改變序列化機制,把jdk的序列化替換掉
繼續讀源碼
找到RedisAutoConfiguration這個類,看它是怎么自動配置的
里面有個內部類RedisConfiguration
初始化的時候,把RedisTemplate和StringRedisTemplate放在了IOC容器里,也就是說我們可以在我們自己的代碼里注入這兩個類,然后手動緩存
而@Cacheable注解使用的是RedisTemplate,那么分析一下RedisTemplate
@Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); return template; }
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
直接new了一個RedisTemplate然后把它返回,呵呵!就從這里入手
@ConditionalOnMissingBean(name = “redisTemplate”)
表示我們可以自定義RedisTemplate,我們有RedisTemplate,就用我們的,否則就用默認,我們不喜歡你的,要json就要自己配一個RedisTemplate
自己寫
package com.hehui.config; import java.net.UnknownHostException; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; /** * 自定義redis配置 * @author hehui * @date 2019年3月12日 * */ @Configuration public class MyRedisConfig { @Bean public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setDefaultSerializer(serializer); return template; } }
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setDefaultSerializer(serializer);
只多了這兩行代碼,其它什么都沒變。
為什么要用Jackson2JsonRedisSerializer呢?
因為Jackson2JsonRedisSerializer實現了RedisSerializer接口
觀察redis
key是我們要的key,value是我們要的value
再刷新頁面
不會吧!!!
去緩存找,找到了,反序列化失敗…
轉換異常,看來不能用Jackson2JsonRedisSerializer,換成GenericJackson2JsonRedisSerializer
換了之后,刷新頁面
報錯信息變了,這是不能讀取json,現在redis里的json是Jackson2JsonRedisSerializer序列化的,
GenericJackson2JsonRedisSerializer當然不認識咯,清了redis再試
好了。
報錯!!!
SimpleKey and no properties discovered 沒有key 什么情況?
于是繼續讀源碼,看key是咋生成的
/** * Generate a key based on the specified parameters. */ public static Object generateKey(Object... params) { if (params.length == 0) { return SimpleKey.EMPTY; } if (params.length == 1) { Object param = params[0]; if (param != null && !param.getClass().isArray()) { return param; } } return new SimpleKey(params); }
是根據參數來的,我查詢所有,是沒有參數的,這樣key就為空
if (params.length == 0) { return SimpleKey.EMPTY; }
這怎么行,開發中,不傳參的方法多的很,這樣生成key肯定不行撒
于是重寫key的生成策略,用【類名+方法名+參數名】這樣就可以保證key不為空
package com.hehui.config; import java.lang.reflect.Method; import java.net.UnknownHostException; import java.util.Arrays; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; /** * 自定義redis配置 * @author hehui * @date 2019年3月12日 * */ @Configuration public class MyRedisConfig extends CachingConfigurerSupport{ @Bean public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); // Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(); template.setDefaultSerializer(serializer); return template; } @Bean @Override public KeyGenerator keyGenerator() { return new KeyGenerator() { public Object generate(Object target, Method method, Object... objects) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()).append(".").append(method.getName()).append(Arrays.toString(objects)); return sb.toString(); } }; } }
extends CachingConfigurerSupport并重寫keyGenerator方法
測試通過
redis
json中還帶有@Class相當好。
以上是“SpringBoot集成Redis并自定義對象序列化操作的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。