如何使用Spring MVC处理HTTP OPTIONS请求?

28
我想使用Spring MVC控制器拦截OPTIONS请求,但它被DispatcherServlet捕获了。我该怎么处理?

2
对于使用Spring Boot的人来说,这个后续问题可能会很有用:https://dev59.com/vFwX5IYBdhLWcg3w0iUc - Jonik
5个回答

34

我在Bozho的答案中为初学者添加了更多细节。 有时,让Spring控制器管理OPTIONS请求很有用(例如设置正确的“Access-Control-Allow-*”标头以响应AJAX调用)。 但是,如果您尝试通常的做法

@Controller
public class MyController {

    @RequestMapping(method = RequestMethod.OPTIONS, value="/**")
    public void manageOptions(HttpServletResponse response)
    {
        //do things
    }
}

由于 DispatcherServlet 将拦截客户端的 OPTIONS 请求,因此它不起作用。

解决方法非常简单:

您需要... 从 web.xml 文件中配置 DispatcherServlet 如下:

...
  <servlet>
    <servlet-name>yourServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>dispatchOptionsRequest</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
...

添加"dispatchOptionsRequest"参数,并将其设置为true。

现在DispatcherServlet将委托OPTIONS处理给您的控制器,manageOption()方法将被执行。

希望这能帮到你。

PS. 老实说,我看到DispatcherServlet将允许的方法列表附加到响应中。在我的情况下,这不重要,所以我放任不管。也许需要进一步的调查。


1
但是,如果例如在端点“/x/y”注册了处理程序方法,则此方法无效。现在,对于/x的OPTIONS请求有效,但对于/x/y则无效。 是否有任何选项来解决此问题?即将此OPTIONS处理添加到所有已注册的端点?我考虑使用拦截器,但是否还有其他方法? - wrm

12
@RequestMapping(value="/youroptions", method=RequestMethod.OPTIONS)
public View getOptions() {

}

您应该通过将其dispatchOptionsRequest设置为true来配置dispatcherServlet。


1
实际上这样做是行不通的,因为DispatcherServlet会拦截请求并处理它。应该配置DispatcherServlet来解决这个问题。我在这个问题上遇到了很多困扰,目前我只能部分解决了这个问题。我本想为社区贡献我的解决方案,但是...由于我的声望还不到100,stackoverflow要求我等待8小时才能回答自己的问题。 - MaVVamaldo
1
是的,这就是解决方案。我应该早点遇见你,天哪!XD 然而,这只是一个“部分”解决方案,因为DispatcherServlet在委派控制器之前会做一些工作。实际上,即使您不触及“允许”标头,它也会填充一个“允许方法”的列表。在我的情况下,这不是问题,但我想对其他人来说可能是个问题。 - MaVVamaldo
重要更新:从Spring Framework 4.3开始,OPTIONS请求将默认支持,请参见https://jira.spring.io/browse/SPR-13130获取更多详细信息。 - Sébastien Deleuze

8
作为对上述两个答案的快速补充,以下是如何在servlet 3(无web.xml)环境中启用dispatchOptionsRequest,因为我花了一些时间才弄清楚如何在非xml设置中应用上述答案。
在spring 3.2 / servlet 3环境中,您将拥有某种类型的DispatcherServlet初始化程序类,它是web.xml的Java等效项;在我的情况下,它是AbstractAnnotationConfigDispatcherServletInitializer。添加以下代码将启用dispatchOptionsRequest:
    @Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setInitParameter("dispatchOptionsRequest", "true");
    }

4

我采用了以下方法:

使用Maven (或手动) 导入以下依赖项:

<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>1.3.2</version>
</dependency>

这是一个用于捕获所有入站 OPTIONS 请求的实现。请将以下配置添加到 web.xml 文件中:

<filter>
   <filter-name>CORS</filter-name>
   <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>       
   <init-param>
      <param-name>cors.supportedHeaders</param-name>
      <param-value>Content-Type,Accept,Origin</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>CORS</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

我看到 /** 方法存在的问题是更具体的控制器实现会覆盖它。

0

对于没有web.xml文件的Spring项目,根据Paul Adamson的答案,我只需将参数dispatchOptionsRequest设置为true,以便在调度程序中处理Options方法调用。

ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new        DispatcherServlet(applicationContext));

dispatcher.setInitParameter("dispatchOptionsRequest", "true");                

dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接