使用HTTPServletRequest和使用@PathVariable的REST服务的行为

时间:2015-10-27 14:53:57

标签: spring rest spring-mvc spring-boot resttemplate

以下是我在为学校项目编写服务时遇到的两种情况。

场景1

@RequestMapping("/customer/firstName/")
public CustomerRepresentation getCustomersByFirstName(HttpServletRequest request) {
    String name = request.getParameter("fname");
    List<Customer> customer = customerActivity.findByCustFirstName(name);
    // etc
}

场景2

@RequestMapping(value="/customer/firstName/{fname}",method = RequestMethod.GET, produces = {"text/html","application/json", "application/xml"})
public @ResponseBody List<CustomerRepresentation> getCustomersByFirstName(@PathVariable("fname") String name) {
    List<Customer> customer = customerActivity.findByCustFirstName(name);
    // etc
}

行为:

  1. 如果我使用第一种方法,我可以使用任何浏览器甚至邮递员的链接访问结果。

  2. 如果我使用第二种方法,只有在指定Accept Headers时才能使用Postman访问结果。如果我使用浏览器,它会给我错误406,键入不支持。

  3. 使用客户端两者都可以正常工作,只需稍微修改一下URL。

  4. 是什么原因引起的?我假设HttpServletRequest中的默认设置?如果我们使用第二种方法,网站将如何运作,或者我做错了什么?

2 个答案:

答案 0 :(得分:1)

如果您指定

produces = {"text/html","application/json", "application/xml"}

您需要使用其中一种类型发送Accept标头。 有些客户端使用默认的Accept标头,它可能与您期望的不同。

答案 1 :(得分:1)

这两个URI在原则上是不同的,根本不应该被认为是相同的。

首先,路径变量和查询参数之间存在巨大差异 - 路径变量必需是路径的一部分,否则路径将无法访问。这是两个URI的区别:

/customer/firstName?fname=Bob
/customer/firstName/Bob

如果没有Bob,则无法访问第二个URI,而不是第一个URI;你可能会要求其他而不是fname

其次,您必须设置Accept标头的原因是由于produces数组的设置方式:您有text/htmlapplication/jsonapplication/xml;你的客户将无法接受任何不属于这三种类型的东西。

第三,要直接回答最后一个问题,我会明确地劝阻你的第二种方法,因为应该对路径变量进行分区。该路径描述了一些必需的信息,以便继续请求;在这里,您只询问有关客户的信息,该信息应包含在查询中。

在这种情况下,您的请求URI应该真的只有customer并且firstName的查询。

/customer?firstName=Bob