java:责任链设计模式配合Spring@Order注解使用场景

news2025/2/21 23:20:16

java:责任链设计模式配合Spring@Order注解使用场景

1 前言

java的责任链模式,经典使用的场景为SpringMVC的doDispatch下,针对请求的过滤链式行为。实际开发场景中,可配合Spring的@Order注解,定义1个有顺序的链式Components列表,根据Components列表的顺序依次处理,如果中途存在处理失败的Component,则终止(或过滤,依赖实际场景即可)整个处理过程,实际使用方式见如下。

2 使用

链式调用的client接口:

public interface IHandleChain {

    boolean handleChain();
}

链式调用的client抽象类:

package com.xiaoxu.handleChain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:com.xiaoxu.handleChain.AbstractHandleChain
 */
public abstract class AbstractHandleChain implements IHandleChain{
    @Autowired
    List<IHandle> handlers;

    IHandle handler;

    @PostConstruct
    public void postHandlers(){
        if(CollectionUtils.isEmpty(handlers)){
            throw new RuntimeException("handlers should not be null or empty.");
        }
        System.out.println("开始执行postHandlers...");
        IHandle currentHandler;
        IHandle nextHandler;
        for (int i = 0; i < handlers.size(); i++) {
            if(i == 0){
                handler = handlers.get(0);
            }else{
                currentHandler = handlers.get(i-1);
                nextHandler = handlers.get(i);
                currentHandler.setNextIHandle(nextHandler);
            }
        }
        System.out.println("handleChain:"+handler);
    }

    protected boolean handle(){
        if(null == this.handler){
            throw new RuntimeException("handler should not be null.");
        }
        return this.handler.handle();
    }

}

上述抽象类获取的链式client处理对象:

在这里插入图片描述

链式调用Client:

package com.xiaoxu.handleChain;

import org.springframework.stereotype.Component;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:com.xiaoxu.handleChain.HandleChainClient
 */
@Component
public class HandleChainClient extends AbstractHandleChain{

    @Override
    public boolean handleChain() {
        boolean res;
        if(res = this.handle()){
            System.out.println("全部业务处理成功!");
        }else{
            System.out.println("事务中途处理失败!!!");
        }
        return res;
    }

}

IHandle接口:

public interface IHandle {

    void setNextIHandle(IHandle iHandle);

    IHandle getNextIHandle();

    boolean doHandle();

    boolean handle();
}

IHandle抽象类:

package com.xiaoxu.handleChain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * @author xiaoxu
 * @date 2023-01-10
 * java_demo2:com.xiaoxu.handleChain.AbstractIHandle
 */
public abstract class AbstractIHandle implements IHandle{

    IHandle nextIHandle;

    @Override
    public void setNextIHandle(IHandle iHandle) {
        this.nextIHandle = iHandle;
    }

    @Override
    public IHandle getNextIHandle() {
        return this.nextIHandle;
    }

    @Override
    public boolean handle() {
        boolean res = this.doHandle();
        if(res){
            if(null != getNextIHandle()){
                return getNextIHandle().handle();
            }
            return true;
        }
        return false;
    }

