redis与spring aop整合
2017-07-27 12:53
267 查看
redis与Spring整合做缓存
项目中要用到redis,没用过,费了很多功夫,还是做了一个勉强能可以使用的。因为项目中用mysql和mangoDB结合主从配合使用,感觉配置有点让人头大。pom.xml
<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>
redis数据源配置
使用的基本算是最原始的方法,因为不太了解,怕出错。
<!-- Jedis 连接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="2000" /> <property name="maxIdle" value="2000" /> <property name="minIdle" value="50" /> <property name="maxWaitMillis" value="2000" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="false" /> </bean> <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"> <constructor-arg ref="jedisPoolConfig" /> <constructor-arg> <list> <bean class="redis.clients.jedis.JedisShardInfo"> <constructor-arg value="127.0.0.1" /> <constructor-arg type="int" value="6379" /> <constructor-arg value="redis1" /> </bean> </list> </constructor-arg> </bean> <bean id="jedisClient" class="*.redis.JedisClientSingle" />
基于注解的aop的redis缓存
自定义注解@RedisCache
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface RedisCache { @SuppressWarnings("rawtypes") Class type(); public int expire() default 120; //缓存多少秒,默认无限期 public String cacheKey() default "key"; //默认key值 为key }
自定义注解@RedisEvict 清除数据,但是不太友好,很暴力,可以自己按照需求修改自己的
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 { @SuppressWarnings("rawtypes") Class type(); }
JsonUtils 对象pojo 要实现序列化
import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JsonUtils { @SuppressWarnings("unused") private static Logger logger = LoggerFactory.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 beanType * 对象中的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 */ @SuppressWarnings("unchecked") 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 */ @SuppressWarnings("rawtypes") public static <T> T mapTopojo(Map map, Class<T> clazz) { try { return MAPPER.convertValue(map, clazz); } catch (Exception e) { e.printStackTrace(); } return null; } }
JedisClient
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 redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPool; public class JedisClientSingle implements JedisClient { @Autowired private ShardedJedisPool shardedJedisPool; @Override public String get(String key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); String string = jedis.get(key); jedis.close(); return string; } @Override public String set(String key, String value) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); String string = jedis.set(key, value); jedis.close(); return string; } @Override public String hget(String hkey, String key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); String string = jedis.hget(hkey, key); jedis.close(); return string; } @Override public long hset(String hkey, String key, String value) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); Long result = jedis.hset(hkey, key, value); jedis.close(); return result; } @Override public long incr(String key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); Long result = jedis.incr(key); jedis.close(); return result; } @Override public long expire(String key, int second) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); Long result = jedis.expire(key, second); jedis.close(); return result; } @Override public long ttl(String key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); Long result = jedis.ttl(key); jedis.close(); return result; } @Override public long del(String key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); Long result = jedis.del(key); jedis.close(); return result; } @Override public long hdel(String hkey, String key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); Long result = jedis.hdel(hkey, key); jedis.close(); return result; } @Override public byte[] get(byte[] key) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); byte[] result = jedis.get(key); jedis.close(); return result; } @Override public String set(byte[] key, byte[] value) { ShardedJedis jedis = shardedJedisPool.getResource(); // Jedis jedis = jedisPool.getResource(); String result = jedis.set(key, value); jedis.close(); return result; } }
CacheInterceptor Spring Aop
aop的处理还是很粗糙,可以自己根据实际需求修改,我觉得删除缓存那块可以优化下
<!-- 开启AOP --> <aop:aspectj-autoproxy proxy-target-class="true"/>* //proxy-target-class="true" 没记错的话使用cglib代理,不加他默认的是jdk的动态代理
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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Aspect @Component public class CacheInterceptor { private static Logger logger = LoggerFactory.getLogger(JsonUtils.class); @Autowired private JedisClient jedisClient; //前置由于数据库数据变更 清理redis缓存 @Before("@annotation(redisEvict)") public void doBefore (JoinPoint jp,RedisEvict redisEvict){ try{ String modelName = redisEvict.type().getName(); // 清除对应缓存 jedisClient.del(modelName); }catch (Exception e) { logger.info("缓存服务器出现问题,发邮箱,发信息..."+e); } } // 配置环绕方法 @Around("@annotation(redisCache)") public Object doAround(ProceedingJoinPoint pjp, RedisCache redisCache) throws Throwable { //得到注解上类型 @SuppressWarnings("rawtypes") Class modelType = redisCache.type(); // 去Redis中看看有没有我们的数据 类名 + 方法名 + 参数(多个) String cacheKey = redisCache.cacheKey(); if(cacheKey.equals("key")){ cacheKey = this.getCacheKey(pjp); } String value = null; try {//当取redis发生异常时,为了不影响程序正常执行,需要try..catch()... //检查redis中是否有缓存 value = jedisClient.hget(modelType.getName(),cacheKey); // System.out.println(jedisClient.hget(modelType.getName(),cacheKey)); } catch (Exception e) { logger.info("缓存服务器出现问题,发邮箱,发信息..."+e); } // result是方法的最终返回结果 Object result = null; if (null == value) { // 缓存未命中 // System.out.println("缓存未命中"); // 后端查询数据 result = pjp.proceed(); try {//当取redis发生异常时,为了不影响程序正常执行,需要try..catch()... String json = serialize(result); //判断结果是否为空,不为空则返回 if(!(json.equals("[]"))){ // 序列化结果放入缓存 jedisClient.hset(modelType.getName(), cacheKey, json); int times = redisCache.expire(); if(times < 60){ times = 120; } if(redisCache.expire()>0) { jedisClient.expire(cacheKey, times);//设置缓存时间 } } } catch (Exception e) { logger.info("缓存服务器出现问题,发邮箱,发信息..."+e); } } else { try{//当数据转换失败发生异常时,为了不影响程序正常执行,需要try..catch()... // int i =1/0; // 得到被代理方法的返回值类型 @SuppressWarnings("rawtypes") Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType(); //把json反序列化 result = deserialize(value, returnType, modelType); // 缓存命中 } catch (Exception e) { //数据转换失败,到后端查询数据 result = pjp.proceed(); logger.info("缓存命中,但数据转换失败..."+e); } } return result; } protected String serialize(Object target) { return JsonUtils.objectToJson(target); } @SuppressWarnings({ "unchecked", "rawtypes" }) 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().getSimpleName(); 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(); } }
在service层,注入注解
@RedisCache(type = Bim114CategoryLevel2.class) public List<Bim114CategoryLevel2> getlevel2List() { return null; }
开启redis,运行项目就可以了
欢迎加我QQ 971492191 讨论,一起向前
相关文章推荐
- spring与redis集成之aop整合方案
- dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3.2整合(四)Spring AOP中使用log4j实现http请求日志入mongodb
- spring boot 整合redis对查询数据做缓存( 利用spring的AOP技术)
- spring与redis集成之aop整合方案
- spring与redis集成之aop整合方案
- Spring AOP整合redis(注解方式) 实现缓存统一管理
- spring与redis集成之aop整合方案
- spring与redis集成之aop整合方案
- spring boot 整合redis对查询数据做缓存( 利用spring的AOP技术)
- spring与redis集成之aop整合方案
- Spring AOP如何整合redis(注解方式)实现缓存统一管理详解
- spring4.1与redis集成之aop整合方案
- spring与redis集成之aop整合方案
- redis和spring整合
- Spring 整合 Redis
- spring-data-redis整合
- spring-boot整合redis作为缓存(3)——自定义key
- spring整合redis时 因为版本问题导致bean注入不进去问题
- Redis整合Spring结合使用缓存实例