spring版責(zé)任鏈模式
責(zé)任鏈模式顧名思義就是。執(zhí)行一串業(yè)務(wù)處理,像鏈子一樣,從上向下,一個(gè)節(jié)點(diǎn)一個(gè)節(jié)點(diǎn)有序執(zhí)行,中間任何一個(gè)節(jié)點(diǎn)掛啦,鏈子就斷了,不會(huì)繼續(xù)向下執(zhí)行
實(shí)現(xiàn)思路就是把一個(gè)個(gè)處理器類放到一個(gè)數(shù)組list中,遍歷數(shù)組,從第一個(gè)到末尾一個(gè)個(gè)執(zhí)行 handle 方法,數(shù)組list就是一個(gè)鏈子,一個(gè)個(gè)對(duì)象的處理方法就是責(zé)任,合起來(lái)就是責(zé)任鏈咯!
import org.springframework.lang.Nullable;
/**
* 描述: 業(yè)務(wù)處理頂級(jí)攔截器接口 </br>
* 時(shí)間: 2021-03-02 14:46 </br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
public interface HandleIntercept {
/**
* 業(yè)務(wù)頂級(jí)接口處理接口
* @param model 泛型參數(shù)
* @return 成功的對(duì)象返回,可以是boolean,string,model
*/
Object handle(@Nullable Object model);
}
第一個(gè)業(yè)務(wù)處理攔截器
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 描述: 第一個(gè)業(yè)務(wù)處理攔截器 </br>
* 時(shí)間: 2021-03-02 14:57 </br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Order(2)
@Component
public class FirstHandleIntercept implements HandleIntercept {
@Override
public Object handle(Object model) {
System.out.println("========執(zhí)行 firstHandleIntercept 開始業(yè)務(wù)處理 =======");
return true;
}
}
第二業(yè)務(wù)處理器
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 描述: 第二業(yè)務(wù)處理器 </br>
* 時(shí)間: 2021-03-02 15:02 </br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Order(1)
@Component
public class SecondHandleIntercept implements HandleIntercept {
@Override
public Object handle(Object model) {
System.out.println("========執(zhí)行 SecondHandleIntercept =======");
return true;
}
}
第三業(yè)務(wù)處理器
import org.springframework.stereotype.Component;
/**
* 描述: 第二業(yè)務(wù)處理器 </br>
* 時(shí)間: 2021-03-02 15:02 </br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
//@Order(1)
@Component
public class ThirdHandleIntercept implements HandleIntercept {
@Override
public Object handle(Object model) {
System.out.println("========執(zhí)行 ThirdHandleIntercept =======");
return true;
}
}
業(yè)務(wù)處理器門面入口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 描述: 業(yè)務(wù)處理器門面入口 </br>
* 時(shí)間: 2021-03-02 15:05 </br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Component
public class HandleInterceptEntrance {
@Autowired
private Map<String, HandleIntercept> HandleInterceptBeanMap = new ConcurrentHashMap<>();
//業(yè)務(wù)鏈?zhǔn)教幚砥鱨ist
private static List<HandleIntercept> HandleInterceptList = new ArrayList<>();
/**
* 鏈?zhǔn)教幚砣肟?,類似門面
*/
public void handleEntrance() {
if (CollectionUtils.isEmpty(HandleInterceptList)){
getHandleInterceptList ();
}
for (HandleIntercept handleIntercept : HandleInterceptList) {
//要注入?yún)?shù),可以在此處理
handleIntercept.handle(null);
}
}
/**
* 處理攔截器拍尋,解決order排序不生效問(wèn)題
* 并把HandleIntercept注入到HandleInterceptList中
*/
@PostConstruct
private synchronized void getHandleInterceptList () {
//存貯不帶order注解的攔截器容器list
List<HandleIntercept> noOrderHandleInterceptList = new ArrayList<>();
//存貯帶order注解的攔截器容器list
List<HandleIntercept> orderHandleInterceptList = new ArrayList<>();
//處理HandleIntercept的springioc容器中的HandleIntercept,處理到
//noOrderHandleInterceptList和orderHandleInterceptList
for (String beanName : HandleInterceptBeanMap.keySet()) {
HandleIntercept handleIntercept = HandleInterceptBeanMap.get(beanName);
//獲取order注解
Order order = handleIntercept.getClass().getAnnotation(Order.class);
if (ObjectUtils.isEmpty(order)){
noOrderHandleInterceptList.add(handleIntercept);
}else {
orderHandleInterceptList.add(handleIntercept);
}
}
//對(duì)orderHandleInterceptList進(jìn)行oder注解的value值升序排列
if (!CollectionUtils.isEmpty(orderHandleInterceptList)){
Collections.sort(orderHandleInterceptList, new Comparator<HandleIntercept>() {
@Override
public int compare(HandleIntercept h1, HandleIntercept h2) {
//升序
Integer value1 = h1.getClass().getAnnotation(Order.class).value();
Integer value2 = h2.getClass().getAnnotation(Order.class).value();
return value1.compareTo(value2);
}
});
}
//優(yōu)先orderHandleInterceptList注入HandleInterceptList
HandleInterceptList.addAll(orderHandleInterceptList);
HandleInterceptList.addAll(noOrderHandleInterceptList);
}
}
使用示例demo
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/test")
public class HandleController {
@Autowired
private HandleInterceptEntrance handleEntrance;
@GetMapping("/handleEntrance")
public void test() {
handleEntrance.handleEntrance();
}
}
責(zé)任鏈模式顧名思義就是。執(zhí)行一串業(yè)務(wù)處理,像鏈子一樣,從上向下,一個(gè)節(jié)點(diǎn)一個(gè)節(jié)點(diǎn)有序執(zhí)行,中間任何一個(gè)節(jié)點(diǎn)掛啦,鏈子就斷了,不會(huì)繼續(xù)向下執(zhí)行
實(shí)現(xiàn)思路就是把一個(gè)個(gè)處理器類放到一個(gè)數(shù)組list中,遍歷數(shù)組,從第一個(gè)到末尾一個(gè)個(gè)執(zhí)行 handle 方法,數(shù)組list就是一個(gè)鏈子,一個(gè)個(gè)對(duì)象的處理方法就是責(zé)任,合起來(lái)就是責(zé)任鏈咯!
其實(shí)這里面包含了,工廠模式,單例模式。門面模式和責(zé)任鏈綜合使用,很多情況都是多種模式配合使用
看明白后,要自己動(dòng)手玩玩吧,自己寫,不要抄,實(shí)在搞不定,再看看,不要copy,使用場(chǎng)景需要一連串的不同的業(yè)務(wù)處理的操作場(chǎng)景,可以考慮責(zé)任鏈,經(jīng)典場(chǎng)景:ip很名單處理 ->登錄處理 -> 權(quán)限處理等類似不同處理維度的連續(xù)不間斷處理,考慮責(zé)任鏈
作者:IT學(xué)習(xí)道場(chǎng)
歡迎關(guān)注微信公眾號(hào) : IT學(xué)習(xí)道場(chǎng)