【问题标题】:Spring MVC does not handle RequestMethod.OPTIONSSpring MVC 不处理 RequestMethod.OPTIONS
【发布时间】:2014-05-30 23:52:31
【问题描述】:

我在 Rest API 的上下文中。当我执行跨域请求时,我需要发回标头“Access-Control-Allow-Origin”。

我有一个这样的控制器:

@Controller
@RequestMapping("/api")
public class PackageManagerRestController {


    @RequestMapping(method = RequestMethod.OPTIONS, value = "/test")
    public void commonOptions(HttpServletResponse theHttpServletResponse) throws IOException {
        theHttpServletResponse.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with");
        theHttpServletResponse.addHeader("Access-Control-Max-Age", "60"); // seconds to cache preflight request --> less OPTIONS traffic
        theHttpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        theHttpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
    }

    @RequestMapping(method = RequestMethod.GET, value = "/test")
    public void getPtions(HttpServletResponse theHttpServletResponse) throws IOException {
        theHttpServletResponse.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with");
        theHttpServletResponse.addHeader("Access-Control-Max-Age", "60"); // seconds to cache preflight request --> less OPTIONS traffic
        theHttpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        theHttpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
    }
}

如果我使用 GET 运行测试,结果符合预期:

$ curl -i -X GET http://localhost:8081/api/test
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Access-Control-Allow-Headers: origin, content-type, accept, x-requested-with
Access-Control-Max-Age: 60
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Content-Length: 0
Date: Wed, 16 Apr 2014 08:18:38 GMT

但是,如果我使用 OPTIONS 发送请求,控制器将永远不会处理该请求:

$ curl -i -X OPTIONS http://localhost:8081/api/test
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Wed, 16 Apr 2014 08:19:56 GMT

任何人都知道为什么我会收到这个“默认响应”以及为什么我不能自定义它?

【问题讨论】:

  • 您在项目中使用 Spring Security 吗?如果是这样,据我所知,Spring Security 确实允许您仅发出跨域 GET 请求,并在其默认配置中阻止其他 HTTP 方法类型。
  • 默认 Spring DispatcherServlet 仅支持 GET、HEAD、POST、PUT、PATCH 和 DELETE;如果您想支持 TRACE 和 OPTIONS,您必须将“dispatchOptionsRequest”和“dispatchTraceRequest”属性设置为“true”;在这里查看docs.spring.io/spring/docs/4.0.3.RELEASE/javadoc-api

标签: spring spring-mvc tomcat7 http-options-method


【解决方案1】:

根据上一个答案 我解决了我的问题

@RequestMapping(value = "/**",method = RequestMethod.OPTIONS)
public String getOption(HttpServletResponse response,Model model)
{
    response.setHeader("Access-Control-Allow-Origin","*");

    response.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");

    return "";
}

我们需要在dispacherservlet中添加一些东西

<init-param>
        <param-name>dispatchOptionsRequest</param-name>
        <param-value>true</param-value>
    </init-param>

这就结束了

【讨论】:

  • getOption 可以返回 void 而不是 string 并且您不需要 return "";。干净了一点。
  • 这只是我的习惯......不管它是否宁静
【解决方案2】:

对于默认 Spring DispatcherServlet 仅支持 GET、HEAD、POST、PUT、PATCH 和 DELETE;如果您想支持 TRACE 和 OPTIONS,您必须将“dispatchOptionsRequest”和“dispatchTraceRequest”属性设置为“true”;在这里查看 docs.spring.io/spring/docs/4.0.3.RELEASE/javadoc-api

为了在您的 web.xml 中也支持 OPTIONS,您必须输入以下内容:

<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>

通过添加它我可以处理选项:

~$ curl -i -X OPTIONS http://localhost:8180/sample/api/test
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Access-Control-Allow-Headers: origin, content-type, accept, x-requested-with
Access-Control-Max-Age: 60
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Wed, 16 Apr 2014 08:44:55 GMT

安杰洛

【讨论】:

  • 不使用 web.xml 怎么能做到这一点?
  • @daniegarcia254:从spring 3.2开始在servlet 3环境中,有多种DispatcherServlet初始化器;例如,您可以使用 AbstractAnnotationConfigDispatcherServletInitializer 并添加此代码以启用 dispatchOptionsRequest:protected void customizeRegistration(Dynamic registration) {registration.setInitParameter("dispatchOptionsRequest", "true");}
  • 我已经应用了您的想法,但仍然无法正常工作。你能检查我的问题吗? stackoverflow.com/questions/37733501/…
猜你喜欢
  • 2012-08-17
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 2013-05-01
  • 2015-04-28
  • 1970-01-01
相关资源
最近更新 更多