Java DispatcherServlet如何在REST和MVC处理程序方法之间进行选择?

Java DispatcherServlet如何在REST和MVC处理程序方法之间进行选择?,java,spring,rest,spring-mvc,Java,Spring,Rest,Spring Mvc,假设我有一个Spring MVC(3.2+)应用程序,其控制器实现如下所示: @Controller public class OrderController{ @Autowired OrderRepository orderRepository; //"RESTful" method @RequestMapping(value="/orders/{id}", method=RequestMethod.GET, produces = {"application/jso

假设我有一个Spring MVC(3.2+)应用程序,其控制器实现如下所示:

@Controller
public class OrderController{

    @Autowired OrderRepository orderRepository;

    //"RESTful" method
    @RequestMapping(value="/orders/{id}", method=RequestMethod.GET, produces = {"application/json", "application/xml"})
    @ResponseStatus(HttpStatus.OK)
    public @ResponseBody Order getOrder(@PathVariable("id") long id) {
       return orderRepository.findOrderById(id);
    }

    //"MVC" method
    @RequestMapping(value="/orders/{id}", method=RequestMethod.GET)
    public String getOrder(Model model, @PathVariable("id") long id) {
       model.addAttribute(getOrder(id));
       return "orderDetails";
    }
}
这里我有两个请求映射,它们将处理URI“/orders/{id}”的请求。一种是“RESTful”,因为它生成json或xml。另一个是传统的MVC,因为它更新传入的模型并返回逻辑视图名称

我的问题是Spring(DispatcherServlet)究竟如何决定调用这两个方法中的哪一个?我的直觉(以及的文档)告诉我,它将基于传入请求的“Accept”头

然而,这引出了另一个问题:Accept头匹配有多“严格”?下面我列出了几个不同的请求场景,在上述映射的情况下,Spring将如何处理这些请求

情景1 情景2 情景3 (请注意,场景2和场景3都指定它们将接受application/xml…而不是“仅”接受application/xml)

我的问题是Spring(DispatcherServlet)到底是如何决定的 要调用这两个方法中的哪一个

正如您所猜测的,它试图通过使用
@RequestMapping
的其他属性来消除歧义

美国

映射请求的可生产媒体类型,缩小主映射范围

格式为单一媒体类型或媒体类型序列,带有 仅当
Accept
与其中一种媒体类型匹配时,才映射请求

将选择最具体的处理程序,即匹配大多数映射属性的处理程序。在存在歧义的情况下,Spring将抛出异常


在您的三个场景中,由于
application/xml
是可以接受的,因此将使用具有相应
products
的handler方法。

。因此,考虑到大多数现代浏览器都将“application/xml”定义为其接受头的一部分(2和3是从默认的firefox和chrome接受头复制的);如果我从web浏览器访问www.example.com/myApp/orders/123,则不会调用我的“MVC”方法?@FGreg您最好尝试一下。(但是,是的,
生成的方法将被调用。)(请注意,XML和JSON不一定会使它更加Restful。)我确实验证了它的行为,正如您在这里解释的那样。我发现让浏览器启动“MVC”方法最简单的方法就是简单地将
headers=“User Agent”
添加到该方法的请求映射中。这样,如果是浏览器,将返回逻辑视图名称并呈现视图。
GET /orders/123
HOST: www.example.com
Accept: application/json, application/xml
GET /orders/123
HOST: www.example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
GET /orders/123
HOST: www.example.com
Accept: application/xml,application/xhtml+xml,text/html;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5