分页进阶-使用redis实现基础分页缓存(一)使用aop代理
·
一.redis基础配置
本项目采用基础ssm配置来实现,首先我们使用redis来做缓存,那么我们就需要先在spring中整合redis。
- 整合第一步,导入对应依赖。
有关redis的配置
<!--redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
- 第二步在spring配置文件中配置对应的redis配置
<!--jedis配置-->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${maxIdle}"/>
<property name="maxWaitMillis" value="${redis.maxWait}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="poolConfig"/>
<property name="port" value="${redis.port}"/>
<property name="hostName" value="${redis.host}"/>
<property name="password" value="${redis.password}"/>
<property name="timeout" value="${redis.timeout}"/>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
//这里是键的序列化
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
//这里是值的序列化
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
二.
做缓存的对象都是查询操作,从这一点我们可以想到使用spring的aop来对对应的查询操作进行拦截处理,步骤如下。
- 书写配置文件定义对应的切面类,切点。
//下面这行配置需要在spring的两个配置文件中都书写
<aop:aspectj-autoproxy/>
<bean id="redisUtil" class="com.by.util.RedisUtil">
<property name="redisTemplate" ref="redisTemplate"/>
</bean>
<bean id="methodInterceptor" class="com.by.interceptor.CacheInterceptor">
<property name="redisUtil" ref="redisUtil"/>
</bean>
<aop:config>
<aop:pointcut id="controllerMethodPointcut" expression="execution(* com.by.service.*.query*(..))"/>
<aop:advisor advice-ref="methodInterceptor" pointcut-ref="controllerMethodPointcut"/>
</aop:config>
- 书写对应的redis工具类,这一步操作是为了方便我们书写切面类。
package com.by.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
/**
* redis操作工具类
*/
public class RedisUtil {
private RedisTemplate<Serializable, Object> redisTemplate;
/**
* 判断是否有key
*
* @param key
* @return
*/
public boolean exists(String key) {
return redisTemplate.hasKey(key);
}
/**
* 删除对应的value
*
* @param key
*/
public void remove(String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 批量删除对应的value
*
* @param keys
*/
public void remove(String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存,并设置有效期
*
* @param key
* @param value
* @param expireTime
* @return
*/
public boolean set(String key, Object value, Long expireTime) {
boolean result = false;
try {
redisTemplate.opsForValue().set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 读取缓存
*
* @param key
* @return
*/
public Object get(String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
public void setRedisTemplate(RedisTemplate<Serializable, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
}
- 书写对应的拦截类(切面类),在这个类中我们拦截对应的
package com.by.interceptor;
import com.by.util.RedisUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.util.Map;
public class CacheInterceptor implements MethodInterceptor {
private RedisUtil redisUtil;
private Long defaultCacheExpireTime;
/**
* 加载缓存有效时间
*/
public CacheInterceptor() {
defaultCacheExpireTime = 3600L;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object value = null;
//类名
String targetName = invocation.getThis().getClass().getName();
//方法名
String methodName = invocation.getMethod().getName();
//参数数组
Object[] args = invocation.getArguments();
Map<String, Object> maps = (Map<String, Object>) args[0];
String pageSize = String.valueOf(maps.get("pageSize"));
String pageNum = String.valueOf(maps.get("pageNum"));
Object[] arguments = {pageNum + ":" + pageSize};
String key = getCacheKey(targetName, methodName, arguments);
//如果redis有数据,取出
if (redisUtil.exists(key)) {
return redisUtil.get(key);
}
//这里调用的方法是用来调用对应的代理实现方法,也就是分页查询方法
value = invocation.proceed();
//如果没有,写入
if (value != null) {
String tkey = key;
Object tval = value;
new Thread(new Runnable() {
@Override
public void run() {
redisUtil.set(tkey, tval, defaultCacheExpireTime);
}
}).start();
}
return value;
}
public String getCacheKey(String targetName, String methodName, Object[] args) {
StringBuffer sbu = new StringBuffer();
sbu.append(targetName).append("_").append(methodName);
//如果有参数,一起拼接
if ((args != null) && (args.length != 0)) {
for (int i = 0; i < args.length; i++) {
sbu.append("_").append(args[i]);
}
}
return sbu.toString();
}
public void setRedisUtil(RedisUtil redisUtil) {
this.redisUtil = redisUtil;
}
}
到这里我们就实现了使用aop和redis来实现分页缓存
更多推荐



所有评论(0)