利用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; } }
- 配置我们自定义的HandlerInterceptor @Slf4j @Configuration public class WebConfiguration implements WebMvcConfigurer{ @Autowired private RequestHandlerChain requestHandlerChain; /** * 注入我们自己定义的 RequestHandlerChain */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(requestHandlerChain).order(1); } }
- 然后我们只需要实现 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类的实现方法中循环调用实现类的实现方法。