SpringBoot自定义OPTIONS方法出现双响应:排查来源及禁用默认处理
首先,咱们先搞清楚你收到的第二个OPTIONS响应的来源,再针对性解决问题。
额外响应的来源
你遇到的情况大概率是以下两种之一:
1. 浏览器自动触发的CORS预检请求
因为你的Ajax请求是跨域的(页面域名和服务器域名不一致),浏览器会自动在你手动发送的OPTIONS请求之前,发起一个CORS预检OPTIONS请求——这是浏览器的安全机制,和你的代码无关。这个预检请求会被Spring的默认CORS处理逻辑(或你配置的CORS规则)响应,而你手动发送的OPTIONS请求会被自定义的options()方法处理,所以会看到两个响应。
你可以打开浏览器开发者工具的Network面板验证:预检请求会带有Access-Control-Request-Method、Access-Control-Request-Headers这类头,而你手动发送的请求没有这些标识。
2. Spring Boot DispatcherServlet的默认OPTIONS处理
Spring Boot内置的DispatcherServlet默认会自动处理OPTIONS请求,即使你已经通过@RequestMapping自定义了处理逻辑。如果你的方法没有完全处理响应(比如返回了非void类型的结果),可能会触发默认逻辑,导致额外的响应头或重复响应。
对应的解决方法
如果是浏览器预检导致的重复响应
你完全不需要手动发送OPTIONS请求!跨域场景下,浏览器会自动处理预检流程,你只需要配置好CORS规则,让Spring正确响应预检即可。
删掉手动发送OPTIONS的Ajax代码,直接发送目标请求(比如GET/POST),浏览器会自动完成预检。如果需要自定义CORS规则,推荐用全局配置或@CrossOrigin注解,比自己写OPTIONS方法更规范:
// 全局CORS配置示例 @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "HEAD", "POST", "PUT", "OPTIONS") .allowedHeaders("*") .maxAge(3600); } }
如果是DispatcherServlet默认处理导致的重复响应
直接禁用DispatcherServlet的默认OPTIONS处理逻辑,让所有OPTIONS请求都交给你的自定义方法处理。在application.properties中添加配置:
spring.mvc.dispatch-options-request=false
或者在application.yml中:
spring: mvc: dispatch-options-request: false
另外,你的自定义OPTIONS方法可以优化一下:按照HTTP规范,OPTIONS请求不需要返回响应体,推荐返回void并设置204(No Content)状态码:
@RequestMapping(value = "/fetchData/{jiraid}", method = RequestMethod.OPTIONS) public void options(@PathVariable String jiraid, HttpServletResponse response) { response.setHeader("Access-Control-Allow-Methods","GET,HEAD,POST"); response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS"); response.setHeader("Access-Control-Allow-Origin","*"); response.setStatus(HttpServletResponse.SC_NO_CONTENT); // 204状态码更符合规范 }
内容的提问来源于stack exchange,提问作者codemania23

