利用spring的bean工厂优雅的实现责任链模式

责任链模式

责任链设计模式:当有多个对象都会对某个对象进行操作时,我们可以将这些对象转换为一个类似于链表的形式,按顺序执行这些对象的操作。

使用场景:servlet内的filter,spring中的interceptor都是采用责任链设计模式,多个interceptor是按顺序执行的。

利用spring的bean工厂优雅的实现责任链模式

案例:Spring MVC 为我们提供了HandlerInterceptor ,我们可以实现HandlerInterceptor 接口并进行配置来拦截请求。

但是每个HandlerIntercepotr都需要进行配置,能否不配置就自动拦截请求呢?答案是通过责任链模式对HandlerInterceptor再次封装即可实现。

1 定义执行链类

@Component
public class RequestHandlerChain implements HandlerInterceptor, ApplicationContextAware {
          
   

    private List<HandlerInterceptor> handlerList;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
          
   
        //从bean工厂获取所有的HandlerInterceptor
        this.handlerList = new ArrayList<>(applicationContext.getBeansOfType(HandlerInterceptor.class).values());

        if(CollUtil.isNotEmpty(handlerList)){
          
   
            //根据类上面的@Order的值进行排序
            AnnotationAwareOrderComparator.sort( handlerList );
        }
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          
   

        for (HandlerInterceptor handlerInterceptor : this.handlerList) {
          
   
            boolean proceed = handlerInterceptor.preHandle(request, response, handler);
            //如果有一个未放行,直接返回false
            if(!proceed){
          
   
                return false;
            }
        }
        return true;
    }
}
  1. 配置我们自定义的HandlerInterceptor @Slf4j @Configuration public class WebConfiguration implements WebMvcConfigurer{ @Autowired private RequestHandlerChain requestHandlerChain; /** * 注入我们自己定义的 RequestHandlerChain */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(requestHandlerChain).order(1); } }
  2. 然后我们只需要实现 HandlerInterceptor并在类上通过@Order指定执行顺序即可,无需再进行额外的配置
@Order(2)
@Component
public class TokenRequestHandler implements HandlerInterceptor {
          
   
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          
   
        System.out.println("解析token");

        if(true) throw new RuntimeException("请登录");

        return true;
    }
}

@Order(1)
@Component
public class WebLogRequestHandler implements HandlerInterceptor {
          
   
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          
   
        System.out.println("接收到请求------>"+System.currentTimeMillis());
        return true;
    }
}

责任链模式实现思路:首先需要有个抽象类/接口,然后定义一个Chain类,Chain类需要实现这个抽象类/接口并保存项目中所有改抽象类/接口的实现,然后在Chain类的实现方法中循环调用实现类的实现方法。

经验分享 程序员 微信小程序 职场和发展