栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot中Interceptor和Filter的使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot中Interceptor和Filter的使用

目录
  • `Interceptor` 拦截器
    • 拦截器概述
    • 拦截器中方法的执行流程
    • 拦截器的配置
      • 传统项目拦截器的配置
      • `springboot` 项目拦截器的配置
        • 实现 `HandlerInterceptor` 接口编写拦截器
        • 实现 `WebMvcConfigurer` 接口注册拦截器
      • 多个拦截器的执行顺序
  • `Filter` 过滤器
    • 过滤器概述
    • 过滤器的配置
      • 传统项目过滤器的配置
      • `springboot` 项目过滤器的配置
        • 方式一:`@WebServlet + @ServletComponentScan` 注解
          • `@WebFilter` 注解开发过滤器
          • 启动类增加 `@ServletComponentScan`
        • 方式二:`FilterRegistrationBean` 注册
          • 实现 `Filter` 接口
          • 在配置类中注册该过滤器
  • `Interceptor` 和 `Filter` 小结

Interceptor 拦截器 拦截器概述

HandlerInterceptor 接口,该接口提供了拦截器的功能,如果自定义拦截器就要实现该接口,HandlerInterceptor 源码如下

public interface HandlerInterceptor {
	
	// 该方法会在控制器方法前执行
	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return true;
	}

	// 该方法会在控制器方法调用之后,且解析视图之前执行
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}
	
	// 该方法会在整个请求完成,即视图渲染结束之后执行
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}
}

Interceptor 依赖于 web 框架,我们经常在 springMVC 中用到该配置,在这个场景下 Interceptor 就依赖于 springMVC 框架。Interceptor 基于 Java 的反射机制,属于AOP 的一种运用

  • 由于拦截器是基于 web 框架的调用,因此可以使用 spring 的依赖注入进行一些业务操作,同时一个拦截器实例在一个 controller 生命周期之内可以多次调用
  • 只能对 controller 请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理
拦截器中方法的执行流程

  • 请求到达 DispatcherServlet,DispatcherServlet 发送至 Interceptor ,执行 preHandle() 方法,该方法会返回一个布尔值。如果为 false ,则结束所有流程:如果为 true , 则执行下一步
  • 请求达到 controller,执行处理器逻辑,它包含控制器的功能
  • 执行 postHandle() 方法
  • 执行视图解析和视图渲染
  • 执行 afterCompletion() 方法
拦截器的配置 传统项目拦截器的配置

基于 springMVC 的项目 ,我们之前的案例配置拦截器的方式如下

springboot 项目拦截器的配置 实现 HandlerInterceptor 接口编写拦截器

继承 HandlerInterceptorAdapter 也可以,它是 HandlerInterceptor 的子类

public class MyInterceptor implements HandlerInterceptor {

	// preHandle在执行Controller之前执行
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("MyInterceptor-处理器执行前方法preHandle,返回true则不拦截后续的处理");
		return true;
	}

	// postHandle在请求执行完之后 渲染ModelAndView返回之前执行
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
		System.out.println("MyInterceptor-处理器处理后方法postHandle");
	}

	// afterCompletion在整个请求执行完毕后执行,无论是否发生异常都会执行
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
		System.out.println("MyInterceptor-处理器完成后方法afterCompletion");
	}
}
实现 WebMvcConfigurer 接口注册拦截器

先说明下几个可以用来注册拦截器的类和接口

  • WebMvcConfigurerAdapter: springboot 2.0 以后的版本已失效
  • WebMvcConfigurationSupport: 不需要返回逻辑视图,可以选择继承此类
  • WebMvcConfigurer:返回逻辑视图,可以选择实现此方法,重写 addInterceptor() 方法
@Configuration 
public class WebConfig implements WebMvcConfigurer {

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 注册拦截器到 springMVC 机制, 然后它会返回一个拦截器注册
		InterceptorRegistration regist =  registry.addInterceptor(new MyInterceptor());
		// 指定拦截匹配模式,限制拦截器拦截请求
		regist.addPathPatterns("/artisan/interceptor/*");
		// 不拦截的路径
		regist.excludePathPatterns("/artisan/interceptor/exclude/*");
	}
}
多个拦截器的执行顺序

使用的是责任链模式的规则:对于 preHandle() 采用 先注册先执行,而 postHandle() 和 afterCompletion() 则是 先注册后执行

Filter 过滤器 过滤器概述

过滤器 Filter,是在 Servlet 规范中定义的,是 Servlet 容器支持的,该接口定义在 javax.servlet 包下,主要是对客户端请求 HttpServletRequest 进行预处理,以及对服务器响应 HttpServletResponsen 进行后处理。Filter 接口源码如下

package javax.servlet;

import java.io.IOException;

public interface Filter {

    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {}
}

该接口包含了 Filter 的 3 个生命周期:init()、doFilter()、destroy()

  • init():Servlet 容器在初始化 Filter 时,会触发 Filter 的 init() 方法,一般来说是当服务启动时,这个方法只调用一次,用于初始化 Filter
  • doFilter():当 init() 方法初始化 Filter 后,Filter 拦截到用户请求时,Filter 就开始工作了
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

Servlet 容器会将用户请求封装成 ServletRequest,而 doFilter() 参数中就 ServletRequest,这也就意味着允许给 ServletRequest 增加属性或者增加 header,也可以修饰 ServletReqest 或者 ServletResponse 来改变其行为

请注意最后一个参数 FilterChain var3,该接口定义如下

public interface FilterChain {

    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

该参数存在意味着,到达用户请求的真正方法之前,可能被多个过滤器进行过滤,这时 Filter.doFilter() 方法将触发 Filter 链条中下一个 Filter

  • destroy():顾名思义,该方法就是在 Servlet 容器要销毁 Filter 时触发,一般在应用停止的时候调用
过滤器的配置 传统项目过滤器的配置

传统项目配置使用 filter 的主要 2 个步骤

  • 实现 Filter 接口,实现其 doFilter() 方法
  • 在 web.xml 文件中使用 元素对编写的 filter 类进行注册,并设置它所能拦截的资源
  • 可以编写多个 Filter,组成一个 Filter 链,根据 Filter 在 web.xml 文件中的注册顺序,决定先调用哪个 Filter
springboot 项目过滤器的配置 方式一:@WebServlet + @ServletComponentScan 注解 @WebFilter 注解开发过滤器

@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器

@WebFilter(filterName = "HttpFilter2", urlPatterns = "/*")
public class HttpFilter2 implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("HttpFilter2  init");
		Filter.super.init(filterConfig);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("HttpFilter2  doFilter begin");

		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		System.out.println("HttpFilter2 name:" + request.getParameter("name"));

		// 将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,如果没有filter那就是请求的资源。
		chain.doFilter(request, response);
		System.out.println("HttpFilter2  doFilter end");
	}

	@Override
	public void destroy() {
		System.out.println("HttpFilter2  destroy");
		Filter.super.destroy();
	}
}
启动类增加 @ServletComponentScan

使用 @ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册

方式二:FilterRegistrationBean 注册 实现 Filter 接口
public class HttpFilter implements Filter {
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("HttpFilter  init");
		Filter.super.init(filterConfig);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("HttpFilter  doFilter begin");
		
		HttpServletRequest req =(HttpServletRequest) request;
		HttpServletResponse res =(HttpServletResponse) response;
		System.out.println("HttpFilter name:" + request.getParameter("name"));
		
		// 将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,如果没有filter那就是请求的资源。
		chain.doFilter(request, response);
		System.out.println("HttpFilter  doFilter end");
	}

	@Override
	public void destroy() {
		System.out.println("HttpFilter  destroy");
		Filter.super.destroy();
	}
}
在配置类中注册该过滤器
@Configuration
public class FilterConfig {
	
	@Bean
	public FilterRegistrationBean httpFilter(){
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		// 设置filter
		filterRegistrationBean.setFilter(new HttpFilter());
		// 拦截规则
		filterRegistrationBean.addUrlPatterns("/*");
		return filterRegistrationBean;
	}
}
Interceptor 和 Filter 小结
  • Filter 的执行顺序在 Interceptor 之前
  • Interceptor 是基于 Java 的反射机制,而过滤器 Filter 是基于函数回调
  • Filter 能做的事情,Interceptor 都能做,而且可以在请求前,请求后执行,比较灵活

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/285177.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号