欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java設(shè)計(jì)模式(實(shí)戰(zhàn))-責(zé)任鏈模式

 更新時(shí)間:2022年01月03日 12:53:16   作者:不懂的浪漫  
這篇文章主要介紹了java設(shè)計(jì)模式(實(shí)戰(zhàn))-責(zé)任鏈模式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一:模式說(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)

在文章 >手寫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)用

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緩存處理 不適用與內(nèi)部方法調(diào)用(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 {
		// 獲得當(dāng)前訪問(wèn)的class
		Class<?> className = joinPoint.getTarget().getClass();
		// 獲得訪問(wèn)的方法名
		String methodName = joinPoint.getSignature().getName();
		// 得到方法的參數(shù)的類型
		Class<?>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
		Object[] args = joinPoint.getArgs();
		String key = "";
		String nextKey = "";
		int expireTime = 1800;
		try {
			// 得到訪問(wèn)的方法對(duì)象
			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緩存注解參數(shù)異常", e);
		}
		//責(zé)任鏈模式
		CacheHandler firstCacheHadler = new FirstCacheHadler();
		CacheHandler secondCacheHadler = new SecondCacheHadler();
		//設(shè)置下級(jí)處理者
		firstCacheHadler.setNext(secondCacheHadler);
		//獲取處理級(jí)別
		int cacheLevel = getCacheLevel(key, nextKey);
		RedisResult result = new RedisResult(redisUtil, key, nextKey, joinPoint, cacheLevel, expireTime);
		//客戶端調(diào)用
		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中的參數(shù)名稱
	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 緩存處理接口
 * 責(zé)任鏈模式
 */
public abstract class CacheHandler {
	// 定義處理級(jí)別
	protected final static int FirstCache_LEVEL_REQUEST = 1;
	protected final static int SecondCache_LEVEL_REQUEST = 2;
 
	// 能處理的級(jí)別
	private int level = 0;
	// 責(zé)任傳遞,下一個(gè)責(zé)任人是誰(shuí)
	private CacheHandler nextHandler;
 
	// 每個(gè)類自己能處理那些請(qǐng)求
	public CacheHandler(int level) {
		this.level = level;
	}
 
	// 處理請(qǐng)求
	public final Object HandleMessage(RedisResult redisResult) throws Throwable {
		//如果women類型為當(dāng)前處理的level
		if(redisResult.getCacheLevel()==this.level){
			return this.response(redisResult);
		}else{
			 if(null!=this.nextHandler){
				 return this.nextHandler.HandleMessage(redisResult);
			 }else{
				 //沒(méi)有下級(jí)不處理
				 return null;
			 }
		}
	}
 
	public void setNext(CacheHandler handler) {
		this.nextHandler = handler;
	}
 
	// 有請(qǐng)示的回應(yīng)
	protected abstract Object response(RedisResult redisResult) throws Throwable;
}

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

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:二級(jí)緩存處理者

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:該業(yè)務(wù)場(chǎng)景對(duì)象,用于傳遞參數(shù)

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java concurrency集合之CopyOnWriteArraySet_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java concurrency集合之CopyOnWriteArraySet_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    CopyOnWriteArraySet基于CopyOnWriteArrayList實(shí)現(xiàn),其唯一的不同是在add時(shí)調(diào)用的是CopyOnWriteArrayList的addIfAbsent(若沒(méi)有則增加)方法
    2017-06-06
  • Java基于JavaMail實(shí)現(xiàn)向QQ郵箱發(fā)送郵件

    Java基于JavaMail實(shí)現(xiàn)向QQ郵箱發(fā)送郵件

    這篇文章主要為大家詳細(xì)介紹了Java基于JavaMail實(shí)現(xiàn)向QQ郵箱發(fā)送郵件的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Netty分布式客戶端處理接入事件handle源碼解析

    Netty分布式客戶端處理接入事件handle源碼解析

    這篇文章主要為大家介紹了Netty源碼分析客戶端流程處理接入事件handle創(chuàng)建,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • HashMap紅黑樹(shù)入門(實(shí)現(xiàn)一個(gè)簡(jiǎn)單的紅黑樹(shù))

    HashMap紅黑樹(shù)入門(實(shí)現(xiàn)一個(gè)簡(jiǎn)單的紅黑樹(shù))

    紅黑樹(shù)(Red Black Tree) 是一種自平衡二叉查找樹(shù),是在計(jì)算機(jī)科學(xué)中用到的一種數(shù)據(jù)結(jié)構(gòu),典型的用途是實(shí)現(xiàn)關(guān)聯(lián)數(shù)組。 紅黑樹(shù)發(fā)明時(shí)被稱為平衡二叉B樹(shù),后來(lái)修改為如今的“紅黑樹(shù)”
    2021-06-06
  • Java使用BouncyCastle加密

    Java使用BouncyCastle加密

    本文主要介紹了Java使用BouncyCastle加密,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 通過(guò)Feign進(jìn)行調(diào)用@FeignClient?找不到的解決方案

    通過(guò)Feign進(jìn)行調(diào)用@FeignClient?找不到的解決方案

    這篇文章主要介紹了通過(guò)Feign進(jìn)行調(diào)用@FeignClient?找不到的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java基本數(shù)據(jù)類型族譜與易錯(cuò)點(diǎn)梳理解析

    Java基本數(shù)據(jù)類型族譜與易錯(cuò)點(diǎn)梳理解析

    Java有八大基本類型,很多同學(xué)只對(duì)經(jīng)常使用的int類型比較了解。有的同學(xué)是剛從C語(yǔ)言轉(zhuǎn)入Java學(xué)習(xí),誤以為兩者的基本數(shù)據(jù)類型完全相同,這也是大錯(cuò)特錯(cuò)的。今天這本Java基本數(shù)據(jù)類型全解析大字典,可以幫助你直接通過(guò)目錄找到你想要了解某一種基本數(shù)據(jù)類型
    2022-01-01
  • 詳解springboot解決CORS跨域的三種方式

    詳解springboot解決CORS跨域的三種方式

    本文主要介紹了詳解springboot解決CORS跨域的三種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • java實(shí)現(xiàn)單詞查詢小程序

    java實(shí)現(xiàn)單詞查詢小程序

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)單詞查詢小程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • RocketMQMessageListener注解對(duì)rocketmq消息的消費(fèi)實(shí)現(xiàn)機(jī)制

    RocketMQMessageListener注解對(duì)rocketmq消息的消費(fèi)實(shí)現(xiàn)機(jī)制

    這篇文章主要為大家介紹了RocketMQMessageListener注解對(duì)rocketmq消息的消費(fèi)實(shí)現(xiàn)機(jī)制源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10

最新評(píng)論