一、项目架构
二、引入依赖关系
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- spring版本号 -->
<spring.version>4.3.9.RELEASE</spring.version>
<!-- junit版本号 -->
<junit.version>4.12</junit.version>
</properties>
<!-- Redis 相关依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.4.RELEASE</version>
</dependency>
<!--单元测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
三、配置文件
1、redis的常见配置
redies.properties配置如下:
redis.host=127.0.0.1
redis.port=6379
redis.password=123456
redis.maxIdle=100
redis.maxActive=300
redis.maxWait=1000
redis.testOnBorrow=true
redis.timeout=10000
2、Spring配置文件
1、Jedis
Jedis是 Redis 官方首选的 Java 客户端开发包,Java中使用Jedis操作Redis.
2、RedisTemplate
Spring Data Redis(SDR),是SpringFramework提供的一套简化访问Redis的API,是对Jedis的又一层封装。SDR集成了Jedis,JRedis,SRP,Lettuce这四种开源的Redis Connector,这些Connector都是针对于Redis的开源Java库。其中,JRedis和SRP从spring-data-redis1.7开始,就不支持了。RedisTemplate是SDR的一个核心Helper类,该类是一个高级的抽象(对Jedis的又一层封装),它封装了对Redis中的数据的CRUD操作,包含“高级封装”。高级封装的操作包含:OpsForValue(),OpsForList(),OpsForSet(),OpsForZset(),OpsForHash()等等。通过Redistemplate可以调用ValueOperations和ListOperations等等方法,分别是对Redis命令的高级封装。
3、配置思路
要配置redis的缓存,就要配置RedisTemplate,要配RedisTemplate,就得配置JedisConnectionFactory,就要配JedisPoolConfig。
4、正则表达式
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。 |
5、DefaultAdvisorAutoProxyCreator这个类功能更为强大,这个类的奇妙之处是他实现了BeanProcessor接口,当ApplicationContext读如所有的Bean配置信息后,这个类将扫描上下文,寻找所有的Advistor(一个Advisor是一个切入点和一个通知的组成),将这些Advisor应用到所有符合切入点的Bean中。
配置信息:
<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- -
1、配置扫描的包
-->
<context:component-scan base-package="cn.com.bochy"/>
<!-- 2、配置读取redis.properties的bean -->
<bean id="dealProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:redis.properties"></property>
</bean>
<!-- 3、配置 JedisPoolConfig: jedis 配置 -->
<bean id="JedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"></property>
<property name="maxWaitMillis" value="${redis.maxWait}"></property>
<property name="testOnBorrow" value="${redis.testOnBorrow}"></property>
</bean>
<!-- 4、配置jedis的连接工厂 -->
<bean id="JedisConnectionFactory"class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="JedisPoolConfig"></property>
<property name="hostName" value="${redis.host}"></property>
<property name="port" value="${redis.port}"></property>
<property name="timeout" value="${redis.timeout}"></property>
</bean>
<!-- 5、配置RedisTemplate -->
<bean id="RedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory"></property>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
</property>
</bean>
<!-- 6、注入RedisTemplate -->
<bean id="cache" class="cn.com.bochy.redis.cache.MethodCache">
<property name="redisTemplate" ref="RedisTemplate"></property>
</bean>
<!-- 7、配置AOP:切点+建议 -->
<bean id="redisAop" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="cache"></property>
<property name="pattern" value=".*getTimes"></property>
</bean>
<!-- 8、配置bean -->
<bean id="redisImpl" class="cn.com.bochy.redis.serviceimpl.GetTimesImpl"></bean>
<!-- 9、配置AutoProxy的bean -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
</beans>
四、RedisTemplate常见操作
1、redisTemplate.opsForValue():字符串类型操作
ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue();
2、redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
//key,时间,单位
3、redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
1.redisTemplate.opsForValue().set(key,value));
2.redisTemplate.opsForValue().get(key));
3.redisTemplate.opsForValue().get(key, start, end);
4、ValueOperations
1、 operations.set(key, value);
2、operations.get(key)
五、具体实现
1、RedisService.java
package cn.com.bochy.redis.service;
public interface RedisServer {
public String getTimes(int id);
}
2、GetTimesImpl.java
package cn.com.bochy.redis.serviceimpl;
import cn.com.bochy.redis.service.RedisServer;
public class GetTimesImpl implements RedisServer{
@Override
public String getTimes(int id) {
longcurrentTimes=System.currentTimeMillis()+id;
return String.valueOf(currentTimes);
}
}
3、MethodCache.java
package cn.com.bochy.redis.cache;
import java.util.concurrent.TimeUnit;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
public class MethodCache implements MethodInterceptor{
//1、使用setter方法注入redisTemplate
private RedisTemplate<String, Object> redisTemplate;
public void setRedisTemplate(RedisTemplate<String, Object>redisTemplate) {
this.redisTemplate = redisTemplate;
}
//2、自定义方法,把数据写入缓存 redis
public boolean setCache(Stringkey,Object obj,long expireTime){
boolean mark=false;
try {
ValueOperations<String , Object> valueOperation=redisTemplate.opsForValue();//字符串
valueOperation.set(key,obj);//把数据存入redis
//第一个参数保存哪一个数据,第二个保存时间,第三个为保存的时间单位。
redisTemplate.expire(key, expireTime,TimeUnit.SECONDS);//设置保存数据的时间为10秒
mark=true;
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
return mark;
}
//3、自定义方法,根据key从redis获取值
public Object getCache(Stringkey){
ValueOperations<String , Object> valueOperation=redisTemplate.opsForValue();
return valueOperation.get(key);
}
//4、自定义方法,创建区分不同方法的key
/**
* 获取方法的类名+方法名+参数
*/
@SuppressWarnings("null")
public String getCacheKey(String targetClass,StringMethodname,Object[] params){
StringBuffer buf=new StringBuffer();
buf.append(targetClass+"_");
buf.append(Methodname+"_");
if(params!=null||params.length>0)
for(int i=0;i<params.length;i++){
buf.append(params[i]+"_");
}
return buf.toString();
}
//5、自定义方法,通过判断是否有key,用于判断redis是否已经存入该数据
public boolean exist(Stringkey){
return redisTemplate.hasKey(key);
}
//6、,判断是否从缓存中拿数据,如果已经存入缓存,从缓存里拿数据,如果缓存里没有,存入缓存。
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
StringtargetClass=invocation.getThis().getClass().getName();//
StringMethodname=invocation.getMethod().getName();
Object[] params= invocation.getArguments();
//得到被拦截方法的对应key值
final StringcacheKey=getCacheKey(targetClass, Methodname, params);
/**
*如果key存在于redis,直接从redis缓存中拿数据
*/
if(exist(cacheKey)){
returngetCache(cacheKey);
}
/**
*key不存在于redis
*/
final Object obj=invocation.proceed();
/**
* 把数据存入redis
*/
//setCache(cacheKey, obj, 10);
new Thread(new Runnable() {
public void run() {
setCache(cacheKey, obj, 10);
}
}).start();
return obj;
}
}
4、TestRedis.java
packagecn.com.bochy.redis.test;
import org.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
import cn.com.bochy.redis.service.RedisServer;
public class TestRedis {
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext context=newClassPathXmlApplicationContext("applicationContext.xml");
RedisServer gettimesImpl=(RedisServer)context.getBean("redisImpl");//把代理对象转化为实现类的接口
System.out.println(gettimesImpl.getTimes(100));
try {
Thread.sleep(2000);
System.out.println(gettimesImpl.getTimes(100));
Thread.sleep(11000);
System.out.println(gettimesImpl.getTimes(100));
} catch (InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
}
执行结果:
在10秒内,第二次从redis缓存中获取数据,超过10秒,缓存失效。