共计 2483 个字符,预计需要花费 7 分钟才能阅读完成。
本文首发于个人网站:Spring Boot 项目中如何定制拦截器
Servlet 过滤器属于 Servlet API,和 Spring 关系不大。除了使用过滤器包装 web 请求,Spring MVC 还提供 HandlerInterceptor(拦截器) 工具。根据文档,HandlerInterceptor 的功能跟过滤器类似,但拦截器提供更精细的控制能力:在 request 被响应之前、request 被响应之后、视图渲染之前以及 request 全部结束之后。我们不能通过拦截器修改 request 内容,但是可以通过抛出异常(或者返回 false)来暂停 request 的执行。
Spring MVC 中常用的拦截器有:LocaleChangeInterceptor(用于国际化配置)和ThemeChangeInterceptor。我们也可以增加自己定义的拦截器,可以参考这篇文章中提供的 demo
实战
添加拦截器不仅是在 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
- 了解 Spring Boot 的自动配置
- Spring Boot 的 @PropertySource 注解在整合 Redis 中的使用
- Spring Boot 项目中如何定制 HTTP 消息转换器
- Spring Boot 整合 Mongodb 提供 Restful 接口
- Spring 中 bean 的 scope
- Spring Boot 项目中使用事件派发器模式
- Spring Boot 提供 RESTful 接口时的错误处理实践
- Spring Boot 实战之定制自己的 starter
- Spring Boot 项目如何同时支持 HTTP 和 HTTPS 协议
- 自定义的 Spring Boot starter 如何设置自动配置注解
- Spring Boot 项目中使用 Mockito
- 在 Spring Boot 项目中使用 Spock 测试框架
本号专注于后端技术、JVM 问题排查和优化、Java 面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。