静态资源映射与 CORS 跨域配置
前后端分离时代,CSS/JS/图片、以及浏览器的跨域访问限制都是接口开发绕不开的配置项。这一章讲 Spring MVC 如何托管静态资源、如何放开 CORS。
静态资源映射
把 classpath 或文件系统的目录暴露成 URL 路径,用 WebMvcConfigurer.addResourceHandlers:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**") // URL 前缀
.addResourceLocations("classpath:/static/") // 物理位置(以 / 结尾)
.setCachePeriod(3600); // 缓存秒数
// 也支持 file:/data/upload/ 指向服务器磁盘目录
}
}
// 访问 /static/app.js → classpath:/static/app.js
- addResourceLocations 必须以 / 结尾,可写多个位置按顺序找。
- 静态资源处理器还支持 Last-Modified/ETag 校验、资源链(ResourceChain)与版本号策略(内容指纹缓存),细节以官方文档为准。
- 当 DispatcherServlet 映射 / 时,找不到映射的路径可委托容器默认 Servlet:
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
注意:控制器 @GetMapping("/static/**") 之类若与资源映射冲突,按 HandlerMapping 顺序,注解映射优先——想让两者各管一段,路径设计上就分开前缀。
CORS 是什么
浏览器同源策略:页面 https://example.com 里的 JS 默认不能跨源调用 https://api.example.com 的接口。CORS(跨源资源共享)通过响应头 Access-Control-Allow-Origin 等告诉浏览器「这个源允许访问」。
- 简单请求:直接带上 Origin 发请求,看响应头放不放行。
- 预检请求:非简单请求(自定义头、PUT/DELETE、application/json 等)先发 OPTIONS 预检,通过后才发真实请求。
注解式:@CrossOrigin
最小粒度,标在方法或类上:
@RestController
@CrossOrigin(origins = "https://example.com") // 类级别:整个控制器放行该源
public class UserApi {
@GetMapping("/api/users/{id}")
@CrossOrigin(origins = "*", maxAge = 3600) // 方法级别覆盖类级别
public User getUser(@PathVariable Long id) { ... }
}
全局配置:addCorsMappings
集中管理所有接口的跨域策略:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://example.com") // 精确允许的源
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true) // 是否允许携带 Cookie
.maxAge(3600); // 预检结果缓存秒数
}
- allowedOrigins("") 与 allowCredentials(true) 不能同时使用(通配配凭证不安全);Spring 5.3+ 提供 allowedOriginPatterns("") 来表达「任意源 + 携带凭证」,具体限制以官方文档为准。
- allowCredentials(true) 时浏览器要求 Access-Control-Allow-Origin 返回具体源而非 *。
- 不用注解时,预检 OPTIONS 由 MVC 内部 CORS 拦截逻辑处理;若请求没命中任何处理器(例如被安全框架挡在前面),可改用 org.springframework.web.filter.CorsFilter 在过滤器层处理,方案对比以官方文档为准。
常见坑
- 只配了接口 CORS 忘了静态资源/文件下载接口 → 分开配多段 mapping。
- 改了 allowedOrigins 没生效 → 检查是否走了缓存(maxAge)或代理层丢头。
- 出现「CORS 头缺失」但明明配了 → 多半是异常被全局处理后响应头被覆盖,或 OPTIONS 被过滤器/鉴权拦截。
静态资源让 URL 直达文件,CORS 让跨源调用有章可循。资源映射记住「URL 前缀 → 物理位置」成对出现,跨域记住「源 + 方法 + 头 + 凭证」四要素齐配,开发环境与生产环境各配一份。