SpringBoot中HandlerInterceptor拦截器和过滤器的区别和使用

文章目录

    • 拦截器介绍
    • 过滤器介绍
    • 拦截器使用实例
    • 拦截器注意事项

拦截器介绍

简介

  • Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。

  • 依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。

  • 在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。

  • 由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。

  • 缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

应用场景

  • 拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

过滤器介绍

简介

  • 依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的requestresponse提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。

应用场景

  • 在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。

以下演示基于SpringBoot

拦截器使用实例

创建第一个拦截器

/**
 * @author xiao7
 * @date Created in 2020/7/5 21:15
 * @description 第一个拦截器测试
 */
public class FirstInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("第一个拦截器测试  preHandle");
        return true; //返回false将不往下执行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("第一个拦截器测试  postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("第一个拦截器测试  afterCompletion");
    }
}

注册进Spring容器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    /**
     * 注册拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new FirstInterceptor());
    }
}

创建控制器测试

@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping("/index")
    public String test() {
        return "test:";
    }
}

SpringBoot中HandlerInterceptor拦截器和过滤器的区别和使用_第1张图片

拦截器注意事项

拦截器的执行顺序

  • preHandle: 前置拦截器的执行顺序就是拦截器的注册顺序
    前置拦截如果返回true是允许继续执行,如果返回false是不继续执行了
  • postHandle :跟preHandle倒序
  • afterCompletion:跟preHandle倒序

部分源码截图

  • preHandle 执行源码 applyPreHandle
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				//如果前置拦截执行后返回false就直接执行triggerAfterCompletion,不执行其他拦截器了
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}
  • postHandle 执行源码 applyPostHandle
	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			//很明显示倒序了
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}

你可能感兴趣的:(Spring)