如何在SpringBoot项目中使用过滤器和拦截器

简介: 过滤器和拦截器是日常开发中常用技术,用于对特定请求进行增强处理,如插入自定义代码以实现特定功能。过滤器在请求到达 `servlet` 前执行,而拦截器在请求到达 `servlet` 后执行。`SpringBoot` 中的拦截器依赖于 `SpringBoot` 容器,过滤器则由 `servlet` 提供。通过实现 `Filter` 接口并重写 `doFilter()` 方法可实现过滤器;通过实现 `HandlerInterceptor` 接口并重写相应方法可实现拦截器。两者的主要区别在于执行时机的不同,需根据具体场景选择使用。

过滤器和拦截器都是日常开发中经常使用到的技术,他们都可以对特定的请求进行增强处理,比如在请求之前或之后插入自定义的代码,完成想要的功能。过滤器和拦截器最本质的区别是,过滤器是在请求到达servlet之前执行,拦截器则在请求到达servlet之后执行。需要注意的是,SpringBoot中的拦截器依赖于SpringBoot容器,而过滤器是servlet本身提供的。

过滤器的实现

过滤器依赖servlet中的Filter接口,自定义一个Filter的实现类,重写doFilter()方法

java

代码解读

复制代码

@Component
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("hello");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("world");
    }
}

filterChain.doFilter(servletRequest,servletResponse);这个方法的作用是放行请求,在这条语句的前后可以做一些自定义的操作,比如记录日志、定义请求和返回的字符集编码、或者对请求的参数进行处理等。现在过滤器还不能使用,因为SpringBoot的过滤器依赖其提供的过滤器链,所以要先把自定义的过滤器注册到过滤器链中。

java

代码解读

复制代码

@Configuration
public class WebConfig {
    private final MyFilter myFilter;
    @Autowired
    public WebConfig(MyFilter myFilter){
        this.myFilter = myFilter;
    }
    @Bean
    public FilterRegistrationBean<MyFilter> registFilter(){
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(myFilter);
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

上面的配置类中,我们将MyFilter对象注册到FilterRegistrationBean中,可以理解为通过FilterRegistrationBean将自定义的过滤器注册到了过滤器链中。setOrder(int)的作用是设置过滤器在过滤器链中的执行顺序,直越小顺序越靠前。addUrlPatterns(String... param)方法用来设置要拦截的请求路径。现在请求项目中的任意接口,都会在请求前打印hello,在请求后打印world

拦截器的实现

拦截器是基于SpringBootdispatcherServlet的处理器Handler拦截器实现的,直接上代码

java

代码解读

复制代码

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("请求前执行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("返回ModelAndView前执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("处理完请求后执行");
    }
}

上面是自定义的拦截器,重写了处理器拦截器接口的preHandlepostHandleafterCompletion方法,分别表示请求前执行返回ModelAndView前执行处理完请求后执行,然后同样的需要将拦截器注册到拦截器链中,代码如下

java

代码解读

复制代码

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final MyFilter myFilter;
    private final MyInterceptor myInterceptor;

    @Autowired
    public WebConfig(MyFilter myFilter,
                     MyInterceptor myInterceptor){
        this.myFilter = myFilter;
        this.myInterceptor = myInterceptor;
    }
    @Bean
    public FilterRegistrationBean<MyFilter> registFilter(){
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(myFilter);
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(1);
        return registrationBean;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).
                addPathPatterns("/**").order(1);
    }
}

直接沿用了自定义过滤器的配置类,并实现SpringMvc的配置接口WebMvcConfigurer,重写addInterceptors()方法,将我们自定义的拦截器注册到拦截器链中,同样的,也可以使用order()方法设置拦截器的在链中的执行顺序,值越小则优先级越高。addPathPatterns("/**")表示拦截任意请求。

测试拦截器和过滤器

编写一个测试Controller

java

代码解读

复制代码

@RestController
@RequestMapping("/sys")
public class SysUserController {
    @GetMapping(value = "/test")
    public String test() {
        return "200";
    }
}

上面的接口路径既符合过滤器的过滤条件,也符合拦截器的拦截条件,使用postman工具请求测试

控制台打印的数据如下图所示:

