责任链模式(处理逻辑解耦)

目录

前言

UML

plantuml

类图

代码实战

Filter

Interceptor

业务实战


前言

使用设计模式的主要目的之一就是解耦,让程序易于维护和更好扩展。

责任链则是将处理逻辑进行解耦,将独立的处理逻辑抽取到不同的处理者中,每个处理者都能够单独修改而不影响其他处理者。

使用时,依次调用链上的处理者处理逻辑。

UML

plantuml

@startuml
'https://plantuml.com/class-diagram

interface Handler {
    + handle() : void
}

class ConcreteHandlerA {
    + handle() : void
}

class ConcreteHandlerB {
    + handle() : void
}

class HandlerChain {
    - handlers : List<Handler>
    + HandlerChain(List<Handler>)
    + handle() : void
}

class Client {}

Handler <|.. ConcreteHandlerA
Handler <|.. ConcreteHandlerB

HandlerChain "1" --> "n" Handler

Client ..> HandlerChain

@enduml

类图

代码实战

Filter

过滤器是 Servlet 规范规定的,处理时机是在进入 servlet 容器之前

Filter 的 doFilter 方法第三个入参 FilterChain,即为过滤器调用链,通过它实现递归调用链上的过滤器 doFilter 方法,执行过滤处理逻辑(前置处理和后置处理)

@WebFilter (urlPatterns = "/test", filterName = "MyFilter ")
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException {
        //前置处理

        //递归调用过滤器链上的过滤器,过滤器 doFilter 方法依次入方法栈

        chain.doFilter(request, response);

        //当 FilterChain 上的过滤器都执行后,就会调用 servlet 的 service 方法

        //方法栈弹出 doFilter 方法,执行后置处理
        
        //后置处理
    }

    @Override
    public void destroy() {}
}

ApplicationFilterChain 维护了过滤器配置列表和当前索引下标

ApplicationFilterChain 中 doFilter 方法里面调用私有方法 internalDoFilter,在私有方法中,根据当前索引下标调用链上的过滤器

如果过滤器都执行了,就调用 servlet

Interceptor

拦截器是 Spring 框架提供的功能,处理时机实在进入servlet 后,且在进入 controller 之前处理,具体的处理逻辑在 DispatcherServlet 的 doDispatch 中

从代码中可以看出来,拦截器的处理分为三个时机,前置处理,后置处理,以及完成后。

mappedHandler 即为拦截器调用链 HandlerExecutionChain

维护了拦截器列表和当前索引下标

调用拦截链时,其实就是遍历拦截器数组,判断是否合法

业务实战

在 Filter 和 Interceptor 中,应用的最小的颗粒度都是接口,通常它们都是用来处理一些与具体业务无关的功能

如果只需要应用在某一个方法上,在 spring 中可以依靠 IOC 容器和依赖注入来实现特定业务的责任链模式

比如在业务处理中需要对一批业务数据做各种校验

解耦出各个不同校验逻辑,注入 IOC 容器

public interface Handler {

    /**
     * 对参数进行处理
     * @param object
     * @return
     */
    Object handle(Object object);
}

/**
 * 指定注入顺序为1
 *
 */
@Order(1)
@Component
public class Handler1 implements Handler {


    //...省略
}

/**
 * 指定注入顺序为2
 *
 */
@Order(2)
@Component
public class Handler2 implements Handler {


    //...省略
}

/**
 * 指定注入顺序为3
 *
 */
@Order(3)
@Component
public class Handler3 implements Handler {


    //...省略
}

@Component
public class HandleChain {

    @Autowired
    private List<Handler> handleList;

    /**
     * 执行处理
     * @param context
     * @return
     */
    public Object execute(Object object){
        for (OrderHandleIntercept handleIntercept : handleList) {
            object = handleIntercept.handle(object);
        }
        return object;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值