偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

巧妙利用 SpringBoot 責(zé)任連模式,讓編程事半功倍!

開(kāi)發(fā) 前端
本文主要圍繞在 SpringBoot 中如何引入責(zé)任鏈設(shè)計(jì)模式,介紹了三種玩法,其中第二種用法最多,其次就是第一種,第三種用的比較少,第三種本質(zhì)是一種鏈?zhǔn)綄?xiě)法,可能理解上不如第一種直觀,但是效果是一樣的。

一、什么是責(zé)任鏈模式?

責(zé)任鏈模式(Chain of Responsibility Pattern),顧名思義,為請(qǐng)求者和接受者之間創(chuàng)建一條對(duì)象處理鏈路,避免請(qǐng)求發(fā)送者與接收者耦合在一起!

圖片

責(zé)任鏈模式,是一種實(shí)用性非常強(qiáng)的設(shè)計(jì)模式,比較典型的應(yīng)用場(chǎng)景有:

  • Apache Tomcat 對(duì) Encoding 編碼處理的處理
  • SpringBoot ??的攔截器、過(guò)濾器鏈
  • netty 中的處理鏈
  • 支付風(fēng)控的機(jī)制
  • ?志處理級(jí)別

尤其是當(dāng)程序的處理流程很長(zhǎng)的時(shí)候,采用責(zé)任鏈設(shè)計(jì)模式,不僅實(shí)現(xiàn)優(yōu)雅,而且易復(fù)用可擴(kuò)展!

今天我們就一起來(lái)了解一下在 SpringBoot 中如何應(yīng)用責(zé)任鏈模式!

二、代碼實(shí)踐

在 SpringBoot 中,責(zé)任鏈模式的實(shí)踐方式有好幾種,今天我們主要抽三種實(shí)踐方式給大家介紹。

我們以某下單流程為例,將其切成多個(gè)獨(dú)立檢查邏輯,可能會(huì)經(jīng)過(guò)的數(shù)據(jù)驗(yàn)證處理流程如下:

圖片

采用責(zé)任鏈設(shè)計(jì)模式來(lái)編程,代碼實(shí)踐如下!

2.1、方式一

首先,我們定義一個(gè)簡(jiǎn)易版的下單對(duì)象OrderContext。

public class OrderContext {

    /**
     * 請(qǐng)求唯一序列ID
     */
    private String seqId;

    /**
     * 用戶ID
     */
    private String userId;

    /**
     * 產(chǎn)品skuId
     */
    private Long skuId;

    /**
     * 下單數(shù)量
     */
    private Integer amount;

    /**
     * 用戶收貨地址ID
     */
    private String userAddressId;

 //..set、get
}

然后,我們定義一個(gè)數(shù)據(jù)處理接口OrderHandleIntercept,用于標(biāo)準(zhǔn)化執(zhí)行!

public interface OrderHandleIntercept {

    /**
     * 指定執(zhí)行順序
     * @return
     */
    int sort();

    /**
     * 對(duì)參數(shù)進(jìn)行處理
     * @param context
     * @return
     */
    OrderAddContext handle(OrderAddContext context);
}

接著,我們分別創(chuàng)建三個(gè)不同的接口實(shí)現(xiàn)類,并指定執(zhí)行順序,內(nèi)容如下:

  • RepeatOrderHandleInterceptService:用于重復(fù)下單的邏輯驗(yàn)證
  • ValidOrderHandleInterceptService:用于驗(yàn)證請(qǐng)求參數(shù)是否合法
  • BankOrderHandleInterceptService:用于檢查客戶賬戶余額是否充足
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {

    @Override
    public int sort() {
        //用于重復(fù)下單的邏輯驗(yàn)證,在執(zhí)行順序?yàn)?
        return 1;
    }

    @Override
    public OrderAddContext handle(OrderAddContext context) {
        System.out.println("通過(guò)seqId,檢查客戶是否重復(fù)下單");
        return context;
    }
}
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {


    @Override
    public int sort() {
        //用于驗(yàn)證請(qǐng)求參數(shù)是否合法,執(zhí)行順序?yàn)?
        return 2;
    }

    @Override
    public OrderAddContext handle(OrderAddContext context) {
        System.out.println("檢查請(qǐng)求參數(shù),是否合法,并且獲取客戶的銀行賬戶");
        return context;
    }
}
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {


    @Override
    public int sort() {
        //用于檢查客戶賬戶余額是否充足,在執(zhí)行順序?yàn)?
        return 3;
    }

    @Override
    public OrderAddContext handle(OrderAddContext context) {
        System.out.println("檢查銀行賬戶是否合法,調(diào)用銀行系統(tǒng)檢查銀行賬戶余額是否滿足下單金額");
        return context;
    }
}

再然后,我們還需要?jiǎng)?chuàng)建一個(gè)訂單數(shù)據(jù)驗(yàn)證管理器OrderHandleChainService,用于管理這些實(shí)現(xiàn)類。

