您将如何使用 Spring Boot 处理只有可选查询参数的 REST API?
How would you handle a REST API with only optional query params with Spring Boot?
我想构建一个简单的端点,returns 一个 Order
对象,我可以在其中通过单个查询参数或多个查询参数的组合来搜索此订单。所有这些查询参数都是可选的,原因是不同的人会根据不同的 ID 访问这些订单。
例如:
/order/items?itemId={itemId}&orderId={orderId}&deliveryId={deliveryId}&packetId={packetId}
@GetMapping(path = "/order/items", produces = "application/json")
public Order getOrders(@RequestParam Optional<String> itemId,
@RequestParam Optional<String> orderId,
@RequestParam Optional<String> deliveryId,
@RequestParam Optional<String> packetId) { }
我当然也可以跳过 Java 可选并使用 @RequestParam(required = false)
,但这里的问题是如何摆脱 if-else
或 .isPresent()
的噩梦检查查询参数是否为空?或者是否有一种优雅的方式(取决于参数的组合)进一步传递到我的服务和 Spring Data JPA 存储库。
我的小建议是避免使用过于笼统的 API,例如您可以将映射拆分为多个端点,例如:/order/delivery/itemId/{itemId} 和 /order/delivery/deliveryId/{deliveryId } 和 /order/delivery/packetId/{packetId} 并处理您需要在客户端调用的内容。
为了尽量减少方法中的参数数量,您可以将查询参数定义为 class:
的字段
@Data
public class SearchOrderCriteria {
private String itemId;
private String orderId;
private String deliveryId;
private String packetId;
}
然后在您的控制器方法中接收此类 class 的实例:
@GetMapping(path = "/order/items", produces = "application/json")
public ResponseEntity<OrderInfo> getOrder(SearchOrderCriteria searchCriteria) {
OrderInfo order = orderService.findOrder(searchCriteria)
return ResponseEntity.ok(order);
}
并且,在您的服务中,为了避免一堆 if
-else
,您可以使用 query by example:
public OrderInfo findOrder(SearchOrderCriteria searchCriteria) {
OrderInfo order = new OrderInfo();
order.setItemId(searchCriteria.getItemId());
order.setOrderId(searchCriteria.getOrderId());
order.setDeliveryId(searchCriteria.getDeliveryId());
order.setPacketId(searchCriteria.getPacketId());
Example<OrderInfo> example = Example.of(order);
return orderRepository.findOne(example);
}
我想构建一个简单的端点,returns 一个 Order
对象,我可以在其中通过单个查询参数或多个查询参数的组合来搜索此订单。所有这些查询参数都是可选的,原因是不同的人会根据不同的 ID 访问这些订单。
例如:
/order/items?itemId={itemId}&orderId={orderId}&deliveryId={deliveryId}&packetId={packetId}
@GetMapping(path = "/order/items", produces = "application/json")
public Order getOrders(@RequestParam Optional<String> itemId,
@RequestParam Optional<String> orderId,
@RequestParam Optional<String> deliveryId,
@RequestParam Optional<String> packetId) { }
我当然也可以跳过 Java 可选并使用 @RequestParam(required = false)
,但这里的问题是如何摆脱 if-else
或 .isPresent()
的噩梦检查查询参数是否为空?或者是否有一种优雅的方式(取决于参数的组合)进一步传递到我的服务和 Spring Data JPA 存储库。
我的小建议是避免使用过于笼统的 API,例如您可以将映射拆分为多个端点,例如:/order/delivery/itemId/{itemId} 和 /order/delivery/deliveryId/{deliveryId } 和 /order/delivery/packetId/{packetId} 并处理您需要在客户端调用的内容。
为了尽量减少方法中的参数数量,您可以将查询参数定义为 class:
的字段@Data
public class SearchOrderCriteria {
private String itemId;
private String orderId;
private String deliveryId;
private String packetId;
}
然后在您的控制器方法中接收此类 class 的实例:
@GetMapping(path = "/order/items", produces = "application/json")
public ResponseEntity<OrderInfo> getOrder(SearchOrderCriteria searchCriteria) {
OrderInfo order = orderService.findOrder(searchCriteria)
return ResponseEntity.ok(order);
}
并且,在您的服务中,为了避免一堆 if
-else
,您可以使用 query by example:
public OrderInfo findOrder(SearchOrderCriteria searchCriteria) {
OrderInfo order = new OrderInfo();
order.setItemId(searchCriteria.getItemId());
order.setOrderId(searchCriteria.getOrderId());
order.setDeliveryId(searchCriteria.getDeliveryId());
order.setPacketId(searchCriteria.getPacketId());
Example<OrderInfo> example = Example.of(order);
return orderRepository.findOne(example);
}