可以看到先执行了过滤器的请求前置代码打印了hello,然后过滤器放行后才进入到servlet控制层执行了控制器的前置、中置及后置方法,最后当控制层处理完请求后,最后才执行了过滤器中的请求后置代码打印了world

总结

  • 过滤器是在servlet之外执行的,过滤器的代码只会在servlet外层执行
  • 拦截器是基于servlet的处理器handler的,所以拦截器会在控制器处理器这一层执行
  • 过滤器和拦截器的主要区别是执行的时机不同,虽然他们的作用相似,但是在实际开发中,要根据具体的场景,在两者中做出更合适的选择


转载来源:https://juejin.cn/post/7407621980574990399

目录
打赏
0
3
4
1
195
分享
相关文章
微服务——SpringBoot使用归纳——Spring Boot开发环境搭建和项目启动
本文介绍了Spring Boot开发环境的搭建和项目启动流程。主要内容包括:jdk的配置(IDEA、STS/eclipse设置方法)、Spring Boot工程的构建方式(IDEA快速构建、官方构建工具start.spring.io使用)、maven配置(本地maven路径与阿里云镜像设置)以及编码配置(IDEA和eclipse中的编码设置)。通过这些步骤,帮助开发者顺利完成Spring Boot项目的初始化和运行准备。
57 0
微服务——SpringBoot使用归纳——Spring Boot开发环境搭建和项目启动
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
18 0
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——使用Logger在项目中打印日志
本文介绍了如何在项目中使用Logger打印日志。通过SLF4J和Logback,可设置不同日志级别(如DEBUG、INFO、WARN、ERROR)并支持占位符输出动态信息。示例代码展示了日志在控制器中的应用,说明了日志配置对问题排查的重要性。附课程源码下载链接供实践参考。
49 0
SpringBoot项目打war包流程
本文介绍了将Spring Boot项目改造为WAR包并部署到外部Tomcat服务器的步骤。主要内容包括:1) 修改pom.xml中的打包方式为WAR;2) 排除Spring Boot内置的Tomcat依赖;3) 添加Servlet API依赖;4) 改造启动类以支持WAR部署;5) 打包和部署。通过这些步骤,可以轻松地将Spring Boot应用转换为适合外部Tomcat服务器的WAR包。
229 64
SpringBoot项目打war包流程
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——指定项目配置文件
在实际项目中,开发环境和生产环境的配置往往不同。为简化配置切换,可通过创建 `application-dev.yml` 和 `application-pro.yml` 分别管理开发与生产环境配置,如设置不同端口(8001/8002)。在 `application.yml` 中使用 `spring.profiles.active` 指定加载的配置文件,实现环境快速切换。本节还介绍了通过配置类读取参数的方法,适用于微服务场景,提升代码可维护性。课程源码可从 [Gitee](https://gitee.com/eson15/springboot_study) 下载。
37 0
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
在微服务架构中,随着业务复杂度增加,项目可能需要调用多个微服务。为避免使用`@Value`注解逐一引入配置的繁琐,可通过定义配置类(如`MicroServiceUrl`)并结合`@ConfigurationProperties`注解实现批量管理。此方法需在配置文件中设置微服务地址(如订单、用户、购物车服务),并通过`@Component`将配置类纳入Spring容器。最后,在Controller中通过`@Resource`注入配置类即可便捷使用,提升代码可维护性。
22 0
SpringBoot项目打包成war包
通过上述步骤,我们成功地将一个Spring Boot应用打包成WAR文件,并部署到外部的Tomcat服务器中。这种方式适用于需要与传统Servlet容器集成的场景。
55 8
|
3月前
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
177 36
SpringBoot start.aliyun.com创建项目,解决properties乱码的问题
通过确保文件和开发环境的编码一致,配置 Maven 编码,设置 Spring Boot 应用和嵌入式服务器的编码,可以有效解决 properties 文件的乱码问题。以上步骤可以帮助开发者确保在 Spring Boot 项目中正确处理和显示多语言字符,避免因编码问题导致的乱码现象。
61 5
SpringBoot项目的html页面使用axios进行get post请求
SpringBoot项目的html页面使用axios进行get post请求
72 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等