java設(shè)計(jì)模式(實(shí)戰(zhàn))_第1頁(yè)
java設(shè)計(jì)模式(實(shí)戰(zhàn))_第2頁(yè)
java設(shè)計(jì)模式(實(shí)戰(zhàn))_第3頁(yè)
java設(shè)計(jì)模式(實(shí)戰(zhàn))_第4頁(yè)
java設(shè)計(jì)模式(實(shí)戰(zhàn))_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第java設(shè)計(jì)模式(實(shí)戰(zhàn))目錄一:模式說(shuō)明二:項(xiàng)目實(shí)戰(zhàn)三:源代碼

一:模式說(shuō)明

模式定義:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免了請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有對(duì)象處理它為止。

責(zé)任鏈模式的重點(diǎn)是在鏈上,由一條鏈去處理相似的請(qǐng)求在鏈中決定誰(shuí)來(lái)處理這個(gè)請(qǐng)求,并返回相應(yīng)的結(jié)果(取自《設(shè)計(jì)模式之禪》)。

翻譯:Client對(duì)象調(diào)用一個(gè)處理者(類)的方法,可能有多個(gè)處理者(實(shí)現(xiàn)類),但是該對(duì)象只需要調(diào)用第一個(gè)處理者(類)即可,該模式會(huì)自動(dòng)分配誰(shuí)來(lái)處理這個(gè)請(qǐng)求;這多個(gè)處理者繼承同一個(gè)父類(即在一條鏈上)。

通用類圖如下:

Client發(fā)送請(qǐng)求到Handler,Handler自動(dòng)分配請(qǐng)求到子類的實(shí)現(xiàn)類ConcreteHandler中。

二:項(xiàng)目實(shí)戰(zhàn)

在文章手寫(xiě)redis@Cacheable注解支持過(guò)期時(shí)間設(shè)置的基礎(chǔ)之上做修改,原版為redis緩存注解實(shí)現(xiàn),

原版實(shí)現(xiàn)功能:

將數(shù)據(jù)存放到redis中設(shè)置過(guò)期時(shí)間

原業(yè)務(wù)邏輯查詢?nèi)藛T列表listleader()接口,數(shù)據(jù)存放redis中,減少數(shù)據(jù)庫(kù)負(fù)載。

由于業(yè)務(wù)發(fā)展,需要進(jìn)一步優(yōu)化查詢接口;目前每個(gè)人都會(huì)操作redis中存放的人員列表,導(dǎo)致該列表會(huì)實(shí)時(shí)發(fā)生變動(dòng)(比如

每個(gè)人員對(duì)應(yīng)的分?jǐn)?shù)),每個(gè)人都有自己的緩存人員列表而不是統(tǒng)一的人員列表;原列表已經(jīng)無(wú)法滿足現(xiàn)需求,每個(gè)人第一次登

錄都會(huì)查詢數(shù)據(jù)庫(kù),將自己的列表存放在redis中。

解決方法:設(shè)置兩級(jí)緩存,第一級(jí)為該用戶(uuid)唯一緩存,key值設(shè)置為參數(shù)1+uuid+參數(shù)2;第二級(jí)為第一次登錄查詢返

回redis中的原始leader列表,key值設(shè)置為參數(shù)1+參數(shù)2。如果當(dāng)前用戶leader列表(一級(jí)緩存)為空,則查詢?cè)糽eader列表

(二級(jí)緩存),在操作分?jǐn)?shù)的時(shí)候修改二級(jí)緩存(初始人員列表)來(lái)產(chǎn)生一級(jí)緩存,存放進(jìn)redis,減少了數(shù)據(jù)庫(kù)的直接訪問(wèn)。

項(xiàng)目中責(zé)任鏈相關(guān)設(shè)計(jì)類圖如下:

說(shuō)明:抽象類CacheHandler一是定義了處理請(qǐng)求方法handleMessage;二是定義一個(gè)鏈的編排方法setNext,設(shè)置下一個(gè)處理者;三是定義了具體的請(qǐng)求者必須實(shí)現(xiàn)的兩個(gè)方法:定義自己能夠處理的級(jí)別getHandlerLevel和具體的處理任務(wù)response;

