工作实战之拦截器模式

news/2024/5/19 15:19:22 标签: java, 代码解耦, 设计模式, 责任链模式

目录

前言

一、结构中包含的角色

二、拦截器使用

1.拦截器角色

 a.自定义拦截器UserValidateInterceptor,UserUpdateInterceptor,UserEditNameInterceptor

 b.拦截器配置者UserInterceptorChainConfigure,任意组装拦截器顺序

c.拦截器管理者UserInterceptorChainManager

2.运行结果展示

a.使用代码

三、拦截器调用解说

1.项目启动,初始化bean

2.方法执行 

四、代码下载

总结


前言

拦截过滤器模式,简称拦截器模式,是责任链模式的一种衍生模式。用于对业务程序做一些预处理/后处理


一、结构中包含的角色

  1. Interceptor(抽象处理者)
  2. InterceptorChain(责任链)
  3. InterceptorChainBuilder(责任链建造者)
  4. AbstractInterceptorChainManager(链条管理者)
  5. InterceptorChainConfigure(链条配置者)

二、拦截器使用

1.拦截器角色

 a.自定义拦截器UserValidateInterceptor,UserUpdateInterceptor,UserEditNameInterceptor

java">/**
 * 校验用户
 * @author liangxi.zeng
 */
@Component
public class UserValidateInterceptor implements Interceptor<User> {
    /**
     * 拦截方法
     *
     * @param user
     */
    @Override
    public void interceptor(User user) {
        if(user.getAge() != 10) {
            throw new CommonException("年龄不对");
        }
        System.out.println("校验用户"+user);
    }
}

 b.拦截器配置者UserInterceptorChainConfigure,任意组装拦截器顺序

java">@Component
public class UserInterceptorChainConfigure
        implements InterceptorChainConfigure<User,InterceptorChainBuilder<User>> {
    /**
     * 拦截器链配置
     *
     * @param interceptorChainBuilder 拦截器链构造器
     */
    @Override
    public void configure(InterceptorChainBuilder<User> interceptorChainBuilder) {
        interceptorChainBuilder
                .pre()
                .addInterceptor(UserValidateInterceptor.class)
                .post()
                .addInterceptor(UserUpdateInterceptor.class)
                .addInterceptor(UserEditNameInterceptor.class);
    }
}

c.拦截器管理者UserInterceptorChainManager

java">/**
 * @author liangxi.zeng
 * 拦截器链管理类
 */
@Component
public class UserInterceptorChainManager 
extends AbstractInterceptorChainManager<User> {
    public UserInterceptorChainManager(List<Interceptor<User>> interceptorList,
                                       List<InterceptorChainConfigure<User, InterceptorChainBuilder<User>>> configureList) {
        super(interceptorList, configureList);
    }
}

2.运行结果展示

a.使用代码

java">/**
 * @author liangxi.zeng
 */
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private UserInterceptorChainManager userInterceptorChainManager;

    @Autowired
    private UserService userService;

    @RequestMapping("/user")
    public String user() {
        User user = new User();
        user.setId("111");
        user.setName("liangxi");
        user.setAge(10);
        userInterceptorChainManager.doInterceptor(user,(u) -> {
            // 内部创建用户
            userService.save(user);
        });
        return "success";
    }
  
}

三、拦截器调用解说

1.项目启动,初始化bean

a.初始化责任链管理者UserInterceptorChainManager,调用父类AbstractInterceptorChainManager方法initInterceptorChain,通过责任链建造者初始化责任链

java"> public AbstractInterceptorChainManager(List<Interceptor<T>> interceptorList,
                                           List<InterceptorChainConfigure<T, InterceptorChainBuilder<T>>> configureList) {
        interceptorChain = initInterceptorChain(interceptorList, configureList);
        LOGGER.info("Register {} InterceptorChain, names are [{}]",interceptorList);
    }

    private InterceptorChain<T> initInterceptorChain(List<Interceptor<T>> interceptorList,
                                                                   List<InterceptorChainConfigure<T, InterceptorChainBuilder<T>>> configureList) {
        if (CollectionUtils.isEmpty(interceptorList)) {
            throw new IllegalArgumentException("Interceptors is empty.");
        }

        if (CollectionUtils.isEmpty(configureList)) {
            throw new IllegalArgumentException("Interceptor configurers is empty.");
        }

        InterceptorChainBuilder<T> builder = new InterceptorChainBuilder<>(interceptorList);

        configureList.sort(AnnotationAwareOrderComparator.INSTANCE);

        configureList.forEach(configurer -> {
            configurer.configure(builder);
        });

        return builder.performBuild();
    }

 b.责任链建造者,完成对业务方法前后逻辑的织入

