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

时间:2014-11-07 22:36:28

标签: 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/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";
    }
}

这里我有2个请求映射,它们将处理URI" / orders / {id}"的请求。一个是" RESTful"因为它产生json或xml。另一种是传统的MVC,因为它更新传入的模型并返回逻辑视图名称。

我的问题是Spring(DispatcherServlet)究竟如何决定调用这两种方法中的哪一种?我的直觉(以及Producible Media Types的文档)告诉我,它将基于传入的请求"接受"报头中。

然而,这引出了另一个问题:如何严格' Accept标头匹配?下面我列出了一些不同的请求场景,Spring如何根据上述映射处理这些请求?

场景1

GET /orders/123
HOST: www.example.com
Accept: application/json, application/xml

场景2

GET /orders/123
HOST: www.example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

场景3

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

(请注意,场景2和场景3都指定他们将接受application / xml ...而不是' only' application / xml)

1 个答案:

答案 0 :(得分:1)

  

我的问题是Spring(DispatcherServlet)究竟是如何决定的   这两种方法中哪一种叫?

正如您所猜测的那样,它会尝试使用@RequestMapping的其他属性来消除歧义。

javadoc of RequestMapping#produces()

  

映射请求的可制作媒体类型,缩小主映射

     

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

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

在您的三种情况下,由于application/xml是可接受的,因此将使用具有相应produces的处理程序方法。