    @Override
    public String toString(){
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

IHandle的具体处理实现类:

链式处理step1:前置检查

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:com.xiaoxu.handleChain.PreHandle
 */
@Component
@Order(value = 1)
public class PreHandle extends AbstractIHandle{

    @Override
    public boolean doHandle() {
        System.out.println("前置检查...");
        return true;
    }

}

链式处理step2:安全检查

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:com.xiaoxu.handleChain.CheckSecurityHandle
 */
@Component
@Order(value = 2)
public class CheckSecurityHandle extends AbstractIHandle{

    @Override
    public boolean doHandle() {
        System.out.println("安全检查...");
        return true;
    }

}

链式处理step3:业务处理

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:com.xiaoxu.handleChain.ServiceHandle
 */
@Component
@Order(value = 3)
public class ServiceHandle extends AbstractIHandle{

    @Override
    public boolean doHandle() {
        System.out.println("业务处理...");
        return true;
    }

}

链式处理step4:后置处理

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:com.xiaoxu.handleChain.PostHandle
 */
@Component
@Order(value = 4)
public class PostHandle extends AbstractIHandle{

    @Override
    public boolean doHandle() {
        System.out.println("后置处理...");
        return true;
    }

}

编写单测执行:

import com.xiaoxu.MainApplication;
import com.xiaoxu.handleChain.HandleChainClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author xiaoxu
 * @date 2023-01-09
 * java_demo2:PACKAGE_NAME.TestHandle
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class TestHandle {
    @Autowired
    HandleChainClient client;

    @Test
    public void test_01(){
        boolean b = client.handleChain();
        System.out.println("结果为:" + b);
    }

}

执行结果如下,可见达到了链式处理的效果:

在这里插入图片描述

若将业务处理的返回改为false后再次执行:

在这里插入图片描述

结果如下所示:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/152568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我在深圳的三次工厂旅程 (一)

2019年末加入一家人工智能AI创业公司&#xff0c;由于公司涉及到智能硬件产品&#xff0c;所以有机会参与到硬件产品的整个研发测试端、产品迭代流、工厂生产序等方面的这些事情。相对于研发测试、产品迭代这些在过往的工作中经历中相对比较熟悉和接触频繁&#xff0c;在软件产…

鉴定完毕!来看看跨年晚会谁假唱了…欧莱雅智能画眉设备;首个AI律师下月出庭;推特又裁员;GitHub今日热榜 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f3a1;AI应用与工具大全 | &#x1f514;公众号资料下载 | &#x1f369;韩信子 &#x1f3a1; 『谁在假唱』技术手段分析跨年演唱会上的歌手们 各大卫视的跨年演唱会&#xff0c;你追了几场&#xff1f;看出来了谁在对口型&#xff1f;B站Up主…

【北京理工大学-Python 数据分析-2.2Matplotlib绘制饼图、直方图、极坐标、散点图】

pyplot的基础图标函数 函数说明plt.plot(x,y,fmt,…)绘制一个坐标图plt.boxplot(data,notch,position)绘制一个箱型图plt.bar(left,height,width,bottom)绘制一个条形图plt.barh(width,bottom,left,height)绘制一个横向条形图plt.polar(theta,r)绘制极坐标图plt.psd(x,NFFT256…

Dokcer14_5:Docker Compose volumes解析、Docker Compose volumes目录路径生成规则

Dokcer14_5&#xff1a;Docker Compose volumes解析、Docker Compose volumes目录路径生成规则docker-compose volumes语法语法格式及其三种变体1.无来源 &#xff1a;匿名挂载主机系统上的目录路径2.非路径源&#xff1a;具名挂载&#xff08;常用&#xff09;主机系统上的目录…

mysql idb,frm文件复制恢复

idb是innodb数据文件frm是innodb表结构文件在数据库的data目录下可以看到 data下的目录名就是数据库名&#xff0c;打开该数据库文件夹对于一个表有2个文件&#xff0c;一个以idb结尾&#xff0c;一个以frm结尾直接复制粘贴是不识别的&#xff0c;提示找不到该表解决方法&#…

在线实习项目|Python爬虫助力疫情数据追踪在线实习项目

项目介绍 项目背景&#xff1a;2019-NCOV新型冠状病毒引发的肺炎牵动全国人民的心&#xff0c;本项目希望通过大数据技术为抗击新冠肺炎贡献一份力量。 项目目标&#xff1a;使用PYTHON爬虫技术爬取疫情数据&#xff0c;从不同维度分析数据&#xff0c;并用 MATPLOT…

ubuntu18.04部署DXSLAM,CNN+VSLAM,CPU实时运行

一、下载源代码 打开终端&#xff0c;输入命令克隆仓库 git clone https://github.com/raulmur/DXSLAM.git DXSLAM二、配置环境 We have tested the library in Ubuntu 16.04 and Ubuntu 18.04, but it should be easy to compile in other platforms. C11 or C0x CompilerPa…

虚拟化技术学习笔记8

添加网卡&#xff1a; 1、virt-manager: 选择虚拟机直接添加网卡操作。 2、virsh命令&#xff1a; virsh list virsh domiflist centos7-1 virsh attach-interface centos7-1 \ --type network \ --source default \ --model virtio \ --config 虚拟机查看网卡的添加情况&…

分享65个NET源码,总有一款适合您

NET源码 分享65个NET源码&#xff0c;总有一款适合您 65个NET源码链接&#xff1a;https://pan.baidu.com/s/19yFm_9K_L0xfykMP1hdP5A?pwdn2p7 提取码&#xff1a;n2p7 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#x…

Apache APISIX Ingress 1.6 正式发布!

距离上一个版本 v1.5 发布&#xff0c;已经过了 3 个月&#xff0c;我们很高兴地宣布 Apache APISIX Ingress v1.6 正式发布&#xff01; 在该版本中&#xff0c;共有 29 位贡献者 参与代码提交&#xff0c;其中 17 位是新晋贡献者 &#xff0c;感谢大家的支持和参与&#xff…

nacos的服务注册与调用

此篇博客进行一个简单实例进行展示服务注册和服务的调用&#xff0c;以订单与库存模块为例&#xff0c;其结构图如下&#xff1a; 目 录 1、创建订单模块与库存模块 1.1、编写stock模块 1.2、编写order模块 2、访问地址进行测试 3、总结 1、创建订单模块与库存模块 创建两…

论文投稿指南——中文核心期刊推荐(生物科学 2)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

.net开发安卓入门-文件操作与配置操作

.net开发安卓入门-文件操作与配置操作文件操作内部存储代码运行效果System.Environment.SpecialFolder枚举类型对应路径表格外部存储&#xff08;代码和效果见上图&#xff09;区别缓存SharedPreferences获取SharedPreferences对象方法列表读取配置信息写配置信息AssetsNlog配置…

【Linux项目自动化构建工具 make/Makefile】

目录 1 背景 2 原理 3 Linux第一个小程序&#xff0d;进度条 3.1 行缓冲区概念 3.2 进度条代码 4 总结 1 背景 在VS中我们知道当我们想要运行程序时直接按f5程序就会自动运行起来&#xff0c;但是在Linux中如果有多个文件好像并不能这样快速进行&#xff0c;那么这时候就…

远程接入(远程办公)解决方案 OpenText™ Exceed™ TurboX (ETX)

OpenText™ Exceed™ TurboX 安全快速的虚拟应用程序和桌面解决方案&#xff0c;适用于混合工作环境&#xff0c;只需低带宽互联网连接即可为办公桌面和图形要求苛刻的软件提供卓越的用户体验。 突出优势&#xff1a; 支持混合云环境使用任何设备随时随地远程工作为用户提供类…

SpringCloud之Zuul路由网关

Zuul路由网关1. Zuul的概念2. Zuul的作用3. 案例1. Zuul的概念 Zuul包含了对请求的路由&#xff08;用来跳转的&#xff09;和过滤两个最主要功能&#xff1a; 其中路由功能负责将外部请求转发到具体的微服务实例上&#xff0c;是实现外部访问统一入口的基础&#xff0c;而过滤…

新年新故事 | Nice 兔 Meet U

各位伙伴新年好哇 比特熊又回来啦【比特熊故事汇2.0】23年开年第一场与大家一起认识“印象中”的不寻常开发人产品创新实践、工作 Mix 生活、反差感2023年1月12日19:00-20:00【比特熊故事汇2.0】新年想见你第一面Nice 兔 Meet U 比特熊兔年特别限定手办2023年兔年来到&#xff…

Ubuntu10.04编译libevent记录

目前有一个旧的程序 基于很老的ubuntu1004的系统做开发 很多新的C11什么的都用不了 之前 很多在ubuntu1804 上编译的so库 直接拿到1004上来用 提示报错 如下 没办法 只能重新在ubuntu 1004 上面编译了 记录下 下载libevent之后解压 直接执行./configure 提示报错如下图 …

kettle简单的ETL抽取同步两个库之间的数据

kettle下载安装 kettle下载&#xff0c;提取码为 1qyd 安装后&#xff0c;把连接数据库需要的jar包放到 data-integration\lib 目录下&#xff0c;到时候kettle才能正确连接数据库。 sqlserver需要的jar包&#xff0c;提取码为 6a6qmysql需要的jar包&#xff0c;提取码为 n8…

深入理解CAS

目录深入理解CASCAS中的引入什么是CAS&#xff1f;CAS原理——Unsafe类CAS优点CAS缺点ABA问题解决ABA问题深入理解CAS CAS中的引入 我们知道我们使用Volatile可以保证可见性&#xff0c;但不保证原子性&#xff0c;那么&#xff0c;如果我们不使用Lock锁和synchronized&#x…