WebMvcConfigurer 是 Spring Boot 中用于扩展 Spring MVC 功能的接口,可以用来自定义 Web 相关的配置,例如:
✅ 跨域(CORS) 配置 addCorsMappings
✅ 拦截器(Interceptor) addInterceptors
✅ 静态资源映射 addResourceHandlers
✅ 消息转换器(Message Converter) configureMessageConverters
✅ 视图解析器(View Resolver) configureViewResolvers
✅ 参数解析
它的主要作用是在不改变 Spring Boot 默认行为的情况下,提供灵活的扩展能力。
复杂的解释: WebMvcConfigurer配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,可以自定义一些Handler,Interceptor,ViewResolver,MessageConverter。基于java-based方式的spring mvc配置,需要创建一个配置类并实现WebMvcConfigurer 接口;
在Spring Boot 1.5版本都是靠重写WebMvcConfigurerAdapter
的方法来添加自定义拦截器,消息转换器等。SpringBoot 2.0 后,该类被标记为@Deprecated(弃用)。官方推荐直接实现WebMvcConfigurer或者直接继承WebMvcConfigurationSupport。
/* 拦截器配置 */
void addInterceptors(InterceptorRegistry var1);
/* 视图跳转控制器 */
void addViewControllers(ViewControllerRegistry registry);
/** 静态资源处理 **/
void addResourceHandlers(ResourceHandlerRegistry registry);
/* 默认静态资源处理器 */
void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);
/** 这里配置视图解析器 **/
void configureViewResolvers(ViewResolverRegistry registry);
/* 配置内容裁决的一些选项 */
void configureContentNegotiation(ContentNegotiationConfigurer configurer);
/** 解决跨域问题 **/
public void addCorsMappings(CorsRegistry registry) ;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径
.allowedOrigins("https://frontend.com") // 允许特定域名
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的请求方法
.allowedHeaders("*") // 允许所有请求头
.allowCredentials(true) // 允许携带 Cookie
.maxAge(3600); // 预检请求的缓存时间
}
};
}
}
当然Nginx也可以实现
location / {
proxy_pass http://localhost:8080;
add_header 'Access-Control-Allow-Origin' 'https://frontend.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Allow-Credentials' 'true';
if ($request_method = OPTIONS) {
return 204;
}
}
a. 其中location /
其中/
代表匹配所有请求。
b. proxy_pass http://localhost:8080;
Nginx 会把所有匹配 / 的请求转发到 http://localhost:8080(假设 Spring Boot 运行在 8080 端口)。 这样前端请求 Nginx,Nginx 代理请求到 Spring Boot,对外隐藏后端服务。
c. add_header 'Access-Control-Allow-Origin' 'https://frontend.com';
允许跨域的前端来源
允许 https://frontend.com
访问后端 API。
如果改成'*'
,add_header 'Access-Control-Allow-Origin' '*';
表示所有域都可以访问:
d. add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
允许前端调用 GET、POST、OPTIONS、PUT、DELETE 方法。
e. add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
允许前端在请求中携带 Authorization(比如 Bearer Token)和 Content-Type 头。
f. add_header 'Access-Control-Allow-Credentials' 'true';
允许携带 Cookie
允许前端发送带有 Cookie 的跨域请求(如身份验证)。
⚠️ 如果启用 Access-Control-Allow-Credentials,必须指定具体的 Access-Control-Allow-Origin,不能用 *。
g.
if ($request_method = OPTIONS) {
return 204;
}
处理预检请求(OPTIONS)
当浏览器发送 OPTIONS 预检请求(比如跨域的 POST 请求),Nginx 直接返回 204 No Content,避免 Spring Boot 处理这类请求,提高性能。
总结
适用场景
✅ 前后端分离项目(前端 https://frontend.com,后端 http://localhost:8080)
✅ 使用 Nginx 代理后端 API,同时处理跨域
✅ 后端 API 需要支持身份验证(携带 Cookie 或 Token)
拦截器(HandlerInterceptor)可以用于日志记录、权限校验、请求处理等。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/api/**") // 只拦截 /api/ 开头的请求
.excludePathPatterns("/api/login", "/api/register"); // 这些路径不拦截
}
}
✅ 适用场景:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 将 /static/ 目录下的资源映射到 /resources/** 访问路径
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:/static/");
// 访问 http://localhost:8080/images/test.jpg 时,会去 D:/uploads/ 目录查找
registry.addResourceHandler("/images/**")
.addResourceLocations("file:D:/uploads/");
// 访问 http://localhost:8080/files/doc.pdf 时,会去 /home/user/docs/ 目录查找
registry.addResourceHandler("/files/**")
.addResourceLocations("file:/home/user/docs/");
}
}
说明
@Configuration
:标记该类为 Spring 配置类,使其生效。registry.addResourceHandler("/resources/**"):
/resources/**
的请求,会被映射到 classpath:/static/
目录下的资源(即 src/main/resources/static/
)。src/main/resources/static/css/style.css
可以通过 http://localhost:8080/resources/css/style.css
访问。/images/**
访问路径映射到 D:/uploads/ 目录(必须加 file: 前缀)。/files/**
访问 /home/user/docs/
目录下的资源。默认静态资源位置
如果没有自定义 WebMvcConfigurer,Spring Boot 默认会从以下位置加载静态资源:
classpath:/static/
classpath:/public/
classpath:/resources/
classpath:/META-INF/resources/
例如:
src/main/resources/static/index.html
可以直接通过 http://localhost:8080/index.html
访问。
但如果自定义了 WebMvcConfigurer,默认配置可能会被覆盖,因此需要手动添加 addResourceHandlers 方法来保持默认行为。
在 Spring Boot 中,默认的静态资源(如 CSS、JS、图片等)通常存放在 src/main/resources/static/
目录下,并且可以直接通过 http://localhost:8080/资源路径 访问。
但是,如果你想让应用访问 本地文件系统(比如 D:/uploads/ 或 /home/user/docs/),就需要手动配置 addResourceHandlers(),并使用 file: 前缀 指定外部目录。
示例 1:Windows 配置外部目录
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 让 /images/** 访问 D:/uploads/ 目录下的资源
registry.addResourceHandler("/images/**")
.addResourceLocations("file:D:/uploads/");
}
解释
示例2:同时支持多个目录
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:D:/uploads/", "file:/home/user/docs/");
}
这样访问 http://localhost:8080/uploads/test.jpg
时,Spring 会先去 D:/uploads/
目录找,再去 /home/user/docs/
目录找。
WebMvcConfigurer
还可以用于配置自定义视图解析器。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/"); // 视图文件前缀
resolver.setSuffix(".jsp"); // 视图文件后缀
return resolver;
}
}
✅ 适用场景:
在 Spring Boot 中,视图解析器(View Resolver) 负责将控制器返回的视图名称解析为实际的 视图文件(如 HTML、JSP、Thymeleaf 等)。如果你想自定义视图解析规则,可以实现 WebMvcConfigurer 接口。
Spring Boot 默认集成了 Thymeleaf 作为模板引擎,我们可以使用 WebMvcConfigurer 进行自定义配置,比如:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// 配置 Thymeleaf 视图解析器
registry.jsp("/WEB-INF/views/", ".jsp"); // 仅用于 JSP
}
}
解释
registry.jsp("/WEB-INF/views/", ".jsp")
/WEB-INF/views/
.jsp
registry.jsp()
主要用于 JSP 视图解析,如果使用 Thymeleaf,Spring Boot 会自动管理,无需额外配置。Spring Boot 提供了默认的 JSON 处理方式(Jackson),但如果你想使用 Gson 或自定义格式,可以在 WebMvcConfigurer 里配置消息转换器。
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public Gson gson() {
return new GsonBuilder().setPrettyPrinting().create();
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new GsonHttpMessageConverter(gson()));
}
}
✅ 适用场景: