本文首发于个人网站: Spring Boot 项目中如何定制拦截器 http://www.javaadu.online/?p=590
Servlet 过滤器属于 Servlet API, 和 Spring 关系不大. 除了使用过滤器包装 web 请求, Spring MVC 还提供 HandlerInterceptor(拦截器)工具. 根据文档, HandlerInterceptor 的功能跟过滤器类似, 但拦截器提供更精细的控制能力: 在 request 被响应之前, request 被响应之后, 视图渲染之前以及 request 全部结束之后. 我们不能通过拦截器修改 request 内容, 但是可以通过抛出异常 (或者返回 false) 来暂停 request 的执行.
Spring MVC 中常用的拦截器有: LocaleChangeInterceptor(用于国际化配置)和 ThemeChangeInterceptor. 我们也可以增加自己定义的拦截器, 可以参考这篇文章中提供的 demo http://lihao312.iteye.com/blog/2078139
实战
添加拦截器不仅是在 WebConfiguration 中定义 bean,Spring Boot 提供了基础类 WebMvcConfigurerAdapter, 我们项目中的 WebConfiguration 类需要继承这个类.
继承 WebMvcConfigurerAdapter;
为 LocaleChangeInterceptor 添加 @Bean 定义, 这仅仅是定义了一个 interceptor spring bean, 但是 Spring boot 不会自动将它加入到调用链中.
拦截器需要手动加入调用链.
修改后完整的 WebConfiguration 代码如下:
- package com.test.bookpub;
- import org.apache.catalina.filters.RemoteIpFilter;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.Web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.Web.servlet.config.annotation.WebMvcConfigurerAdapter;
- import org.springframework.Web.servlet.I18N.LocaleChangeInterceptor;
- @Configuration
- public class WebConfiguration extends WebMvcConfigurerAdapter {
- @Bean public RemoteIpFilter remoteIpFilter() {
- return new RemoteIpFilter();
- }
- @Bean public LocaleChangeInterceptor localeChangeInterceptor() {
- return new LocaleChangeInterceptor();
- }
- @Override public void addInterceptors(InterceptorRegistry registry {
- registry.addInterceptor(localeChangeInterceptor());
- }
- }
使用 mvn spring-boot:run 运行程序, 然后通过 httpie 访问 http://localhost:8080/books?locale=foo, 在终端看到如下错误信息.
- Servlet.service() for servlet [dispatcherServlet] in context with path []
- threw exception [Request processing failed; nested exception is
- java.lang.UnsupportedOperationException: Cannot change HTTP accept
- header - use a different locale resolution strategy] with root cause
PS: 这里发生错误并不是因为我们输入的 locale 是错误的, 而是因为默认的 locale 修改策略不允许来自浏览器的请求修改. 发生这样的错误说明我们之前定义的拦截器起作用了.
分析
在我们的示例项目中, 覆盖并重写了 addInterceptors(InterceptorRegistory registory)方法, 这是典型的回调函数 -- 利用该函数的参数 registry 来添加自定义的拦截器.
在 Spring Boot 的自动配置阶段, Spring Boot 会扫描所有 WebMvcConfigurer 的实例, 并顺序调用其中的回调函数, 这表示: 如果我们想对配置信息做逻辑上的隔离, 可以在 Spring Boot 项目中定义多个 WebMvcConfigurer 的实例.
Spring Boot 1.x 系列
Spring Boot 的自动配置, Command-line-Runner http://www.javaadu.online/?p=487
了解 Spring Boot 的自动配置 http://www.javaadu.online/?p=495
Spring Boot 的 @PropertySource 注解在整合 Redis 中的使用 http://www.javaadu.online/?p=499
Spring Boot 项目中如何定制 HTTP 消息转换器 http://www.javaadu.online/?p=515
Spring Boot 整合 MongoDB 提供 Restful 接口 http://www.javaadu.online/?p=518
Spring 中 bean 的 scope http://www.javaadu.online/?p=521
Spring Boot 项目中使用事件派发器模式 http://www.javaadu.online/?p=526
Spring Boot 提供 RESTful 接口时的错误处理实践 http://www.javaadu.online/?p=530
Spring Boot 实战之定制自己的 starter http://www.javaadu.online/?p=535
Spring Boot 项目如何同时支持 HTTP 和 HTTPS 协议 http://www.javaadu.online/?p=538
自定义的 Spring Boot starter 如何设置自动配置注解 http://www.javaadu.online/?p=546
Spring Boot 项目中使用 Mockito http://www.javaadu.online/?p=575
在 Spring Boot 项目中使用 Spock 测试框架 http://www.javaadu.online/?p=588
本号专注于后端技术, JVM 问题排查和优化, Java 面试题, 个人成长和自我管理等主题, 为读者提供一线开发者的工作和成长经验, 期待你能在这里有所收获.
来源: https://www.cnblogs.com/javaadu/p/11748716.html