一、添加Redis依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.shyroke.redis</groupId> <artifactId>springboot_redis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>springboot_redis</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <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.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
二、 application配置
server.port=8888 #數據庫連接配置 spring.datasource.url=jdbc:mysql://localhost/db_boot?useUnicode=true&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.jdbc.Driver # JPA spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto= update #redis spring.cache.type=redis spring.redis.host=localhost spring.redis.port=6379 #spring.redis.password= #spring.redis.database=0 #spring.redis.pool.max-active=8 #spring.redis.pool.max-idle=8 #spring.redis.pool.max-wait=-1 #spring.redis.pool.min-idle=0 #spring.redis.timeout=0
三、 redis緩存配置類
package com.shyroke.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import java.lang.reflect.Method; @Configuration public class RedisConfig extends CachingConfigurerSupport { /* * 定義緩存數據 key 生成策略的bean 包名+類名+方法名+所有參數 */ @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(); } }; } /* * 要啟用spring緩存支持,需創建一個 CacheManager的 bean,CacheManager 接口有很多實現,這里Redis 的集成,用 * RedisCacheManager這個實現類 Redis 不是應用的共享內存,它只是一個內存服務器,就像 MySql 似的, * 我們需要將應用連接到它並使用某種“語言”進行交互,因此我們還需要一個連接工廠以及一個 Spring 和 Redis 對話要用的 * RedisTemplate, 這些都是 Redis 緩存所必需的配置,把它們都放在自定義的 CachingConfigurerSupport 中 */ @Bean public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); // cacheManager.setDefaultExpiration(60);//設置緩存保留時間(seconds) return cacheManager; } // 1.項目啟動時此方法先被注冊成bean被spring管理,如果沒有這個bean,則redis可視化工具中的中文內容(key或者value)都會以二進制存儲,不易檢查。 @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); 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); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
四、在springboot啟動類中添加緩存支持
@SpringBootApplication @EnableCaching public class SpringbootRedisApplication { public static void main(String[] args) { SpringApplication.run(SpringbootRedisApplication.class, args); } }
五、編寫控制類
package com.shyroke.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.shyroke.bean.UserBean; import com.shyroke.mapper.UserMapper; import com.shyroke.service.UserServiceI; import com.shyroke.util.DateUtil; @Controller @RequestMapping(value = "/") public class IndexController { @Autowired private UserServiceI userService; @ResponseBody @RequestMapping(value = "/get") public UserBean get() { return userService.getUserById(1); } @ResponseBody @RequestMapping(value="/update") public UserBean update() { UserBean user=userService.getUserById(1); user.setCreateTime(DateUtil.getDataFormat()); user.setUserName("test"); return userService.update(user); } @ResponseBody @RequestMapping(value="/del") public String del() { return userService.del(1); } }
六、Service層接口及其實現
package com.shyroke.service; import com.shyroke.bean.UserBean; public interface UserServiceI { UserBean getUserById(int i); UserBean update(UserBean user); String del(int id); }
- 實現類
package com.shyroke.service.impl; import org.springframework.beans.factory.annotation.Autowired; 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 org.springframework.stereotype.Service; import com.shyroke.bean.UserBean; import com.shyroke.mapper.UserMapper; import com.shyroke.service.UserServiceI; @Service @CacheConfig(cacheNames="users") public class UserServiceImpl implements UserServiceI { @Autowired private UserMapper userMapper; @Cacheable(key="'userCache'") @Override public UserBean getUserById(int i) { System.out.println("執行這里,說明緩存中讀取不到數據,直接讀取數據庫...."); return userMapper.findOne(i); } @CachePut(key="'userCache'") @Override public UserBean update(UserBean user) { System.out.println("執行這里,更新數據庫,更新緩存...."); return userMapper.save(user); } @CacheEvict(key="'userCache'") @Override public String del(int id) { userMapper.delete(id); return "刪除成功!!!!"; } }
- 注意:
- @CacheConfig(cacheNames="users") 注解指的是該類中的緩存的名稱都是users
-
@CachePut(key=" 'userCache' ")中userCache要加‘’單引號,表示這是一個字符串。
-
@Cacheable能夠根據方法的請求參數對其結果進行緩存(緩存的是方法的返回結果),一般用於insert()操作
- @CachePut(key="'userCache'")主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實方法的調用,一般用於update()操作
- @CacheEvict(key="'userCache'")主要針對方法配置,能夠根據一定的條件對緩存進行清空,一般用於delete()操作
- 本例中的@Cacheable和@CachePut和@CacheEvict的key值必須都是同一個緩存的key,因為這樣當update的時候緩存的時候,get方法的得到的才是最新數據,而當刪除的時候@CacheEvict,也必須把該key的緩存刪除。
七、編寫mapper
package com.shyroke.mapper; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.shyroke.bean.UserBean; @Repository public interface UserMapper extends JpaRepository<UserBean,Integer> { }
八、實驗結果
- 啟動springboot會在數據庫中根據bean的定義自動創建一個表數據。插入一條測試數據
- 如下訪問http://localhost:8888/get ,獲取結果,並生成一個緩存。
- 如下 訪問 http://localhost:8888/update ,更新數據,更新緩存,
- 執行上一步更新緩存后,如下我們再訪問http://localhost:8888/get,獲取的是最新數據,且沒有沒有發出sql語句說明是從緩存中讀取的數據。
- 如下訪問http://localhost:8888/del,緩存被清空。
九、總結
要緩存的 Java 對象必須實現 Serializable 接口,因為 Spring 會將對象先序列化再存入 Redis,如果不實現 Serializable 的話將會遇到類似這種錯誤:nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type。。。