前言

常见的有三种,serverlet ,spring Interceptor, aop 。

serverlet filter实现

图解

image.png

使用

  1. public class LogFilter implements Filter {
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. // 在创建Filter时自动调用,
  5. // 其中filterConfig包含这个Filter的配置参数,比如name之类的(从配置文件中读取的)
  6. }
  7. @Override
  8. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  9. System.out.println("拦截客户端发送来的请求.");
  10. chain.doFilter(request, response);
  11. System.out.println("拦截发送给客户端的响应.");
  12. }
  13. @Override
  14. public void destroy() {
  15. // 在销毁Filter时自动调用
  16. }
  17. }
  18. // 在web.xml配置文件中如下配置:
  19. <filter>
  20. <filter-name>logFilter</filter-name>
  21. <filter-class>com.xzg.cd.LogFilter</filter-class>
  22. </filter>
  23. <filter-mapping>
  24. <filter-name>logFilter</filter-name>
  25. <url-pattern>/*</url-pattern>
  26. </filter-mapping>

源码实现

实现思路:
1 维护过滤器数组
2 增加时更新数组,并根据需要扩容
3 执行时,递归执行,直到所有完成

  1. public final class ApplicationFilterChain implements FilterChain {
  2. private int pos = 0; //当前执行到了哪个filter
  3. private int n; //filter的个数
  4. private ApplicationFilterConfig[] filters;
  5. private Servlet servlet;
  6. @Override
  7. public void doFilter(ServletRequest request, ServletResponse response) {
  8. if (pos < n) {
  9. ApplicationFilterConfig filterConfig = filters[pos++];
  10. Filter filter = filterConfig.getFilter();
  11. filter.doFilter(request, response, this);
  12. } else {
  13. // filter都处理完毕后,执行servlet
  14. servlet.service(request, response);
  15. }
  16. }
  17. public void addFilter(ApplicationFilterConfig filterConfig) {
  18. for (ApplicationFilterConfig filter:filters)
  19. if (filter==filterConfig)
  20. return;
  21. if (n == filters.length) {//扩容
  22. ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
  23. System.arraycopy(filters, 0, newFilters, 0, n);
  24. filters = newFilters;
  25. }
  26. filters[n++] = filterConfig;
  27. }
  28. }

spring Interceptor

图解

image.png

使用代码

  1. public class LogInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. System.out.println("拦截客户端发送来的请求.");
  5. return true; // 继续后续的处理
  6. }
  7. @Override
  8. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  9. System.out.println("拦截发送给客户端的响应.");
  10. }
  11. @Override
  12. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  13. System.out.println("这里总是被执行.");
  14. }
  15. }
  16. //在Spring MVC配置文件中配置interceptors
  17. <mvc:interceptors>
  18. <mvc:interceptor>
  19. <mvc:mapping path="/*"/>
  20. <bean class="com.xzg.cd.LogInterceptor" />
  21. </mvc:interceptor>
  22. </mvc:interceptors>

源码实现

  1. public class HandlerExecutionChain {
  2. private final Object handler;
  3. private HandlerInterceptor[] interceptors;
  4. public void addInterceptor(HandlerInterceptor interceptor) {
  5. initInterceptorList().add(interceptor);
  6. }
  7. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  8. HandlerInterceptor[] interceptors = getInterceptors();
  9. if (!ObjectUtils.isEmpty(interceptors)) {
  10. for (int i = 0; i < interceptors.length; i++) {
  11. HandlerInterceptor interceptor = interceptors[i];
  12. if (!interceptor.preHandle(request, response, this.handler)) {
  13. triggerAfterCompletion(request, response, null);
  14. return false;
  15. }
  16. }
  17. }
  18. return true;
  19. }
  20. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
  21. HandlerInterceptor[] interceptors = getInterceptors();
  22. if (!ObjectUtils.isEmpty(interceptors)) {
  23. for (int i = interceptors.length - 1; i >= 0; i--) {
  24. HandlerInterceptor interceptor = interceptors[i];
  25. interceptor.postHandle(request, response, this.handler, mv);
  26. }
  27. }
  28. }
  29. void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
  30. throws Exception {
  31. HandlerInterceptor[] interceptors = getInterceptors();
  32. if (!ObjectUtils.isEmpty(interceptors)) {
  33. for (int i = this.interceptorIndex; i >= 0; i--) {
  34. HandlerInterceptor interceptor = interceptors[i];
  35. try {
  36. interceptor.afterCompletion(request, response, this.handler, ex);
  37. } catch (Throwable ex2) {
  38. logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
  39. }
  40. }
  41. }
  42. }
  43. }

小结与对比

对比

AOP、Servlet Filter、Spring Interceptor这三者可以从不同权限检查的范围大小的视角来应用:
1. Servlet Filter
运维部门需要对只供内部访问的服务进行IP限制或访问审查时,在容器这一层增加一个Filter,在发布时发布系统自动加挂这个Filter,这样对上层应用就是透明的,内网IP地址段增减或审查规则调整都不需要上层应用的开发人员去关心。
2. Spring Interceptor
由框架或基础服务部门来提供的微服务间相互调用的授权检查时,可以提供统一的SDK,由程序员在需要的服务上配置。
3. AOP
业务应用内权限检查,可以把权限检查在统一模块中实现,通过配置由AOP加插拦截检查。

其他类似设计

netty的ChannelPipeline的实现逻辑:
1、每一个SocketChannel对象维护这一个ChannelPipeline对象,该对象支持bind,connect,disconnect,read,write等IO时间的触发链条;
2、ChannelPipeline对外提供ChannelHandler的增删改查的接口、对内使用AbstractChannelHandlerContext对象将ChannelHandler包装了一层,维护了一个AbstractChannelHandlerContext的双向链表。
3、当SocketChannel发生IO事件时,比如发生了read事件,SocketChannel委托ChannelPipeline去处理这些时间,从而启动了责任链的操作。

说明

内容整理自极客《设计模式专栏》