@Component
public class OrderHandleChainService implements ApplicationContextAware {

    private List<OrderHandleIntercept> handleList = new ArrayList<>();


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //獲取指定的接口實(shí)現(xiàn)類,并按照sort進(jìn)行排序,放入List中
        Map<String, OrderHandleIntercept> serviceMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);
        handleList = serviceMap.values().stream()
                .sorted(Comparator.comparing(OrderHandleIntercept::sort))
                .collect(Collectors.toList());
    }

    /**
     * 執(zhí)行處理
     * @param context
     * @return
     */
    public OrderAddContext execute(OrderAddContext context){
        for (OrderHandleIntercept handleIntercept : handleList) {
            context =handleIntercept.handle(context);
        }
        return context;
    }
}

最后,我們編寫(xiě)單元測(cè)試來(lái)看看效果如何!

@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private OrderHandleChainService orderHandleChainService;

    @Test
    public void test(){
        orderHandleChainService.execute(new OrderAddContext());
    }
}

執(zhí)行結(jié)果如下:

通過(guò)seqId,檢查客戶是否重復(fù)下單
檢查請(qǐng)求參數(shù),是否合法,并且獲取客戶的銀行賬戶
檢查銀行賬戶是否合法,調(diào)用銀行系統(tǒng)檢查銀行賬戶余額是否滿足下單金額

如果需要繼續(xù)加驗(yàn)證流程或者處理流程,只需要重新實(shí)現(xiàn)OrderHandleIntercept接口就行,其他的代碼無(wú)需改動(dòng)!

當(dāng)然,有的同學(xué)可能覺(jué)得這種方法用的不習(xí)慣,不喜歡通過(guò)sort()來(lái)指定順序,也可以通過(guò)如下方式進(jìn)行手動(dòng)add排序。

@Component
public class OrderHandleChainService {

    private List<OrderHandleIntercept> handleList = new ArrayList<>();

    @Autowired
    private ValidOrderHandleInterceptService validOrderHandleInterceptService;

    @Autowired
    private RepeatOrderHandleInterceptService repeatOrderHandleInterceptService;

    @Autowired
    private BankOrderHandleInterceptService bankOrderHandleInterceptService;

    @PostConstruct
    public void init(){
     //依次手動(dòng)add對(duì)象
        handleList.add(repeatOrderHandleInterceptService);
        handleList.add(validOrderHandleInterceptService);
        handleList.add(bankOrderHandleInterceptService);
    }

    /**
     * 執(zhí)行處理
     * @param context
     * @return
     */
    public OrderAddContext execute(OrderAddContext context){
        for (OrderHandleIntercept handleIntercept : handleList) {
            context =handleIntercept.handle(context);
        }
        return context;
    }
}

2.2、方式二

第二種實(shí)現(xiàn)方式,就更簡(jiǎn)單了,我們通過(guò)注解@Order來(lái)指定排序,代替手動(dòng)方法排序sort(),操作方式如下:

/**
 * 指定注入順序?yàn)?
 *
 */
@Order(1)
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept {


    //...省略
}
/**
 * 指定注入順序?yàn)?
 *
 */
@Order(2)
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept {


    //...省略
}
/**
 * 指定注入順序?yàn)?
 *
 */
@Order(3)
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept {


    //...省略
}
@Component
public class OrderHandleChainService  {

 @Autowired
    private List<OrderHandleIntercept> handleList;

    /**
     * 執(zhí)行處理
     * @param context
     * @return
     */
    public OrderAddContext execute(OrderAddContext context){
        for (OrderHandleIntercept handleIntercept : handleList) {
            context =handleIntercept.handle(context);
        }
        return context;
    }
}

運(yùn)行單元測(cè)試,你會(huì)發(fā)現(xiàn)結(jié)果與上面運(yùn)行的結(jié)果一致,原因Springioc容器,支持通過(guò)Map或者List來(lái)直接注入對(duì)象,省去自己排序。

2.3、方式三

通過(guò)定義抽象類來(lái)實(shí)現(xiàn)責(zé)任鏈設(shè)計(jì)模式,還是以上面的案例為例,我們需要先定義一個(gè)抽象類,比如AbstractOrderHandle。

public abstract class AbstractOrderHandle {

    /**
     * 責(zé)任鏈,下一個(gè)鏈接節(jié)點(diǎn)
     */
    private AbstractOrderHandle next;

    /**
     * 執(zhí)行入口
     * @param context
     * @return
     */
    public OrderAddContext execute(OrderAddContext context){
        context = handle(context);
        // 判斷是否還有下個(gè)責(zé)任鏈節(jié)點(diǎn),沒(méi)有的話,說(shuō)明已經(jīng)是最后一個(gè)節(jié)點(diǎn)
        if(getNext() != null){
            getNext().execute(context);
        }
        return context;
    }

