代码之家  ›  专栏  ›  技术社区  ›  sschmeck

验证几个控制器方法的URL路径

  •  1
  • sschmeck  · 技术社区  · 8 年前

    提供多个REST资源来收集订单信息。

    • /order/{id}
    • /order/{id}/positions
    • /order/{id}/invoice
    • /order/{id}/shipment

    在Srping Boot 2应用程序中,它跨多个控制器实现,例如。 OrderController , InvoiceController 等

    目前,每个控制器都使用OrderRepository来确保订单与给定的 id 存在。否则它会抛出一个异常。它总是相同的复制代码。

    @RestController
    public class OrderController {
        // ...
        @GetMapping("order/{id}")
        public Order getCustomer(@PathVariable final Integer id) {
            return this.orderRepository.findById(id)
                    .orElseThrow(() -> new IllegalArgumentException("order not found"));
        }
    }
    

    框架是否提供了写订单的回调 身份证件 只检查一次?


    我找到了 AntPathMatcher 但这似乎不是正确的方法,因为它只提供了一个布尔接口。

    1 回复  |  直到 8 年前
        1
  •  3
  •   Dimitri Mestdagh Lancer.Yan    8 年前

    这通常是一个很好的例子 bean validation .虽然已经有许多验证案例的内置支持( @Size , @NotNull , ...), 还可以编写自己的自定义约束。

    首先,您需要定义一个注释来验证您的ID,例如:

    @Documented
    @Constraint(validatedBy = OrderIdValidator.class)
    @Target({PARAMETER})
    @Retention(RUNTIME)
    public @interface ValidOrderId {
        String message() default "Invalid order ID";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    由于订单ID始终是控制器映射的参数,因此可以使用 ElementType.PARAMETER 仅允许对方法参数进行注释。

    下一步是添加 @Constraint 注释并指向一个定制的验证器类(例如。 OrderIdValidator ):

    @Component
    public class OrderIdValidator implements ConstraintValidator<ValidOrderId, Integer> {
        private OrderRepository repository;
    
        public OrderIdValidator(OrderRepository repository) {
            this.repository = repository;
        }
    
        @Override
        public boolean isValid(Integer id, ConstraintValidatorContext constraintValidatorContext) {
            return repository.existsById(id);
        }
    }
    

    通过实施 isValid 方法,您可以检查订单是否存在。如果它不存在,将抛出一个异常,然后 message() 财产 @ValidOrderId 注释将用作消息。

    最后一步是添加 @Validated 注释到所有控制器,并添加 @瓦利多德里德 所有订单ID参数的注释,例如:

    @Validated // Add this
    @RestController
    public class OrderController {
        @GetMapping("order/{id}")
        public Order getCustomer(@PathVariable @ValidOrderId final Integer id) { // Add @ValidOrderId
            // Do stuff
        }
    }
    

    如果您更喜欢在验证中使用不同的响应状态,那么可以添加一个带有 @ControllerAdvice 注释并使用以下方法:

    @ExceptionHandler(ConstraintViolationException.class)
    public void handleConstraints(HttpServletResponse response) throws IOException {
        response.sendError(HttpStatus.BAD_REQUEST.value());
    }