spring-filter-intercepter-过滤器与拦截器

1. 过滤器 Filter

1.1 Filter 定义

Filter是sun公司中servlet2.3后增加的一个新功能,在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器。

Filter可以认为是Servlet的一种“加强版”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序.它依赖于servlet容器,在实现上,基于函数回调,它可以对几乎所有请求进行过滤。

1.2 Filter 工作原理

Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一处理等。

使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

  • 当服务器启动,会创建Filter对象,并调用init方法,只调用一次。
  • 当访问资源,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,
  • 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作。

1.3 Filter 应用场景

在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符、敏感词过滤、响应信息压缩、控制权限、控制转向、做一些业务逻辑判断等。

1.4 Filter 实例

1.定义 Filter

package com.demo.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
/**
* @author gx
*/
@Component
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
System.out.println("这是 myFilter 过滤器!");
filterChain.doFilter(request, response);
System.out.println("这是 myFilter 过滤器执行后!");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("这是 myFilter 初始化");
}
@Override
public void destroy() {
System.out.println("这是 myFilter 销毁");
}
}

2. 配置过滤器

  • 方式一:web.xml
<filter>
<description>测试过滤器</description>
<filter-name>TestFilter</filter-name>
<filter-class>com.test.filtes.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> 
  • 方式二:通过@WebFilter注解配置
@WebFilter(urlPatterns = "/*")
@Component
public class MyFilter2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
System.out.println("这是 myFilter2 过滤器!");
filterChain.doFilter(request, response);
System.out.println("这是 myFilter2 过滤器执行后!");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("这是 myFilter2 初始化");
}
@Override
public void destroy() {
System.out.println("这是 myFilter2 销毁");
}
}

启动类上可能需要这个注解:@ServletComponentScan

  • 方式三:通过@Bean来配置
package com.demo.component;
import com.demo.filter.MyFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author gx
*/
@Configuration
public class MyConfig {
@Autowired
private MyFilter myFilter;
//可以设置 order
@Bean
public FilterRegistrationBean registrationBean(){
FilterRegistrationBean filterRegister = new FilterRegistrationBean(myFilter);
filterRegister.addUrlPatterns("/*");
//可以设置过滤器顺序
filterRegister.setOrder(0);
return filterRegister;
}
}

2. 拦截器 Interceptor

2.1 Interceptor 定义

拦截器(Interceptor)和Servlet无关,它依赖于Web框架,在SpringMVC中就依赖于SpringMVC框架,由SpringMVC框架实现。在Struts2中同理,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制。

在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用。可以用于在某个方法或者字段被访问之前,进行拦截,然后在之前或者之后加入某些统一的处理方法。就是在action的前、后、甚至抛出异常时进行处理,比如动态代理就是拦截器的简单实现。

拦截器将很多service或者Controller中共有的行为提炼出来,在某些方法执行的前后执行,提炼为通用的处理方式,让被拦截的方法都能享受这一共有的功能,让代码更加简洁,同时,当共有的功能需要发生调整、变动的时候,不必修改很多的类或者方法,只要修改这个拦截器就可以了,可复用性很强。

SpringMVC的拦截器基于HandlerInterceptor接口来实现,所以只要实现HandlerInterceptor接口或者继承它的实现类。

2.2 Interceptor 工作原理

  • preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用。如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法。

  • postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成之后,所以我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法需要在当前对应的 Interceptor 类的 preHandle 方法返回值为 true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行。此方法主要用来进行资源清理

2.3 Interceptor 应用场景

  • 日志记录:记录请求操作日志(用户ip,访问时间等)

  • 权限检查:判断用户是否有权限访问资源,如校验token 日志记录

  • 性能监控:记录请求->响应时间,preHandle:记录开始时间,afterCompletion:记录结束时间,开始时间相减去结束时间

  • 登录验证:判断用户是否登录

  • sign校验,封禁校验等

  • 处理cookie,主题,国际化,本地化等

  • filter可以实现的功能intercepter基本上都能实现

2.4 Interceptor 实例

1. 定义拦截器

package com.demo.intercepter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyIntercepter implements HandlerInterceptor {
//进入 handler 之前:权限认证等
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("myIntercepter:preHandel 方法!");
return true;
}
//进入 handler 之后,返回 modelAndView 之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("myIntercepter:postHandle 方法!");
}
//执行完 handler 之后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("myIntercepter:afterCompletion 方法!");
}
}

Object handler 这个 handler 指拦截器拦截的内容,比如方法(HanderMethod)

2. 配置拦截器

  • 方式一:web.xml
<mvc:interceptors>
<!-- 如果直接配置bean,代表对所有请求都拦截 -->
<bean name="myIntercepter" class="com.demo.intercepter.MyIntercepter" />
<mvc:interceptor>
<!-- /**:拦截所有,/*拦截一层目录结构请求 -->
<mvc:mapping path="/**"/>
<!-- 不拦截的请求 -->
<mvc:exclude-mapping path="/testRequestEntity"/>
<!-- 自定义的拦截器引用 -->
<ref bean="myIntercepter"></ref>
</mvc:interceptor>
<mvc:interceptors/>
  • 方式二:WebConfig将拦截器注册添加到拦截器链
package com.demo.component;
import com.demo.intercepter.MyIntercepter;
import com.demo.intercepter.MyIntercepter1;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyIntercepter())
.addPathPatterns("/**")
.order(1);
}
}

spring 环境下这么玩

3. Filter 和 Interceptor 执行顺序

4. Filter 和 Interceptor 区别

过滤器(Filter)和拦截器(Interceptor)区别

过滤器(Filter)

拦截器(Interceptor)

总结

定义位置

Filter定义在java.servlet包下

接口HandlerInterceptor定义在org.springframework.web.servlet包下

配置位置

配置在web.xml中

配置在springmvc.xml中

作用位置

Filter在只在 Servlet 前后起作用,Filter 通常不考虑servlet 的实现

拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期

在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现

使用范围

Filter 是 Servlet 规范规定的

而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。

遵循规范

Filter 是遵循 Servlet 规范

而拦截器是在 Spring容器内的,是Spring框架支持的。

与spring关系

Filter 不能够使用 Spring 容器资源

Interceptor 是被 Spring 调用

Spring 中使用 interceptor 更容易

调用方

Filter 是被 Server(like Tomcat) 调用

Interceptor 是被 Spring 调用

因此 Filter 总是优先于 Interceptor 执行

实现方式

Filter 基于函数回掉

Interceptor基于java反射

demo 示例

https://gitee.com/zangsan/apz/tree/master/demo-boot/demo-filter/src/main/java/com/demo

参考文献

https://blog.csdn.net/tszc95/article/details/129250183

本文作者:Hi.PrimaryC

本文链接:https://www.cnblogs.com/cnff/p/18023433

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   primaryC  阅读(231)  评论(0编辑  收藏  举报
历史上的今天:
2021-02-20 Git基本操作
点击右上角即可分享
微信分享提示
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.