成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發(fā) 前端
本文主要圍繞在 SpringBoot 中如何引入責(zé)任鏈設(shè)計(jì)模式,介紹了三種玩法,其中第二種用法最多,其次就是第一種,第三種用的比較少,第三種本質(zhì)是一種鏈?zhǔn)綄懛ǎ赡芾斫馍喜蝗绲谝环N直觀,但是效果是一樣的。

一、什么是責(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 ??的攔截器、過濾器鏈
  • netty 中的處理鏈
  • 支付風(fēng)控的機(jī)制
  • ?志處理級(jí)別

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

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

二、代碼實(shí)踐

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

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

圖片

采用責(zé)任鏈設(shè)計(jì)模式來編程,代碼實(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("通過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;
    }
}

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

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

    @Autowired
    private OrderHandleChainService orderHandleChainService;

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

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

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

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

當(dāng)然,有的同學(xué)可能覺得這種方法用的不習(xí)慣,不喜歡通過sort()來指定順序,也可以通過如下方式進(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)單了,我們通過注解@Order來指定排序,代替手動(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容器,支持通過Map或者List來直接注入對(duì)象,省去自己排序。

2.3、方式三

通過定義抽象類來實(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),沒有的話,說明已經(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("通過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沒有按照@Order注解方式排序,可以通過如下方式手動(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;
    }
}

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

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

    @Autowired
    private OrderHandleManager orderHandleManager;

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

}

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

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

三、小結(jié)

本文主要圍繞在 SpringBoot 中如何引入責(zé)任鏈設(shè)計(jì)模式,介紹了三種玩法,其中第二種用法最多,其次就是第一種,第三種用的比較少,第三種本質(zhì)是一種鏈?zhǔn)綄懛ǎ赡芾斫馍喜蝗绲谝环N直觀,但是效果是一樣的。

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

責(zé)任編輯:武曉燕 來源: 潘志的研發(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

編程語言微服務(wù)

2021-12-24 07:50:45

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

2010-07-16 10:23:28

Batch telne

2009-04-22 09:50:00

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

2009-10-22 09:52:41

域名郵箱安全

2013-12-09 10:46:24

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é)任鏈模式

2009-08-03 14:14:27

2011-04-01 10:16:08

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

2020-09-16 11:10:33

Linux命令文件

2018-11-19 15:06:23

Python庫(kù)算法

2021-12-03 23:14:49

Github插件開發(fā)

2017-07-13 09:26:28

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

2011-04-22 15:55:33

吊頂正投投影機(jī)

2022-11-01 08:46:20

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

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

主站蜘蛛池模板: 精品九九| 国产视频久久久 | 国产精品成人一区二区 | k8久久久一区二区三区 | 精品免费观看 | 欧美精品福利视频 | 欧美在线观看免费观看视频 | 国产综合在线视频 | 欧美日韩国产一区二区三区 | av网站免费看| 日韩在线播放一区 | www.久久99| 日本三级网址 | 国产精品免费一区二区 | 国产精品精品视频一区二区三区 | 精品一区电影 | 色悠悠久| 亚洲精品一区二区三区在线观看 | 日日操夜夜操天天操 | 综合久久久 | 91av在线免费播放 | 国产在线网站 | 在线观看中文字幕 | 国产在线中文字幕 | 国产成人免费视频网站视频社区 | 久久精品91久久久久久再现 | 国产超碰人人爽人人做人人爱 | 精品成人免费一区二区在线播放 | 中文在线а√在线8 | 欧美日韩高清 | 国产日韩免费观看 | 久久与欧美 | 日韩欧美一级精品久久 | 亚洲91| 三级欧美 | 国产精品永久 | 天天综合91 | 毛片视频观看 | 精品一区二区电影 | 亚洲欧美日本国产 | 91免费福利视频 |