模式定义:银行汇款使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果(取自《设计模式之禅》)。
翻译:client对象调用一个处理者(类)的方法,可能有多个处理者(实现类),但是该对象只需要调用第一个处理者(类)即可,该模式会自动分配谁来处理这个请求;这多个处理者继承同一个父类(即在一条链上)。
通用类图如下:
client发送请求到handler,handler自动分配请求到子类的实现类concretehandler中。
在文章 >手写redis@cacheable注解 支持过期时间设置<的基础之上做修改,原版为redis缓存注解实现,
原版实现功能:
将数据存放到redis中设置过期时间原业务逻辑查询人员列表listleader()接口,数据存放redis中,减少数据库负载。
由于业务发展,需要进一步优化查询接口;目前每个人都会操作redis中存放的人员列表,导致该列表会实时发生变动(比如
每个人员对应的分数),每个人都有自己的缓存人员列表而不是统一的人员列表;原列表已经无法满足现需求,每个人第一次登
录都会查询数据库,将自己的列表存放在redis中。
解决方法:设置两级缓存,第一级为该用户(uuid)唯一缓存,key值设置为参数1+uuid+参数2;第二级为第一次登录查询返
回redis中的原始leader列表,key值设置为参数1+参数2。如果当前用户leader列表(一级缓存)为空,则查询原始leader列表
(二级缓存),在操作分数的时候修改二级缓存(初始人员列表)来产生一级缓存,存放进redis,减少了数据库的直接访问。
项目中责任链相关设计类图如下:
说明:抽象类cachehandler 一是定义了处理请求方法h星期英语缩写andlemessage;二是定义一个链的编排方法tnext,设置下一个处理者;三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别gethandlerlevel和具体的处理任务respon;
firstcachehadler为一级缓存处理者,condcachehadler为二级缓存处理者。缓存处理的方式通过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.condcachehadler;import com.huajie.utils.redisutil;import com.huajie.utils.stringutil; /** * redis缓存处理 不适用与内部方法调用(this.)或者private */@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.taccessible(true);// 判断是否存在@extcacheable注解if (method.isannotationprent(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 condcachehadler = new condcachehadler();//设置下级处理者firstcachehadler.tnext(condcachehadler);//获取处理级别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;} el {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.parint(keyname.tolowerca().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<stri电影院用英语怎么说ng>();if (key.indexof("#") >= 0) {int plusindex = key.substring(ke生物科学考研方向y.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);} el {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 condcache_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.respon(redisresult);}el{ if(null!=this.nexthandler){ return this.nexthandler.handlemessage(redisresult); }el{ //没有下级不处理 return null; }}} public void tnext(cachehandler handler) {this.nexthandler = handler;} // 有请示的回应protected abstract object respon(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 respon(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);} el {object res = joinpoint.proceed();redisutil.t(key, res);redisutil.expire(key, expiretime);return res;}} }
condcachehadler:二级缓存处理者
package com.huajie.common.cache; import org.aspectj.lang.proceedingjoinpoint;import com.huajie.utils.redisutil; 利用的拼音public class condcachehadler extends cachehandler { public condcachehadler() {super(cachehandler.condcache_level_request);} @overrideprotected object respon(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);} el {boolean hasnextkey = redisutil.haskey(nextkey);if (hasnextkey) {return redisutil.get(nextkey);} el {object res = joinpoint.proceed();redisutil.t(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;}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。
本文发布于:2023-04-04 09:45:45,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/91b2b2431907b5ec728871116c6174d2.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:java设计模式(实战).doc
本文 PDF 下载地址:java设计模式(实战).pdf
留言与评论(共有 0 条评论) |