文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

java设计模式中的责任链模式是什么

2023-06-22 07:56

关注

本篇文章为大家展示了java设计模式中的责任链模式是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。


一:模式说明

模式定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果(取自《设计模式之禅》)。

翻译:Client对象调用一个处理者(类)的方法,可能有多个处理者(实现类),但是该对象只需要调用第一个处理者(类)即可,该模式会自动分配谁来处理这个请求;这多个处理者继承同一个父类(即在一条链上)。

通用类图如下:

java设计模式中的责任链模式是什么

Client发送请求到Handler,Handler自动分配请求到子类的实现类ConcreteHandler中。

二:项目实战

在文章 >手写redis@Cacheable注解 支持过期时间设置< 的基础之上做修改,原版为redis缓存注解实现,

原版实现功能:

原业务逻辑查询人员列表listleader()接口,数据存放redis中,减少数据库负载。

由于业务发展,需要进一步优化查询接口;目前每个人都会操作redis中存放的人员列表,导致该列表会实时发生变动(比如

每个人员对应的分数),每个人都有自己的缓存人员列表而不是统一的人员列表;原列表已经无法满足现需求,每个人第一次登

录都会查询数据库,将自己的列表存放在redis中。

解决方法:设置两级缓存,第一级为该用户(uuid)唯一缓存,key值设置为参数1+uuid+参数2;第二级为第一次登录查询返  

回redis中的原始leader列表,key值设置为参数1+参数2。如果当前用户leader列表(一级缓存)为空,则查询原始leader列表

(二级缓存),在操作分数的时候修改二级缓存(初始人员列表)来产生一级缓存,存放进redis,减少了数据库的直接访问。

项目中责任链相关设计类图如下:

java设计模式中的责任链模式是什么

说明:抽象类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; @Component@Aspectpublic class CacheableAspect { @Autowiredprivate RedisUtil redisUtil; @Pointcut("@annotation(com.huajie.annotation.ExtCacheable)")public void annotationPointcut() {} @Around("annotationPointcut()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {// 获得当前访问的classClass<?> 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;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类型为当前处理的levelif(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);} @Overrideprotected 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);} @Overrideprotected 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; @Datapublic 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; @Overridepublic int getCacheLevel() {return cacheLevel;} @Overridepublic 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;}

上述内容就是java设计模式中的责任链模式是什么,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