SpringBoot Web 进阶:WebMvcConfigurer 配置、拦截器、过滤器、Servlet、监听器全详解
·
前言
WebMvcConfigurerAdapter 在 SpringBoot 2.0 + Spring5 中已经被废弃
原因:接口 WebMvcConfigurer 新增了默认方法,不再需要适配器继承;
新版标准写法:直接实现 WebMvcConfigurer 接口,不要继承过期的适配器类。
一、WebMvcConfigurer 常用扩展能力
1、标准配置类模板
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
// 1. 添加自定义拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
// 2. 静态资源映射
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
// 3. 全局跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
}
// 4. 视图控制器跳转
@Override
public void addViewControllers(ViewControllerRegistry registry) {
}
}
2、常用扩展逐一实现
(1)静态资源自定义映射
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 访问 /files/** 映射到服务器 D:/upload/ 真实物理路径
registry.addResourceHandler("/files/**")
.addResourceLocations("file:D:/upload/");
// classpath下静态目录
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
(2)全局CORS跨域
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET","POST","PUT","DELETE")
.allowCredentials(true)
.maxAge(3600);
}
(3)视图跳转(无Controller直接页面转发)
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 访问 /login 直接跳转到 login.html
registry.addViewController("/login").setViewName("login");
}
二、拦截器 HandlerInterceptor
特点
- 属于SpringMVC组件,只拦截Controller请求,不拦截静态资源、Servlet、Filter;
- 执行时机:
Filter → Servlet → Interceptor → Controller; - 不能获取原生
HttpServletRequest的流(可拿到,但无法二次读取); - 适合:登录校验、token校验、权限校验、接口日志、请求耗时统计。
步骤1:自定义拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor implements HandlerInterceptor {
// Controller执行之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
if(token == null || token.isEmpty()){
response.setStatus(401);
response.getWriter().write("未登录");
return false; // 拦截,不放行
}
return true; // 放行
}
// Controller执行完毕,视图渲染之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
// 整个请求结束后(视图渲染之后)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
步骤2:注册到WebMvcConfigurer
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 拦截所有接口
.excludePathPatterns("/login","/static/**","/files/**"); // 放行路径
}
三、过滤器 Filter
特点
- Servlet规范组件,在最外层,所有请求都会拦截(静态资源、Servlet、Controller全部拦截);
- 执行顺序:多个Filter按照注册顺序链式执行;
- 可修改request/response原始报文、编码统一、XSS过滤、全局编码、限流;
- 无法注入Spring Bean(需要特殊处理)。
两种注册方式
方式1:@WebFilter + 启动类 @ServletComponentScan
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "encodingFilter", urlPatterns = "/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 统一编码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response); // 放行
}
}
启动类开启扫描:
@SpringBootApplication
@ServletComponentScan // 扫描@WebFilter、@WebServlet、@WebListener
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
方式2:JavaConfig 注册FilterRegistrationBean
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<EncodingFilter> encodingFilter(){
FilterRegistrationBean<EncodingFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new EncodingFilter());
bean.addUrlPatterns("/*");
bean.setOrder(1); // 执行优先级,数字越小越先执行
return bean;
}
}
四、原生 Servlet 注册
使用场景
对接老旧原生Servlet、第三方SDK、特殊协议处理,现在Web项目极少手写原生Servlet。
方式1:注解 @WebServlet
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(urlPatterns = "/myServlet")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("自定义原生Servlet响应");
}
}
同样需要 @ServletComponentScan。
方式2:RegistrationBean注册
@Bean
public ServletRegistrationBean<MyServlet> myServletRegistrationBean(){
ServletRegistrationBean<MyServlet> bean = new ServletRegistrationBean<>();
bean.setServlet(new MyServlet());
bean.addUrlMappings("/myServlet");
return bean;
}
五、Servlet监听器 Listener
三大常用监听器:
ServletContextListener:应用启动/销毁监听(项目上线、关闭钩子)HttpSessionListener:会话创建/销毁(在线人数统计)ServletRequestListener:每次请求创建/销毁
示例:应用启动监听
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class AppListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
System.out.println("项目Tomcat容器启动完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("项目容器关闭");
}
}
启动类加 @ServletComponentScan 自动生效;
也可以用 ServletListenerRegistrationBean 代码注册。
六、执行完整调用顺序
客户端请求
↓
Filter1.doFilter()
↓
Filter2.doFilter()
↓
原生Servlet / DispatcherServlet(SpringMVC前端控制器)
↓
Interceptor.preHandle()
↓
Controller 执行
↓
Interceptor.postHandle()
↓
视图渲染
↓
Interceptor.afterCompletion()
↓
Filter 后续逻辑返回
↓
响应返回浏览器
七、拦截器Interceptor vs 过滤器Filter 核心区别汇总
| 对比项 | Filter 过滤器 | Interceptor 拦截器 |
|---|---|---|
| 归属规范 | Servlet规范,Tomcat原生 | SpringMVC框架组件 |
| 拦截范围 | 所有请求(静态资源、Servlet、Controller) | 仅Controller接口,静态资源不拦截 |
| 执行层级 | 最外层,最先执行 | DispatcherServlet内部执行 |
| 能否注入Spring Bean | 默认不行,需额外包装 | 可以直接@Autowired注入 |
| 使用场景 | 编码统一、XSS过滤、跨域、流包装、全局请求替换 | 登录校验、Token校验、权限、接口耗时、日志 |
更多推荐



所有评论(0)