中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java設計模式中的責任鏈模式是什么

發布時間:2022-01-04 00:29:31 來源:億速云 閱讀:147 作者:柒染 欄目:開發技術

本篇文章為大家展示了java設計模式中的責任鏈模式是什么,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。


一:模式說明

模式定義:使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有對象處理它為止。

責任鏈模式的重點是在“鏈”上,由一條鏈去處理相似的請求在鏈中決定誰來處理這個請求,并返回相應的結果(取自《設計模式之禪》)。

翻譯:Client對象調用一個處理者(類)的方法,可能有多個處理者(實現類),但是該對象只需要調用第一個處理者(類)即可,該模式會自動分配誰來處理這個請求;這多個處理者繼承同一個父類(即在一條鏈上)。

通用類圖如下:

java設計模式中的責任鏈模式是什么

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,減少了數據庫的直接訪問。

項目中責任鏈相關設計類圖如下:

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

上述內容就是java設計模式中的責任鏈模式是什么,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高平市| 布拖县| 荔波县| 乌兰浩特市| 砚山县| 广安市| 炎陵县| 五指山市| 江口县| 泸定县| 昆山市| 永吉县| 高陵县| 莲花县| 仲巴县| 惠来县| 永靖县| 沙田区| 科技| 化隆| 上杭县| 进贤县| 涪陵区| 临夏市| 乐至县| 安化县| 濮阳县| 梅河口市| 万年县| 德安县| 青浦区| 平山县| 广西| 平果县| 泰来县| 唐山市| 仁寿县| 瑞安市| 汨罗市| 科尔| 穆棱市|