赞
踩
模式定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果(取自《设计模式之禅》)。
翻译:Client对象调用一个处理者(类)的方法,可能有多个处理者(实现类),但是该对象只需要调用第一个处理者(类)即可,该模式会自动分配谁来处理这个请求;这多个处理者继承同一个父类(即在一条链上)。
通用类图如下:
Client发送请求到Handler,Handler自动分配请求到子类的实现类ConcreteHandler中。
在文章 >手写redis@Cacheable注解 支持过期时间设置< 的基础之上做修改,原版为redis缓存注解实现,
原版实现功能:
原业务逻辑查询人员列表listleader()接口,数据存放redis中,减少数据库负载。
由于业务发展,需要进一步优化查询接口;目前每个人都会操作redis中存放的人员列表,导致该列表会实时发生变动(比如
每个人员对应的分数),每个人都有自己的缓存人员列表而不是统一的人员列表;原列表已经无法满足现需求,每个人第一次登
录都会查询数据库,将自己的列表存放在redis中。
解决方法:设置两级缓存,第一级为该用户(uuid)唯一缓存,key值设置为参数1+uuid+参数2;第二级为第一次登录查询返
回redis中的原始leader列表,key值设置为参数1+参数2。如果当前用户leader列表(一级缓存)为空,则查询原始leader列表
(二级缓存),在操作分数的时候修改二级缓存(初始人员列表)来产生一级缓存,存放进redis,减少了数据库的直接访问。
项目中责任链相关设计类图如下:
说明:抽象类CacheHandler 一是定义了处理请求方法handleMessage;二是定义一个链的编排方法setNext,设置下一个处理者;三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别getHandlerLevel和具体的处理任务response;
FirstCacheHadler为一级缓存处理者,SecondCacheHadler为二级缓存处理者。缓存处理的方式通过CacheableAspect类调用。
CacheableAspect:client调用
- package com.huajie.aspect;
-
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.List;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import com.huajie.annotation.ExtCacheable;
- import com.huajie.common.cache.CacheHandler;
- import com.huajie.common.cache.FirstCacheHadler;
- import com.huajie.common.cache.RedisResult;
- import com.huajie.common.cache.SecondCacheHadler;
- import com.huajie.utils.RedisUtil;
- import com.huajie.utils.StringUtil;
-
- /**
- * redis缓存处理 不适用与内部方法调用(this.)或者private
- */
- @Component
- @Aspect
- public class CacheableAspect {
-
- @Autowired
- private RedisUtil redisUtil;
-
- @Pointcut("@annotation(com.huajie.annotation.ExtCacheable)")
- public void annotationPointcut() {
- }
-
- @Around("annotationPointcut()")
- public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
- // 获得当前访问的class
- Class<?> className = joinPoint.getTarget().getClass();
- // 获得访问的方法名
- String methodName = joinPoint.getSignature().getName();
- // 得到方法的参数的类型
- Class<?>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
- Object[] args = joinPoint.getArgs();
- String key = "";
- String nextKey = "";
- int expireTime = 1800;
- try {
- // 得到访问的方法对象
- Method method = className.getMethod(methodName, argClass);
- method.setAccessible(true);
- // 判断是否存在@ExtCacheable注解
- if (method.isAnnotationPresent(ExtCacheable.class)) {
- ExtCacheable annotation = method.getAnnotation(ExtCacheable.class);
- key = getRedisKey(args, annotation.key());
- nextKey = getRedisKey(args,annotation.nextKey());
- expireTime = getExpireTime(annotation);
- }
- } catch (Exception e) {
- throw new RuntimeException("redis缓存注解参数异常", e);
- }
- //责任链模式
- CacheHandler firstCacheHadler = new FirstCacheHadler();
- CacheHandler secondCacheHadler = new SecondCacheHadler();
- //设置下级处理者
- firstCacheHadler.setNext(secondCacheHadler);
- //获取处理级别
- int cacheLevel = getCacheLevel(key, nextKey);
- RedisResult result = new RedisResult(redisUtil, key, nextKey, joinPoint, cacheLevel, expireTime);
- //客户端调用
- return firstCacheHadler.HandleMessage(result);
- }
-
- private int getCacheLevel(String key, String nextKey) {
- if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(nextKey)) {
- return 2;
- } else {
- return 1;
- }
- }
-
- private int getExpireTime(ExtCacheable annotation) {
- return annotation.expireTime();
- }
-
- private String getRedisKey(Object[] args, String primalKey) {
- // 获取#p0...集合
- List<String> keyList = getKeyParsList(primalKey);
- for (String keyName : keyList) {
- int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", ""));
- Object parValue = args[keyIndex];
- primalKey = primalKey.replace(keyName, String.valueOf(parValue));
- }
- return primalKey.replace("+", "").replace("'", "");
- }
-
- // 获取key中#p0中的参数名称
- private static List<String> getKeyParsList(String key) {
- List<String> ListPar = new ArrayList<String>();
- if (key.indexOf("#") >= 0) {
- int plusIndex = key.substring(key.indexOf("#")).indexOf("+");
- int indexNext = 0;
- String parName = "";
- int indexPre = key.indexOf("#");
- if (plusIndex > 0) {
- indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+");
- parName = key.substring(indexPre, indexNext);
- } else {
- parName = key.substring(indexPre);
- }
- ListPar.add(parName.trim());
- key = key.substring(indexNext + 1);
- if (key.indexOf("#") >= 0) {
- ListPar.addAll(getKeyParsList(key));
- }
- }
- return ListPar;
- }
-
- }
CacheHandler:
- package com.huajie.common.cache;
- /**
- * @author xiewenfeng 缓存处理接口
- * 责任链模式
- */
- public abstract class CacheHandler {
- // 定义处理级别
- protected final static int FirstCache_LEVEL_REQUEST = 1;
- protected final static int SecondCache_LEVEL_REQUEST = 2;
-
- // 能处理的级别
- private int level = 0;
- // 责任传递,下一个责任人是谁
- private CacheHandler nextHandler;
-
- // 每个类自己能处理那些请求
- public CacheHandler(int level) {
- this.level = level;
- }
-
- // 处理请求
- public final Object HandleMessage(RedisResult redisResult) throws Throwable {
- //如果women类型为当前处理的level
- if(redisResult.getCacheLevel()==this.level){
- return this.response(redisResult);
- }else{
- if(null!=this.nextHandler){
- return this.nextHandler.HandleMessage(redisResult);
- }else{
- //没有下级不处理
- return null;
- }
- }
- }
-
- public void setNext(CacheHandler handler) {
- this.nextHandler = handler;
- }
-
- // 有请示的回应
- protected abstract Object response(RedisResult redisResult) throws Throwable;
- }
FirstCacheHadler:一级缓存处理者
- package com.huajie.common.cache;
-
- import org.aspectj.lang.ProceedingJoinPoint;
- import com.huajie.utils.RedisUtil;
-
- public class FirstCacheHadler extends CacheHandler{
-
- public FirstCacheHadler() {
- super(CacheHandler.FirstCache_LEVEL_REQUEST);
- }
-
- @Override
- protected Object response(RedisResult redisResult) throws Throwable {
- String key = redisResult.getKey();
- RedisUtil redisUtil = redisResult.getRedisUtil();
- boolean hasKey = redisUtil.hasKey(key);
- ProceedingJoinPoint joinPoint = redisResult.getJoinPoint();
- int expireTime = redisResult.getExpireTime();
- if (hasKey) {
- return redisUtil.get(key);
- } else {
- Object res = joinPoint.proceed();
- redisUtil.set(key, res);
- redisUtil.expire(key, expireTime);
- return res;
- }
- }
-
- }
SecondCacheHadler:二级缓存处理者
- package com.huajie.common.cache;
-
- import org.aspectj.lang.ProceedingJoinPoint;
- import com.huajie.utils.RedisUtil;
-
- public class SecondCacheHadler extends CacheHandler {
-
- public SecondCacheHadler() {
- super(CacheHandler.SecondCache_LEVEL_REQUEST);
- }
-
- @Override
- protected Object response(RedisResult redisResult) throws Throwable {
- String nextKey = redisResult.getNextKey();
- String key = redisResult.getKey();
- RedisUtil redisUtil = redisResult.getRedisUtil();
- ProceedingJoinPoint joinPoint = redisResult.getJoinPoint();
- int expireTime = redisResult.getExpireTime();
- boolean hasKey = redisUtil.hasKey(key);
- if (hasKey) {
- return redisUtil.get(key);
- } else {
- boolean hasNextKey = redisUtil.hasKey(nextKey);
- if (hasNextKey) {
- return redisUtil.get(nextKey);
- } else {
- Object res = joinPoint.proceed();
- redisUtil.set(nextKey, res);
- redisUtil.expire(nextKey, expireTime);
- return res;
- }
- }
- }
- }
RedisResult:该业务场景对象,用于传递参数
- package com.huajie.common.cache;
-
- import org.aspectj.lang.ProceedingJoinPoint;
- import com.huajie.utils.RedisUtil;
- import lombok.Data;
-
- @Data
- public class RedisResult implements IRedisResult {
- private int cacheLevel;
- private Object result;
- private RedisUtil redisUtil;
- private String key;
- private String nextKey;
- private int expireTime;
- private ProceedingJoinPoint joinPoint;
-
- @Override
- public int getCacheLevel() {
- return cacheLevel;
- }
-
- @Override
- public Object getResult() {
- return result;
- }
-
- public RedisResult(RedisUtil redisUtil, String key, String nextKey, ProceedingJoinPoint joinPoint, int cacheLevel,int expireTime) {
- this.redisUtil = redisUtil;
- this.key = key;
- this.joinPoint = joinPoint;
- this.cacheLevel = cacheLevel;
- this.nextKey = nextKey;
- this.expireTime = expireTime;
- }
-
- }
使用方法如下:
- @Override
- @ExtCacheable(key = "middle+#p0+#p1+#p2", nextKey = "middle+#p0+#p2")
- public List<MiddleManage> listMiddleManageInfo(String leadergroupId, String uuid, String yearDetailId) {
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("leadergroupId", leadergroupId);
- map.put("uuid", uuid);
- map.put("yearDetailId", yearDetailId);
- List<MiddleManage> middleManageDetailList = middleManageMapper.listMiddleManageInfo(map);
- return middleManageDetailList;
- }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。