java aop redis缓存

<!-- Redis客户端 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.8.0</version>
		</dependency>

        <!-- Jackson Json处理工具包 -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.7.3</version>
		</dependency>



spring 配置文件添加

  <!-- 开启切面代理 使得spring认识 @Aspect -->
     <aop:aspectj-autoproxy/>

然后定义两个标注在Service实现方法上的注解,用于传递类型参数:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface RedisCache {
	
    Class type();
    public int expire() default 0;      //缓存多少秒,默认无限期  
}


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RedisEvict {
    Class type();
}

注解的使用方式如下:

	@RedisCache(type = User.class, expire = 200000000)
	public List<User> findUsersByGroupId(Integer group_id) {
		return groupDao.findUsersByGroupId(group_id);
	}
	@RedisEvict(type = User.class)// 表示该方法需要执行清除缓存逻辑
	public void updateUserByPhone(String nickName,String phone) {
		UserDao.updateUserByPhone(nickName, phone);
	}


JsonUtils

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;



public class JsonUtils {

	private static Logger logger = Logger.getLogger(JsonUtils.class);

	// 定义jackson对象
	private static final ObjectMapper MAPPER = new ObjectMapper();

	/**
	 * 将对象转换成json字符串。
	 * 
	 * @param data
	 * @return
	 * @throws IOException
	 */
	public static String objectToJson(Object data) {
		try {
			String string = MAPPER.writeValueAsString(data);
			return string;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将json结果集转化为对象
	 * 
	 * @param jsonData
	 *            json数据
	 * @param clazz
	 *            对象中的object类型
	 * @return
	 */
	public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
		try {
			T t = MAPPER.readValue(jsonData, beanType);
			return t;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将json数据转换成pojo对象list
	 * 
	 * @param jsonData
	 * @param beanType
	 * @return
	 */
	public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
		JavaType javaType = MAPPER.getTypeFactory().constructParametricType(
				List.class, beanType);
		try {
			List<T> list = MAPPER.readValue(jsonData, javaType);
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * json string convert to map with javaBean
	 */
	public static <T> Map<String, T> jsonTomap(String jsonStr, Class<T> clazz)
			throws Exception {
		Map<String, Map<String, Object>> map = MAPPER.readValue(jsonStr,
				new TypeReference<Map<String, T>>() {
				});
		Map<String, T> result = new HashMap<String, T>();
		for (Entry<String, Map<String, Object>> entry : map.entrySet()) {
			result.put(entry.getKey(), mapTopojo(entry.getValue(), clazz));
		}
		return result;
	}

	/**
	 * json string convert to map
	 */
	public static <T> Map<String, Object> jsonTomap(String jsonStr) {
		try {
			return MAPPER.readValue(jsonStr, Map.class);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * map convert to javaBean
	 */
	public static <T> T mapTopojo(Map map, Class<T> clazz) {

		try {
			return MAPPER.convertValue(map, clazz);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

}



AOP的代码如下:

import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.core.annotation.RedisCache;
import com.core.annotation.RedisEvict;
import com.jedis.dao.JedisClient;
import com.utils.JsonUtils;

@Aspect
@Component
public class CacheInterceptor {

	@Autowired
	JedisClient jedisClient;
	
	
	//前置由于数据库数据变更  清理redis缓存
	@Before("@annotation(redisEvict)")
	public void <span style="font-family:Consolas, Courier New, Courier, mono, serif;"><span style="line-height: 18px; background-color: rgb(248, 248, 248);">doBefore</span></span>(JoinPoint jp,RedisEvict redisEvict){
		
		  try{
			  
			  String modelName = redisEvict.type().getName();
			  // 清除对应缓存
			  jedisClient.del(modelName);  
			  
		  }catch (Exception e) {
				
				e.printStackTrace();
				System.out.println("缓存服务器出现问题,发邮箱,发信息...");		
		}
	}

	// 配置环绕方法
	@Around("@annotation(redisCache)")
	public Object doAround(ProceedingJoinPoint pjp, RedisCache redisCache)
			throws Throwable {
		// 得到被代理的方法
		// Method me = ((MethodSignature) pjp.getSignature()).getMethod();
		// Class modelType = me.getAnnotation(RedisCache.class).type();

		//得到注解上类型
		Class modelType = redisCache.type();
		//System.out.println(modelType.getName());
		
		// 去Redis中看看有没有我们的数据 包名+ 类名 + 方法名 + 参数(多个)
		String cacheKey = getCacheKey(pjp);
		System.out.println(cacheKey);

		String value = null;
		
		try {//当取redis发生异常时,为了不影响程序正常执行,需要try..catch()...
			
			//检查redis中是否有缓存
	        value = jedisClient.hget(modelType.getName(),cacheKey);
			
		} catch (Exception e) {
			
			e.printStackTrace();
			System.out.println("缓存服务器出现问题,发邮箱,发信息...");
			
		}

		// result是方法的最终返回结果
		Object result = null;
		if (null == value) {
			// 缓存未命中
			System.out.println("缓存未命中");

			// 后端查询数据  
			result = pjp.proceed();
           
			try {//当取redis发生异常时,为了不影响程序正常执行,需要try..catch()...
				
				// 序列化结果放入缓存
				String json = serialize(result);
				jedisClient.hset(modelType.getName(), cacheKey, json);
				
				if(redisCache.expire()>0) { 
					jedisClient.expire(cacheKey, redisCache.expire());//设置缓存时间
				}
				
			} catch (Exception e) {
				
				e.printStackTrace();
				System.out.println("缓存服务器出现问题,发邮箱,发信息...");
			}
			
		} else {
			
			try{//当数据转换失败发生异常时,为了不影响程序正常执行,需要try..catch()...
				
				// int i =1/0;
				
				// 得到被代理方法的返回值类型
				Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType();
				
				//把json反序列化
				result = deserialize(value, returnType, modelType);
				
			    
				// 缓存命中
				System.out.println("缓存命中");
			} catch (Exception e) {
				
				//数据转换失败,到后端查询数据  
				result = pjp.proceed();
				
				e.printStackTrace();
				System.out.println("缓存命中,但数据转换失败...");
			}

		}

		return result;
	}
	

	protected String serialize(Object target) {
		return JsonUtils.objectToJson(target);
	}

	protected Object deserialize(String jsonString, Class clazz, Class modelType) {
		// 序列化结果应该是List对象
		if (clazz.isAssignableFrom(List.class)) {
			return JsonUtils.jsonToList(jsonString, modelType);
		}

		// 序列化结果是普通对象
		return JsonUtils.jsonToPojo(jsonString, clazz);
	}

	
	// 包名+ 类名 + 方法名 + 参数(多个) 生成Key
	public String getCacheKey(ProceedingJoinPoint pjp) {
		StringBuffer key = new StringBuffer();
		// 包名+ 类名 cn.core.serice.product.ProductServiceImpl.productList
		String packageName = pjp.getTarget().getClass().getName();

		key.append(packageName);
		// 方法名
		String methodName = pjp.getSignature().getName();
		key.append(".").append(methodName);

		// 参数(多个)
		Object[] args = pjp.getArgs();

		for (Object arg : args) {
			// 参数
			key.append(".").append(arg.toString());
		}

		return key.toString();
	}
}


jedisClient.java

public interface JedisClient {
	String get(String key);

	byte[] get(byte[] key);

	String set(String key, String value);

	String set(byte[] key, byte[] value);

	String hget(String hkey, String key);

	long hset(String hkey, String key, String value);

	long incr(String key);

	long expire(String key, int second);

	long ttl(String key);

	long del(String key);

	long hdel(String hkey, String key);
	
}


JedisClientSingle 

import org.springframework.beans.factory.annotation.Autowired;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import com.edl.jedis.dao.JedisClient;

public class JedisClientSingle implements JedisClient{

	@Autowired
	private JedisPool jedisPool; 
	
	@Override
	public String get(String key) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.get(key);
		jedis.close();
		return string;
	}

	@Override
	public String set(String key, String value) {
		Jedis jedis = jedisPool.getResource();
		
		String string = jedis.set(key, value);
		jedis.close();
		return string;
	}

	@Override
	public String hget(String hkey, String key) {
		Jedis jedis = jedisPool.getResource();
		String string = jedis.hget(hkey, key);
		jedis.close();
		return string;
	}

	@Override
	public long hset(String hkey, String key, String value) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hset(hkey, key, value);
		jedis.close();
		return result;
	}

	@Override
	public long incr(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.incr(key);
		jedis.close();
		return result;
	}

	@Override
	public long expire(String key, int second) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.expire(key, second);
		jedis.close();
		return result;
	}

	@Override
	public long ttl(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.ttl(key);
		jedis.close();
		return result;
	}

	@Override
	public long del(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.del(key);
		jedis.close();
		return result;
	}

	@Override
	public long hdel(String hkey, String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hdel(hkey, key);
		jedis.close();
		return result;
	}

	@Override
	public byte[] get(byte[] key) {
		Jedis jedis = jedisPool.getResource();
		byte[] result = jedis.get(key);
		jedis.close();
		return result;
	}

	@Override
	public String set(byte[] key, byte[] value) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.set(key, value);
		jedis.close();
		return result;
	}
}

JedisClientCluster


public class JedisClientCluster implements JedisClient {

	@Autowired
	private JedisCluster jedisCluster;
	
	@Override
	public String get(String key) {
		return jedisCluster.get(key);
	}

	@Override
	public String set(String key, String value) {
		return jedisCluster.set(key, value);
	}

	@Override
	public String hget(String hkey, String key) {
		return jedisCluster.hget(hkey, key);
	}

	@Override
	public long hset(String hkey, String key, String value) {
		return jedisCluster.hset(hkey, key, value);
	}

	@Override
	public long incr(String key) {
		return jedisCluster.incr(key);
	}

	@Override
	public long expire(String key, int second) {
		return jedisCluster.expire(key, second);
	}

	@Override
	public long ttl(String key) {
		return jedisCluster.ttl(key);
	}

	@Override
	public long del(String key) {
		
		return jedisCluster.del(key);
	}

	@Override
	public long hdel(String hkey, String key) {
		
		return jedisCluster.hdel(hkey, key);
	}

	@Override
	public byte[] get(byte[] key) {
		// TODO Auto-generated method stub
		return jedisCluster.get(key);
	}

	@Override
	public String set(byte[] key, byte[] value) {
		// TODO Auto-generated method stub
		return jedisCluster.set(key, value);
	}

}



spring-jedis.xml
<?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" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                    http://www.springframework.org/schema/tx
                    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                    http://www.springframework.org/schema/task
                    http://www.springframework.org/schema/task/spring-task-3.0.xsd">

	 <context:component-scan base-package="com.core" />


	<!-- jedis客户端单机版 -->
	<bean id="redisClient" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
		<constructor-arg name="port" value="6379"></constructor-arg>
	</bean>
	<bean id="jedisClient" class="com.edl.jedis.dao.impl.JedisClientSingle" />
	
	<!-- jedis集群版配置 -->
<!-- 	<bean id="redisClient" class="redis.clients.jedis.JedisCluster">
		<constructor-arg name="nodes">
			<set>
			    <bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
					<constructor-arg name="port" value="7006"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
					<constructor-arg name="port" value="7001"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
					<constructor-arg name="port" value="7002"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
					<constructor-arg name="port" value="7003"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
					<constructor-arg name="port" value="7004"></constructor-arg>
				</bean>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.1.87"></constructor-arg>
					<constructor-arg name="port" value="7005"></constructor-arg>
				</bean>
			</set>
		</constructor-arg>
		<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
	</bean>
	<bean id="jedisClientCluster" class="com.edl.jedis.dao.impl.JedisClientCluster"></bean> -->

</beans>




  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值