假设我有一个带有控制器实现的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如何根据上述映射处理这些请求?
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
(请注意,场景2和场景3都指定他们将接受application / xml ...而不是' only' application / xml)
答案 0 :(得分:1)
我的问题是Spring(DispatcherServlet)究竟是如何决定的 这两种方法中哪一种叫?
正如您所猜测的那样,它会尝试使用@RequestMapping
的其他属性来消除歧义。
javadoc of RequestMapping#produces()
州
映射请求的可制作媒体类型,缩小主映射。
格式是单一媒体类型或媒体类型序列,带有 请求仅在
Accept
与其中一种媒体类型匹配时映射
最具体的处理程序,即。将选择大多数mappping属性匹配的位置。在存在歧义的情况下,Spring将抛出异常。
在您的三种情况下,由于application/xml
是可接受的,因此将使用具有相应produces
的处理程序方法。