拦截器和过滤器

spring boot中 拦截器和过滤器

拦截器

拦截器的执行流程

直接上代码,代码有注释

package com.hjx.config;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *  拦截器的实现
 */
@Component
public class MyInterceptor implements HandlerInterceptor {

    /**
     *
     *  预处理回调方法,实现处理器的预处理
     *  返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
     *  在方法处理前执行
     */

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Controller中的方法执行前执行");
        return true;  //返回值:true表示继续向下执行;false表示流程中断,不会继续调用其他的拦截器或即将执行的Controller中的方法
    }

    /**
     * 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Controller中的方法执行后执行");
    }

    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间,
     * 还可以进行一些资源清理,类似于try-catch-finally中的finally,
     * 但仅调用处理器执行链中
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("视图生成后执行");
    }


}

实现拦截器的方式有:

1.实现接口HandlerInterceptor,重写preHandle、postHandle、afterCompletion方法。最后将拦截器进行注册

2.继承HandlerInterceptorAdapter类(HandlerInterceptor接口的实现类)。

3.实现WebRequestInterceptor接口 或 继承该接口的实现类。

注意点:

1.当我们使用 继承 WebMvcConfigurationSupport 类的方式注册拦截器时,默认会对静态资源(包括templates下的资源)进行拦截,导致静态资源时出现:No mapping for GET xxxx的问题

在使用拦截器时,在配置拦截器的时候,由于在 Spring Boot 2.0 之前,我们都是直接继承 WebMvcConfigurerAdapter 类,然后重写 addInterceptors 方法来实现拦截器的配置。但是在 Spring Boot 2.0 之后,该方法已经被废弃了(当然,也可以继续用),取而代之的是 WebMvcConfigurationSupport 方法,如下

解决方案1:最简单的方式,实现WebMvcConfigurer接口注册拦截器即可对静态资源放行。如下:

@Configuration
public class ViewConfig implements WebMvcConfigurer {
    @Autowired
    // 过滤器配置  实现HandlerInterceptor接口
    private MyInterceptor myInterceptor;

        //对拦截器的配置
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 实现WebMvcConfigurer不会导致静态资源被拦截
            registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        }

}

解决方案2
依然使用继承类WebMvcConfigurationSupport 方法注册拦截器,但是还需重写其中一个方法addResourceHandlers用于对静态资源进行放行,如下:

/**
 * 用来指定静态资源不被拦截,否则继承WebMvcConfigurationSupport这种方式会导致静态资源无法直接访问
 * @param registry
 */
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    super.addResourceHandlers(registry);
}

不过,最好使用方案一:便于管理,代码更加轻巧。

多个拦截时的执行流程

preHandle会按照配置文件中的执行顺序执行。

但他们的postHandleafterCompletion方法会按照配置文件中的顺序反序执行

过滤器

实现方式1

1.使用组件注册的方式整合Filter,具体做法如下:

1.定义一个类实现Filter接口,重写init、doFilter、destory方法。并将该类使用@Component注解修饰。
2.新建一个配置类,使用@Configuration 修饰该类。声明一个方法,并用@Bean注解修饰(将该注解修饰的方法的返回值注入到Bean中),具体如下:

Component
public class Myfilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

@Bean
        public FilterRegistrationBean FilterRegister(Myfilter myfilter){
            FilterRegistrationBean registrationBean=new FilterRegistrationBean(myfilter);
            registrationBean.setUrlPatterns(Arrays.asList("/login","/a"));
            return registrationBean;
        }

实现方式2
通过路径扫描的方式,具体如下:

// 主启动类开启包扫描(要扫描的过滤器)
@ServletComponentScan("com.hjx.Controller.Filter")

// 对指定的路径进行拦截
@WebFilter(value = {"/a","/b"})
public class Myfilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

过滤器和拦截器的区别

区别

1.过滤器Filter基于Servlet实现过滤器的主要应用场景是对字符编码、跨域等问题进行过滤。Servlet的工作原理是拦截配置好的客户端请求,然后对Request和Response进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。

3.拦截器是SpringMVC中实现的一种基于Java反射(动态代理)机制的方法增强工具

4.过滤器属于Servlet级别,拦截器属于Spring级别
Filter是在javax.servlet包中定义的,要依赖于网络容器,因此只能在web项目中使用。
Interceptor是SpringMVC中实现的,归根揭底拦截器是一个Spring组件,由Spring容器进行管理。

5.过滤器基于函数回调方式实现,拦截器基于Java反射机制实现

相同点
1、拦截器与过滤器都是体现了AOP的思想,对方法实现增强,都可以拦截请求方法。

2、拦截器和过滤器都可以通过Order注解设定执行顺序

拦截器和过滤器执行路径图

在这里插入图片描述

应用场景

拦截器的应用场景:权限控制,日志打印,参数校验

过滤器的应用场景:跨域问题解决,编码转换

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值