利用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类的实现方法中循环调用实现类的实现方法。
