6

当我RequestMapping在 Spring MVC 中配置我的 s 时,我想在使用AllowOPTIONS方法时自动生成正确的标头。

例如,使用此控制器:

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping(method = RequestMethod.GET)
    ResponseEntity<String> getTest() {
        return new ResponseEntity<>("test", HttpStatus.OK);
    }
}

现在,如果我OPTIONS向该 URL 发出请求,我会得到 405,方法不允许。相反,我希望它自动响应

Allow: GET, OPTIONS204 - No content

我有一个想法,像这样添加一个拦截器:

@Override 
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new HandlerInterceptor() {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if("OPTIONS".equalsIgnoreCase(request.getMethod())){
                response.setHeader("Allow", "GET, OPTIONS");
                response.setStatus(204);
                //TODO figure out the @Controller and what possible methods exist
                return false;
            }
            return true;
        }
        //Deleted excess methods for brevity
    });
}

如果我没有编写自定义拦截器,这个功能是否存在?如果不是,我该如何解决并查找发生调用TODO的同一 URL 上存在哪些注释?OPTIONS

4

4 回答 4

5

扩展 Sotiros 和 jhadesdev 的答案。如果使用 Java Config(如在 Spring Boot 中),您可以通过如下配置DispatchServlet来配置启用OPTIONS请求@Bean

@Bean
public DispatcherServlet dispatcherServlet() {
    DispatcherServlet servlet = new DispatcherServlet();
    servlet.setDispatchOptionsRequest(true);
    return servlet;
}

然后,我创建了一个接受 HttpMethods 可变参数的静态助手,如下所示:

public static ResponseEntity<Void> allows(HttpMethod... methods) {
    HttpHeaders headers = new HttpHeaders();
    Set<HttpMethod> allow = new HashSet<>();
    for(HttpMethod method: methods){
        allow.add(method);
    }
    headers.setAllow(allow);

    return new ResponseEntity<>(headers, HttpStatus.NO_CONTENT);
}

这使得创建我自己的OPTIONS映射变得简单,如下所示:

@RequestMapping(method = RequestMethod.OPTIONS)
ResponseEntity<Void> getProposalsOptions() {
    return allows(HttpMethod.GET, HttpMethod.OPTIONS);
}

虽然我认为 Spring MVC 可以OPTIONS自动提供响应是有道理的Interceptor,但您不能通过DispatcherServlet.

编写自己的响应的好处是在某些情况下根据用户的角色OPTIONS自定义响应是有意义的。OPTIONS例如,未经身份验证的 API 用户可能会收到Allow GET, OPTIONS,但管理员会获得完整的 API Allow GET, PUT, DELETE, OPTIONS。您可以根据在拨打电话时检查用户的角色来自定义响应OPTIONS

于 2014-01-03T15:03:48.597 回答
3

我不知道如何使它通用,尽管它不是通用的,但目前可以使用。

在 web.xml 中将调度程序 servlet 的 dispatchOptionsRequest 设置为 true,否则会阻止 servlet 容器将 OPTIONS 路由到应用程序:

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/mvc-dispatcher-servlet.xml</param-value>
    </init-param>
    <init-param>
        <param-name>dispatchOptionsRequest</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

然后在控制器中添加这个将返回 Allow: GET, OPTIONS 和 204 - No content:

@RequestMapping(value = "/tryoptions", method = RequestMethod.OPTIONS)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public ResponseEntity tryOptions(HttpSession session) throws Exception {
    HttpHeaders headers = new HttpHeaders();
    headers.set("Allow","OPTIONS, GET");
    return new ResponseEntity(headers, HttpStatus.NO_CONTENT);
}
于 2014-01-03T01:21:04.903 回答
2

Spring 4.3 中引入的更改简化了该用例。从现在开始,将自动为应用程序中的所有映射准备 OPTIONS 响应。无需手动配置框架,因为该功能开箱即用。

默认情况下,通过将“允许”响应标头设置为在具有匹配 URL 模式的所有 @RequestMapping 方法上显式声明的 HTTP 方法来处理 HTTP OPTIONS 请求。当没有明确声明 HTTP 方法时,“允许”标头设置为“GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS”

于 2016-07-31T13:31:43.293 回答
0

今天任何人都在看这个,它是这样完成的:

@RestController
@RequestMapping(value = "/user", method = RequestMethod.OPTIONS)
public class UserRestController {

只需RequestMethod.OPTIONS在您的请求映射中定义,即可定义整个控制器的 OPTIONS。

以下是更多信息的参考: https ://docs.spring.io/spring-framework/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-ann-requestmapping-head-options

于 2019-12-01T16:20:03.813 回答