【问题标题】:Optional @Pathvariable in REST controller spring 4REST控制器弹簧4中的可选@Pathvariable
【发布时间】:2017-11-30 06:42:39
【问题描述】:

我正在编写一个 Rest 服务(HTTP Get 端点),在下面的 uri 中执行以下操作

http://localhost:8080/customers/{customer_id}
  1. 获取在 uri 中传递的 customer_id 的详细信息
  2. 如果没有通过customer_id (http://localhost:8080/customers),获取所有客户的详细信息。

代码:

@RequestMapping(method = RequestMethod.GET, value = "customers/{customer_id}")
public List<Customer> getCustomers(
@PathVariable(name = "customer_id", required = false) final String customerId) {
LOGGER.debug("customer_id {} received for getCustomers request", customerId);

}

但是,使用上面的代码,对于第二种情况,控制流向 getCustomers()。

注意:我使用的是 Java8 和 spring-web 4.3.10 版本

非常感谢您对此提供的任何帮助。

【问题讨论】:

    标签: rest spring-mvc java-8 spring-restcontroller


    【解决方案1】:

    仅当您想将GET /customers/{customer_id}GET customers 都映射到单个java 方法时,才使用可选的@PathVariable

    如果您不发送customer_id,您将无法发送将发送到GET /customers/{customer_id} 的请求。

    所以你的情况是:

    @RequestMapping(method = RequestMethod.GET, value = {"/customers", "customers/{customer_id}"})
    public List<Customer> getCustomers(@PathVariable(name = "customer_id", required = false) final String customerId) {
        LOGGER.debug("customer_id {} received for getCustomers request", customerId);
    }
    

    需要公共抽象布尔值

    是否需要路径变量。

    默认为 true,如果传入请求中缺少路径变量,则会引发异常。如果在这种情况下您更喜欢 null 或 Java 8 java.util.Optional,请将其切换为 false。例如在用于不同请求的 ModelAttribute 方法上。

    您可以在 java8 中使用 nullOptional

    【讨论】:

    • value = {"/customers", "customers/{customer_id}"}) 是蚂蚁风格吗。
    • 谢谢@ByeBye.. 像魅力一样工作。
    • @ByeBye 当我将请求映射值作为数组提供时,刚刚注意到任何问题。我注册了一个类级请求映射,方法级请求映射如下:@RequestMapping(method = RequestMethod.GET, value = {"/", "/{customer_id}"})。当我调用 localhost:8080/customers 时,端点返回 404(没有尾部斜杠)。关于这里出了什么问题的任何线索。
    • @ByeBye PathVariable 怎么能接受所需的 false/true 等参数?它给我的编译时间错误
    • @RajeshHatwar docs.spring.io/spring/docs/current/javadoc-api/org/… 文档说该参数存在。
    【解决方案2】:

    这可能对尝试使用多个可选路径变量的人有所帮助。

    如果您有多个变量,则始终可以接受多个路径。 例如:

    @GetMapping(value = {"customers/{customerId}&{startDate}&{endDate}",
    "customers/{customerId}&{startDate}&",
    "customers/{customerId}&&{endDate}",
    "customers/{customerId}&&"
    })
    public Customer getCustomerUsingFilter(@PathVariable String customerId, @PathVariable Optional<Date> startDate, @PathVariable Optional<Date> endDate)
    

    然后您将使用所有 路径分隔符(在本例中为 &)

    调用此 URL

    喜欢
    GET /customers/1&& 或
    获取 /customers/1&&2018-10-31T12:00:00.000+0000 或
    获取 /customers/1&2018-10-31T12:00:00.000+0000& 或
    GET /customers/1&2018-10-31T12:00:00.000+0000&2018-10-31T12:00:00.000+0000

    【讨论】:

      【解决方案3】:

      您应该在这里创建两个端点来处理单个请求:

      @GetMapping("/customers")
      public List<Customer> getCustomers() {
      LOGGER.debug("Fetching all customer");  
      }
      
      @GetMapping("/customers/{id}")
      public List<Customer> getCustomers(@PathVariable("id") String id) {
      LOGGER.debug("Fetching customer by Id {} ",id);  
      }
      

      @GetMapping 等价于@RequestMapping(method = RequestMethod.GET)@GetMapping("/customers/{id}") 等价于@RequestMapping(method = RequestMethod.GET, value = "customers/{id}")

      更好的方法是这样的:

      @RestController
      @RequestMapping("/customers")
      public class CustomerController {
      
          @GetMapping
          public List<Customer> getAllCustomers() {
          LOGGER.debug("Fetching all customer");  
          }
      
          @GetMapping("/{id}")
          public Customer getCustomerById(@PathVariable("id") String id) {
          LOGGER.debug("Fetching customer by Id {} ",id);  
          }
      

      【讨论】:

      • 我最初是这样做的,但是这两个 java 方法都打算执行相同的操作。我正在寻找一种避免代码重复的单一 java 方法。正在寻找类似@ByeBye 建议的东西
      猜你喜欢
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 2019-07-10
      • 2014-12-14
      • 1970-01-01
      相关资源
      最近更新 更多