FirstCacheHadler為一級(jí)緩存處理者,SecondCacheHadler為二級(jí)緩存處理者。緩存處理的方式通過(guò)CacheableAspect類調(diào)用。

三:源代碼

CacheableAspect:client調(diào)用

packagecom.huajie.aspect;

importjava.lang.reflect.Method;

importjava.util.ArrayList;

importjava.util.List;

importorg.aspectj.lang.ProceedingJoinPoint;

importorg.aspectj.lang.annotation.Around;

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Pointcut;

importorg.aspectj.lang.reflect.MethodSignature;

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.stereotype.Component;

importcom.huajie.annotation.ExtCacheable;

importmon.cache.CacheHandler;

importmon.cache.FirstCacheHadler;

importmon.cache.RedisResult;

importmon.cache.SecondCacheHadler;

importcom.huajie.utils.RedisUtil;

importcom.huajie.utils.StringUtil;

*redis緩存處理不適用與內(nèi)部方法調(diào)用(this.)或者private

@Component

@Aspect

publicclassCacheableAspect{

@Autowired

privateRedisUtilredisUtil;

@Pointcut("@annotation(com.huajie.annotation.ExtCacheable)")

publicvoidannotationPointcut(){

@Around("annotationPointcut()")

publicObjectdoAround(ProceedingJoinPointjoinPoint)throwsThrowable{

//獲得當(dāng)前訪問(wèn)的class

ClassclassName=joinPoint.getTarget().getClass();

//獲得訪問(wèn)的方法名

StringmethodName=joinPoint.getSignature().getName();

//得到方法的參數(shù)的類型

Class[]argClass=((MethodSignature)joinPoint.getSignature()).getParameterTypes();

Object[]args=joinPoint.getArgs();

Stringkey="";

StringnextKey="";

intexpireTime=1800;

try{

//得到訪問(wèn)的方法對(duì)象

Methodmethod=className.getMethod(methodName,argClass);

method.setAccessible(true);

//判斷是否存在@ExtCacheable注解

if(method.isAnnotationPresent(ExtCacheable.class)){

ExtCacheableannotation=method.getAnnotation(ExtCacheable.class);

key=getRedisKey(args,annotation.key());

nextKey=getRedisKey(args,annotation.nextKey());

expireTime=getExpireTime(annotation);

}catch(Exceptione){

thrownewRuntimeException("redis緩存注解參數(shù)異常",e);

//責(zé)任鏈模式

CacheHandlerfirstCacheHadler=newFirstCacheHadler();

CacheHandlersecondCacheHadler=newSecondCacheHadler();

//設(shè)置下級(jí)處理者

firstCacheHadler.setNext(secondCacheHadler);

//獲取處理級(jí)別

intcacheLevel=getCacheLevel(key,nextKey);

RedisResultresult=newRedisResult(redisUtil,key,nextKey,joinPoint,cacheLevel,expireTime);

//客戶端調(diào)用

returnfirstCacheHadler.HandleMessage(result);

privateintgetCacheLevel(Stringkey,StringnextKey){

if(StringUtil.isNotEmpty(key)StringUtil.isNotEmpty(nextKey)){

return2;

}else{

return1;

privateintgetExpireTime(ExtCacheableannotation){

returnannotation.expireTime();

privateStringgetRedisKey(Object[]args,StringprimalKey){

//獲取#p0...集合

ListStringkeyList=getKeyParsList(primalKey);

for(StringkeyName:keyList){

intkeyIndex=Integer.parseInt(keyName.toLowerCase().replace("#p",""));

ObjectparValue=args[keyIndex];

primalKey=primalKey.replace(keyName,String.valueOf(parValue));

returnprimalKey.replace("+","").replace("'","");

//獲取key中#p0中的參數(shù)名稱

privatestaticListStringgetKeyParsList(Stringkey){

ListStringListPar=newArrayListString

if(key.indexOf("#")=0){

intplusIndex=key.substring(key.indexOf("#")).indexOf("+");

intindexNext=0;

StringparName="";

intindexPre=key.indexOf("#");

if(plusIndex0){

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));

returnListPar;

}

CacheHandler:

packagemon.cache;

*@authorxiewenfeng緩存處理接口

*責(zé)任鏈模式

publicabstractclassCacheHandler{

//定義處理級(jí)別

protectedfinalstaticintFirstCache_LEVEL_REQUEST=1;

protectedfinalstaticintSecondCache_LEVEL_REQUEST=2;

//能處理的級(jí)別

privateintlevel=0;

//責(zé)任傳遞,下一個(gè)責(zé)任人是誰(shuí)

privateCacheHandlernextHandler;

//每個(gè)類自己能處理那些請(qǐng)求

publicCacheHandler(intlevel){

this.level=level;

//處理請(qǐng)求

publicfinalObjectHandleMessage(RedisResultredisResult)throwsThrowable{

//如果women類型為當(dāng)前處理的level

if(redisResult.getCacheLevel()==this.level){

returnthis.response(redisResult);

}else{

if(null!=this.nextHandler){

returnthis.nextHandler.HandleMessage(redisResult);

}else{

//沒(méi)有下級(jí)不處理

returnnull;

publicvoidsetNext(CacheHandlerhandler){

this.nextHandler=handler;

//有請(qǐng)示的回應(yīng)

protectedabstractObjectresponse(RedisResultredisResult)throwsThrowable;

}

FirstCacheHadler:一級(jí)緩存處理者

packagemon.cache;

importorg.aspectj.lang.ProceedingJoinPoint;

importcom.huajie.utils.RedisUtil;

publicclassFirstCacheHadlerextendsCacheHandler{

publicFirstCacheHadler(){

super(CacheHandler.FirstCache_LEVEL_REQUEST);

@Override

protectedObjectresponse(RedisResultredisResult)throwsThrowable{

Stringkey=redisResult.getKey();

RedisUtilredisUtil=redisResult.getRedisUtil();

booleanhasKey=redisUtil.hasKey(key);

ProceedingJoinPointjoinPoint=redisResult.getJoinPoint();

intexpireTime=redisResult.getExpireTime();

if(hasKey){

returnredisUtil.get(key);

}else{

Objectres=joinPceed();

redisUtil.set(key,res);

redisUtil.expire(key,expireTime);

returnres;

}

SecondCacheHadler:二級(jí)緩存處理者

packagemon.cache;

importorg.aspectj.lang.ProceedingJoinPoint;

importcom.huajie.utils.RedisUtil;

publicclassSecondCacheHadlerextendsCacheHandler{

publicSecondCacheHadler(){

super(CacheHandler.SecondCache_LEVEL_REQUEST);

@Override

protectedObjectresponse(RedisResultredisResult)throwsThrowable{

StringnextKey=redisResult.getNextKey();

Stringkey=redisResult.getKey();

RedisUtilredisUtil=redisResult.getRedisUtil();

ProceedingJoinPointjoinPoint=redisResult.getJoinPoint();

intexpireTime=redisResult.getExpireTime();

booleanhasKey=redisUtil.hasKey(key);

if(hasKey){

returnredisUtil.get(key);

}else{

booleanhasNextKey=redisUtil.hasKey(nextKey);

if(hasNextKey){

returnredisUtil.get(nextKey);

}else{

Objectres=joinPceed();

redisUtil.set(nextKey,res);

redisUtil.expire(nextKey,expireTime);

returnres;

}

RedisResult:該業(yè)務(wù)場(chǎng)景對(duì)象,用于傳遞參數(shù)

packagemon.cache;

importorg.aspectj.lang.ProceedingJoinPoint;

importcom.huajie.utils.RedisUtil;

importlombok.Data;

@Data

publicclassRedisResultimplementsIRedisResult{

privateintcacheLevel;

privateObjectresult;

privateRedisUtilredisUtil;

privateStringkey;

privateStringnextKey;

privateintexpireTime;

privateProceedingJoinPointjoinPoint;

@Override

publicintgetCacheLevel(){

returncacheLevel;

@Override

public

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論