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

Behaviour of REST service using HTTPServletRequest and using @PathVariable

以下是我在学校为一个项目编写服务代码时遇到的两个场景。

场景 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. 如果我使用第一种方法,我可以使用 link 从任何浏览器甚至 Postman 访问结果。

  2. 如果我使用第二种方法,只有当我指定 Accept Headers 时,我才能使用 Postman 访问结果。如果我使用浏览器,它会显示错误 406,类型不受支持。

  3. 对 URL.

  4. 稍作修改,使用客户端都可以正常工作

这是什么原因造成的?我假定 HttpServletRequest 中的默认设置?如果我们使用第二种方法,网站将如何运行,或者我做错了什么?

如果您指定

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

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

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

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

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

没有 Bob,您将无法访问第二个 URI,这与第一个 URI 不同;你可能想要 other 而不是 fname.

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

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

在这种情况下,您的请求 URI 应该 真的 只是 customer 查询 firstName.

/customer?firstName=Bob