本文章牵涉到的技术点比较多:spring Data JPA、Redis、Spring MVC,Spirng Cache,所以在看这篇文章的时候,需要对以上这些技术点有一定的了解或者也可以先看看这篇文章,针对文章中实际的技术点在进一步了解(注意,您需要自己下载Redis Server到您的本地,所以确保您本地的Redis可用,这里还使用了MySQL数据库,当然你也可以内存数据库进行测试)。这篇文章会提供对应的Eclipse代码示例,具体大体的分如下几个步骤:
(1)新建Java MavenProject;
(2)在pom.xml中添加相应的依赖包;
(3)编写Spring Boot启动类;
(4)配置application.properties;
(5)编写RedisCacheConfig配置类;
(6)编写DemoInfo测试实体类;
(7)编写DemoInfoRepository持久化类;
(8)编写DemoInfoService类;
(9)编写DemoInfoController类;
(10)测试代码是否正常运行了
(11)自定义缓存key;
(1)新建Java Maven Project;
(2)在pom.xml中添加相应的依赖包;
<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>me.shijunjie</groupId> <artifactId>testspringbootredis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>testspringbootredis</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!-- springboot web支持:mvc,aop... --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- 添加redis支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <!-- JPA操作数据库. --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- mysql数据库驱动. --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/commons-pool/commons-pool --> <!-- <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> </dependency> --> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </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> <!-- <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin </artifactId> <dependencies> springloaded hotdeploy <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> <version>1.2.4.RELEASE</version> </dependency> </dependencies> <executions> <execution> <goals> <goal>repackage</goal> </goals> <configuration> <classifier>exec</classifier> </configuration> </execution> </executions> </plugin> --> <!-- java编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
(3)编写Spring Boot启动类(com.kfit.App);
package me.shijunjie.testspringbootredis; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.orm.jpa.EntityScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication @ComponentScan("me.shijunjie") @EnableJpaRepositories("me.shijunjie.repository") @EntityScan("me.shijunjie.bean") public class App { public static void main( String[] args ) { SpringApplication.run(App.class, args); } }
(4)配置application.properties;
########################################################
###datasource u914Du7F6EMySQLu6570u636Eu6E90uFF1B
########################################################
spring.datasource.url =jdbc:mysql://123.206.228.200:3306/test
spring.datasource.username = shijunjie
spring.datasource.password = ******
spring.datasource.driverClassName =com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10
########################################################
###REDIS (RedisProperties) redisu57FAu672Cu914Du7F6EuFF1B
########################################################
# database name
spring.redis.database=0
# server host1
spring.redis.host=123.206.228.200
# server password
spring.redis.password=******
#connection port
spring.redis.port=6379
# pool settings ...
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
# name of Redis server
#spring.redis.sentinel.master=
# comma-separated list of host:portpairs
#spring.redis.sentinel.nodes=
########################################################
### Java Persistence Api u81EAu52A8u8FDBu884Cu5EFAu8868
########################################################
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sqlquery
spring.jpa.show-sql = true
# hibernate ddl auto (create,create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy =org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them tothe entity manager)
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
(5)编写RedisCacheConfig配置类;
缓存主要有几个要实现的类:其一就是CacheManager缓存管理器;其二就是具体操作实现类;其三就是CacheManager工厂类(这个可以使用配置文件配置的进行注入,也可以通过编码的方式进行实现);其四就是缓存key生产策略(当然Spring自带生成策略,但是在Redis客户端进行查看的话是系列化的key,对于我们肉眼来说就是感觉是乱码了,这里我们先使用自带的缓存策略)。
package me.shijunjie.config; 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.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; @Configuration @EnableCaching //启用缓存,这个注解很重要; public class RedisCacheConfig extends CachingConfigurerSupport { /** * 缓存管理器. * @param redisTemplate * @return */ @Bean public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) { CacheManager cacheManager = new RedisCacheManager(redisTemplate); return cacheManager; } /** * redis模板操作类,类似于jdbcTemplate的一个类; * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活; * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们 * 自己的缓存类,比如:RedisStorage类; * @param factory : 通过Spring进行注入,参数在application.properties进行配置; * @return */ @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String,String> redisTemplate = new RedisTemplate<String, String>(); redisTemplate.setConnectionFactory(factory); //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误; //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer //或者JdkSerializationRedisSerializer序列化方式; // RedisSerializer<String>redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息; // redisTemplate.setKeySerializer(redisSerializer); // redisTemplate.setHashKeySerializer(redisSerializer); return redisTemplate; } }
(6)编写DemoInfo测试实体类;
package me.shijunjie.bean; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class DemoInfo implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue private long id; private String name; private String pwd; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "DemoInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + "]"; } }
(7)编写DemoInfoRepository持久化类;
package me.shijunjie.repository; import java.io.Serializable; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import me.shijunjie.bean.DemoInfo; @Repository public interface DemoInfoRepository extends CrudRepository<DemoInfo, Serializable> { }
(8)编写DemoInfoService类;
编写DemoInfoService,这里有两个技术方面,第一就是使用Spring @Cacheable注解方式和RedisTemplate对象进行操作,具体代码如下:
package me.shijunjie.service; import me.shijunjie.bean.DemoInfo; public interface DemoInfoService { public DemoInfo findById(long id); public void deleteFromCache(long id); void test(); void save(DemoInfo demoInfo); }
package me.shijunjie.service.impl; import javax.annotation.Resource; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import me.shijunjie.bean.DemoInfo; import me.shijunjie.repository.DemoInfoRepository; import me.shijunjie.service.DemoInfoService; @Service public class DemoInfoServiceImpl implements DemoInfoService { @Resource private DemoInfoRepository demoInfoDao; @Resource private RedisTemplate<String,String> redisTemplate; @Cacheable(value="demoInfo") //缓存,这里没有指定key. @Override public DemoInfo findById(long id) { System.err.println("DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id="+id); DemoInfo demoInfo = demoInfoDao.findOne(id); return demoInfo; } @CacheEvict(value="demoInfo") @Override public void deleteFromCache(long id) { System.out.println("DemoInfoServiceImpl.delete().从缓存中删除."); } @Override public void test() { ValueOperations<String,String> valueOperations = redisTemplate.opsForValue(); valueOperations.set("mykey4", "random1="+Math.random()); System.out.println(valueOperations.get("mykey4")); } @Override public void save(DemoInfo demoInfo) { demoInfoDao.save(demoInfo); } }
(9)编写DemoInfoController类;
package me.shijunjie.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import me.shijunjie.bean.DemoInfo; import me.shijunjie.service.DemoInfoService; @Controller public class DemoInfoController { @Resource DemoInfoService demoInfoService; @RequestMapping("/save") public @ResponseBody String save(){ DemoInfo demoInfo = new DemoInfo(); demoInfo.setName("aaa"); demoInfo.setPwd("aaab"); demoInfoService.save(demoInfo); return "ok"; } @RequestMapping("/test") public @ResponseBody String test(){ DemoInfo loaded = demoInfoService.findById(1); System.out.println("loaded="+loaded); DemoInfo cached = demoInfoService.findById(1); System.out.println("cached="+cached); loaded = demoInfoService.findById(2); System.out.println("loaded2="+loaded); return "ok"; } @RequestMapping("/delete") public @ResponseBody String delete(long id){ demoInfoService.deleteFromCache(id); return "ok"; } @RequestMapping("/test1") public @ResponseBody String test1(){ demoInfoService.test(); System.out.println("DemoInfoController.test1()"); return "ok"; } }
(10)测试代码是否正常运行了
启动应用程序,访问地址:http://127.0.0.1:8080/test
查看控制台可以查看:
(11)自定义缓存key;
在me.shijunjie.config.RedisCacheConfig类中重写CachingConfigurerSupport中的keyGenerator ,具体实现代码如下:
/** * 自定义key. * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。 */ @Override public KeyGenerator keyGenerator() { System.out.println("RedisCacheConfig.keyGenerator()"); return new KeyGenerator() { @Override public Object generate(Object o, Method method, Object... args) { StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()); sb.append(method.getName()); for (Object obj : args) { sb.append(obj.toString()); } System.out.println("keyGenerator=" + sb.toString()); return sb.toString(); } }; }
具体参照http://blog.csdn.net/linxingliang/article/details/52263763