    /**
     * 對(duì)參數(shù)進(jìn)行處理
     * @param context
     * @return
     */
    public abstract OrderAddContext handle(OrderAddContext context);


    public AbstractOrderHandle getNext() {
        return next;
    }

    public void setNext(AbstractOrderHandle next) {
        this.next = next;
    }
}

然后,分別創(chuàng)建三個(gè)處理類,并排好序號(hào)。

@Order(1)
@Component
public class RepeatOrderHandle extends AbstractOrderHandle {

    @Override
    public OrderAddContext handle(OrderAddContext context) {
        System.out.println("通過(guò)seqId,檢查客戶是否重復(fù)下單");
        return context;
    }
}
@Order(2)
@Component
public class ValidOrderHandle extends AbstractOrderHandle {

    @Override
    public OrderAddContext handle(OrderAddContext context) {
        System.out.println("檢查請(qǐng)求參數(shù),是否合法,并且獲取客戶的銀行賬戶");
        return context;
    }
}
@Order(3)
@Component
public class BankOrderHandle extends AbstractOrderHandle {

    @Override
    public OrderAddContext handle(OrderAddContext context) {
        System.out.println("檢查銀行賬戶是否合法,調(diào)用銀行系統(tǒng)檢查銀行賬戶余額是否滿足下單金額");
        return context;
    }
}

接著,創(chuàng)建一個(gè)責(zé)任鏈管理器,比如OrderHandleManager。

@Component
public class OrderHandleManager {

    @Autowired
    private List<AbstractOrderHandle> orderHandleList;


    @PostConstruct
    public void init(){
        //如果List沒(méi)有按照@Order注解方式排序,可以通過(guò)如下方式手動(dòng)排序
        Collections.sort(orderHandleList, AnnotationAwareOrderComparator.INSTANCE);
        int size = orderHandleList.size();
        for (int i = 0; i < size; i++) {
            if(i == size -1){
                orderHandleList.get(i).setNext(null);
            } else {
                orderHandleList.get(i).setNext(orderHandleList.get(i + 1));
            }
        }

    }

    /**
     * 執(zhí)行處理
     * @param context
     * @return
     */
    public OrderAddContext execute(OrderAddContext context){
        context = orderHandleList.get(0).execute(context);
        return context;
    }
}

最后,我們編寫(xiě)單元測(cè)試,來(lái)看看效果。

@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private OrderHandleManager orderHandleManager;

    @Test
    public void test(){
        orderHandleManager.execute(new OrderAddContext());
    }

}

運(yùn)行結(jié)果與預(yù)期一致!

通過(guò)seqId,檢查客戶是否重復(fù)下單
檢查請(qǐng)求參數(shù),是否合法,并且獲取客戶的銀行賬戶
檢查銀行賬戶是否合法,調(diào)用銀行系統(tǒng)檢查銀行賬戶余額是否滿足下單金額

三、小結(jié)

本文主要圍繞在 SpringBoot 中如何引入責(zé)任鏈設(shè)計(jì)模式,介紹了三種玩法,其中第二種用法最多,其次就是第一種,第三種用的比較少,第三種本質(zhì)是一種鏈?zhǔn)綄?xiě)法,可能理解上不如第一種直觀,但是效果是一樣的。

有效的使用責(zé)任鏈設(shè)計(jì)模式,可以顯著降低業(yè)務(wù)代碼的復(fù)雜度,可讀性更好,更容易擴(kuò)展,希望對(duì)大家有幫助!

責(zé)任編輯:武曉燕 來(lái)源: 潘志的研發(fā)筆記
相關(guān)推薦

2022-10-08 07:31:59

Spring責(zé)任連模式

2021-07-12 07:08:54

責(zé)任鏈模式對(duì)象

2009-03-02 10:13:00

交換機(jī)端口模式

2023-12-14 07:11:24

編程語(yǔ)言微服務(wù)

2010-07-16 10:23:28

Batch telne

2009-04-22 09:50:00

TOMATO固件無(wú)線網(wǎng)絡(luò)

2021-12-24 07:50:45

責(zé)任鏈模式設(shè)計(jì)

2013-12-09 10:46:24

2009-10-22 09:52:41

域名郵箱安全

2012-03-28 13:28:56

Java設(shè)計(jì)模式

2022-12-28 08:08:57

2010-04-01 09:10:03

PHP設(shè)計(jì)模式責(zé)任鏈模式

2020-09-16 11:10:33

Linux命令文件

2018-11-19 15:06:23

Python庫(kù)算法

2021-12-03 23:14:49

Github插件開(kāi)發(fā)

2017-07-13 09:26:28

數(shù)據(jù)中心運(yùn)營(yíng)優(yōu)化

2011-04-22 15:55:33

吊頂正投投影機(jī)

2009-08-03 14:14:27

2011-04-01 10:16:08

SQL ServerEXISTS結(jié)構(gòu)

2022-11-01 08:46:20

責(zé)任鏈模式對(duì)象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)