java">public InterceptorChain performBuild() {
            List<Interceptor<T>> preInterceptors = filterInterceptor(preInterceptorList);
            List<Interceptor<T>> postInterceptors = filterInterceptor(postInterceptorList);

            if (preInterceptors.isEmpty() && postInterceptors.isEmpty()) {
                throw new IllegalStateException("Registered Pre-Interceptors and Post-Interceptors is empty.");
            }

            Consumer<T> preConsumer = (T t) -> {
            };
            Consumer<T> postConsumer = (T t) -> {
            };

            if (!preInterceptors.isEmpty()) {
                preConsumer = (T obj) -> {
                    for (Interceptor<T> item : preInterceptors) {
                        item.interceptor(obj);
                    }
                };
            }

            if (!postInterceptors.isEmpty()) {
                postConsumer = (T obj) -> {
                    for (Interceptor<T> item : postInterceptors) {
                        item.interceptor(obj);
                    }
                };
            }
            return new InterceptorChain(preConsumer,postConsumer);
    }

2.方法执行 

a.从userInterceptorChainManager.doInterceptor 到 interceptorChain.doExecute(target, operation);下面代码,完成代码逻辑

java">  /**
     * 拦截器调用入口,将核心操作封装成 Consumer 对象传入。
     *
     * @param target    The target to handle.
     * @param operation The core operation to intercept.
     */
    public final void doExecute(T target, Operation<T> operation) {
        preConsumer.accept(target);

        if (operation != null) {
            operation.execute(target);
        }

        postConsumer.accept(target);
    }

四、代码下载

设计模式可运行代码https://gitee.com/zenglx/design-pattern.git


总结

前后端请求,可以用现成的filter和spring的Interceptor解决,业务自己的拦截器链模式,可以解决繁琐业务重复代码的问题


http://www.niftyadmin.cn/n/128546.html

相关文章

uniapp在线升级关联云空间

升级中心 uni-upgrade-center - App&#xff1a; https://ext.dcloud.net.cn/plugin?id4542 App升级中心 uni-upgrade-center文档&#xff1a; https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html#uni-upgrade-center-app 升级中心 uni-upgrade-center - Admin&#…

不考虑分配与合并情况下,GO实现GCMarkSweep(标记清除算法)

观前提醒 熟悉涉及到GC的最基本概念到底什么意思&#xff08;《垃圾回收的算法与实现》&#xff09;我用go实现&#xff08;因为其他的都忘了&#xff0c;(╬◣д◢)&#xff91;&#xff77;&#xff70;!!&#xff09; 源码地址&#xff08;你的点赞&#xff0c;是我开源的…

一图来看你需要拥有那些知识储备

技术实践 数据 关系型数据 MySQLSQLServerOraclePostgrSQLDB2 大数据存储 RedisMemcacheMongoDBHBaseHive 大数据处理 Hadoop 数据报表看板 DataGearGrafanaKibanaMetaBase 消息对列 Rabbit MQRock MQActive MQKafka 大数据搜索 SolrElasticSearchLucenHive 服务提…

day40|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…

Spring Boot 3.0系列【10】核心特性篇之应用配置的高阶用法

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言1. 命令行2. JSON3. 外部化配置3.1 配置文件加载位置3.2 导入配置3.2 属性占位符4. 加密配置5. 加载YML配置文件6. 配…

使用qt编写一个嵌入浏览器的程序,每浏览一次并清除缓存

使用Qt编写一个嵌入浏览器的程序&#xff0c;每浏览一次并清除缓存&#xff0c;是一个比较复杂的任务&#xff0c;需要涉及到多个Qt模块和类。这里给出一个大致的思路和参考代码&#xff0c;你可以根据自己的需求进行修改和扩展。 - 首先&#xff0c;你需要使用QWebEngineView…

3 Java的一文两吃:常量变量与输入输出

Java的一文两吃&#xff1a;常量变量与输入输出常量与变量1.声明变量2.变量初始化3.常量4.枚举类型输入与输出1.读取输入2.格式化输出3.文件输入与输出常量与变量 1.声明变量 double a; int b; boolean c;int i,j; //可以在一行中声明多个变量Java中&#xff0c;每个变量都有…

centos6下为Rstudio安装多版本R

之前的R版本太旧,不少包装不上,需要安装新版本的R: R --version R version 3.6.0 (2019-04-26) -- "Planting of a Tree"于是下载最新版R: 因为没有证书,需要加上最后面的参数. wget https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/base/R-4/R-4.2.2.tar.gz --no…