`

【Java Web】Filter vs Interceptor

    博客分类:
  • Java
 
阅读更多

我们说的 Filter 和 Interceptor 是啥?

  • Filter:javax.servlet.Filter
  • Interceptor:org.springframework.web.servlet.HandlerInterceptor

参考:

 

简介

Filter

public interface Filter {
    public void init(FilterConfig filterConfig) throws ServletException;

    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException;

    public void destroy();
}

根据代码附属的文档:

Filter 用于过滤对资源的请求和响应。一个Filter可以同时用于过滤请求和响应。
目标资源可以是 Servlet 或 静态资源。

 

Filter 的 doFilter 方法执行具体的过滤操作。
Filter 可以通过 FilterConfig 对象获取初始化参数。还可通过 FilterConfig 提供的 ServletContext 引用获取更多资源信息用于过滤操作。

 

可通过 web descriptor 文件 web.xml 配置Filter,也可以用 @WebFilter 注解配置。
(标准的默认 web descriptor 文件是 WEB-INF/web.xml)

 

典型使用场景:

  1. 身份验证
  2. 日志、审计
  3. 图像转换
  4. 数据压缩
  5. 加解密
  6. 访问令牌处理
  7. 触发资源访问事件2
  8. XSL 转换(XSL/T)
  9. Mime 类型链式过滤

 

HandlerInterceptor

public interface HandlerInterceptor {
	boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                          Object handler)
			throws Exception;

	void postHandle(HttpServletRequest request, HttpServletResponse response,
                        Object handler, ModelAndView modelAndView)
			throws Exception;

	void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                             Object handler, Exception ex)
			throws Exception;
}

根据代码附属文档:

HandlerInterceptor 用于自定义执行链。
HandlerInterceptor 会在相应的 HandlerAdaptor 被调用前执行,所以可用于“预处理”。
例:授权检查、区域设置、主题更改 等。
它的主要目的就是提取出可复用的 Handler 代码。

 

作为Spring中的概念,HandlerInterceptor 可以像一般的Bean那样配置在 Application Context 中。

 

HandlerInterceptor 与 Servlet Filter 很相似。
但是 Interceptor 只允许通过预处理禁止 Handler 本身运行,或执行一些后续处理(post-processing)。
Filter 更强大。如,允许交换传递给后续处理链的 request 和 response 对象。

 

基本准则

  • 细粒度的 Handler相关 预处理操作 可以用 HandlerInterceptor 实现。
    尤其是 授权检查公用的 Handler 代码
  • Filter 适合用于处理 request 和 view 内容。如,Multipart 表单、Gzip压缩。
    典型的作法就是处理特定的 Content-Type。

 

对比

最本质的区别是,Filter 是 Servlet 中的概念,HandlerInterceptor 是 Spring Web 中的概念。
它们是两个不同体系中的概念。因为它们都能实现对 HTTP Request 和 Response 的一些自定义处理,所以会被一些无聊的人强行拿来作比较,甚至成为考题。
其实在一些常见业务常见中,两种技术实现方式并不存在孰优孰劣。只有结合具体业务场景,才能真正比较出哪种方式更合适。

 

Filter 相关流程

HandlerInterceptor 相关流程

 

现在的编程模式都是 遇到 新型 业务需求时先搜索一下别人是如何实现的。
我认为这是最普遍、性价比最高、几乎每个人都默认使用、对个人自身成长提升最快的模式。
注意我的用词“新型”。没有人天生就会;自己埋头苦研,不借助巨人力量的,都是傻子;而且肯定不会得到值得推广的成功。编程就是“抄”!
只要清楚它们在 HTTP Request Response 流程中的角色,看到别人给的常规实现方式,就自然会明白 为什么选其中一种而不选另一种。

 

示例:HandlerInterceptor 用于授权检查

每个项目可能有自己独特的授权检查需求。此示例仅供参考。
很多项目会用Session来存放用户信息(Session可能存储在Redis等中间件中,以实现分布式架构)

RequestContext:存储用户信息的帮助类

此处使用 ThreadLocal 存储的用户信息,不用担心OOM。因为:

  • 我们会在后续的HandlerInterceptor中清理用户信息
  • 即使清理时遇到异常,线程中的用户信息也不会无限增长。
    线程接到下一次用户请求时相关信息又会被设置为新请求的数据
public abstract class RequestContext {
  private static final ThreadLocal userIdHolder = new ThreadLocal();
  // 可根据需要添加各种用户信息字段

  public static String getUserId() { return userIdHolder.get(); }
  public static void setUserId(String id) { userIdHolder.set(id); }

  public static void clear() {
    userIdHolder.remove();
  }
}

AuthInterceptor:执行授权检查

public class AuthInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(
      HttpServletRequest request, HttpServletResponse response, Object handler) {
    // 从 response 获取用户相关标识,并进行授权检查 ...
    // 通过授权检查,并获得 User ID。如果未通过,可设置response相关内容,并返回 false
    String userId = ...
    
    // 保存用户信息,供后续 Controller 业务使用
    RequestContext.setUserId(userId);
  }

  @Override
  public void afterCompletion(
      HttpServletRequest request, HttpServletResponse response,
      Object handler, @Nullable Exception ex) throws Exception {
    // 清除之前保存的用户信息。
    // 为什么在 afterCompletion() 方法中清理,而不是在 postHandle() 中?
    // 因为如果业务代码中抛出异常,将跳过 postHandle() 方法,但不会跳过 afterCompletion().
    // 详见 DispatcherServlet.doDispatch() 方法
    RequestContext.clear();
  }
}

应用 AuthInterceptor

@Configuration
public class MyWebAppConfigurer implements WebMvcConfigurer {
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new AuthInterceptor())
      .addPathPatterns("/**");
  }
}

使用Request用户信息

@RestController
public class TestController {
  @GetMapping("test")
  public void test() {
    String userId = RequestContext.getUserId();
    ...
  }
}
  • 大小: 45.9 KB
  • 大小: 42.9 KB
分享到:
评论

相关推荐

    Java WEB 篇九 Java servlet、filter、listener、interceptor ?.xmind

    Java WEB 篇九 Java servlet、filter、listener、interceptor 之间的区别和联系?

    基于Java(Struts2 框架)+Mysql实现(Web)学生成绩管理系统【100010053】

    数据验证:HTML5 的原生验证模式、Struts2 的 Validation 验证框架以及 Interceptor 拦截器、JavaEE 的 Filter 过滤器 学生端(修改个人信息、修改密码、查看成绩) 教师端(成绩查看与修改、录入成绩、所教科目管理...

    javaweb 项目中三种组件实例

    本资源实现java web项目中常见的三种组件:Filter[过滤器]、Listener[监听器]、Interceptor[拦截器]。就一个Controller层实例,对于初学者而言,是个不错的选择

    简单配置 shiro + spring +springMVC+hibernate简单框架

    SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。 配置applicationContext-shiro.xml 1. 配置authorizingRealm ...

    拦截器和控制器的区别

    过滤器 filter web.xml implements filter filterchain arg2.doFilter(req,resp); 监听器 servlet application /session /request 6/8 个 1、拦截器 定义拦截器的包 定义拦截器的核心 定义拦截器类 ...

    单点登录sso-shiro-cas-maven

    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <param-name>targetFilterLifecycle <param-value>true </filter> <filter-mapping> <filter-name>shiro...

    名为责任链或者拦截器或者过滤器的简单模拟

    以及最早学习到的java web中的javax.servlet.Filter的概念, 都是一种链式的处理流程,这一个环节处理完成,然后处理另一个环节,这样就可以在一个处理本身的之前和之后做一些事情了。 比如说,struts2中Action在...

    FilterAndInterceptor

    过滤器--是在java web中,提前过滤掉一些信息或者提前设置一些参数,然后再传入servlet/struts的 action进行业务逻辑处理。比如过滤掉非法url或者在传入servlet/struts的action前统一设置字符集,或者去除掉一些非法...

    J2EE应用开发详解

    第1章 Java Web应用开发简介 1 1.1 Java EE应用概述 1 1.2 Java EE概念 1 1.2.1 Java EE多层模型 1 1.2.2 Java EE体系结构 2 1.3 Java EE的核心API与组件 4 1.4 Web服务器和应用服务器 13 1.5 小结 16 第2章 建立...

    SpringBoot的拦截器

    idea软件。SpringBoot的拦截器的博客所写的例子。preHandle()方法的返回值true和false的详细区别还未描述

    ssh(structs,spring,hibernate)框架中的上传下载

     本文将围绕SSH文件上传下载的主题,向您详细讲述如何开发基于SSH的Web程序。SSH各框架的均为当前最新版本:  •Struts 1.2  •Spring 1.2.5  •Hibernate 3.0  本文选用的数据库为Oracle 9i,当然你可以在不...

    APACHE 2.2.9+TOMCAT6.0.18配置负载均衡

    filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/> tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> 这个设置是主要...

    SpringFilter:Springboot过滤器示例

    Filter首先在DispatcherServlet的前面运行,而Interceptor在DispatcherServlet和Controllr(Handler)之间运行。 筛选 Web应用程序上下文功能 使用Spring函数困难 通常,实现编码,CORS,XSS,LOG,证书,授权等。 ...

    SpringBoot2.0前后端分离开发之用户身份认证实战 (后端实现)

    本课程在技术栈层面涵盖了“用户身份认证”、“接口鉴权”等业务场景常用的大部分技术,包括Spring Boot2.x、Spring MVC、Mybatis、加密解密算法AES、雪花算法Snowflake、统一验参工具ValidatorUtil、JWT(Json Web ...

    webx3框架指南PDF教程附学习Demo

    现在有很多Java的Web框架可供选择,并且它们也都是免费的。例如: • Struts • Webwork • Tapestry • Spring MVC 以上框架都是非常优秀的。说实话,如果阿里巴巴网站在2001年开始,就有这么多可选择的话,...

Global site tag (gtag.js) - Google Analytics