静止控制器参数上的弹簧验证不起作用

时间:2016-10-05 09:21:12

标签: spring validation annotations

我有这样的控制器处理程序:

@RequestMapping(method = POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Add to basket")
@ApiResponses(value = {@ApiResponse(code = 200, message = "Successfully add to basket")})
@PreAuthorize("@securityService.hasUserAccess()")
public ResponseEntity addToBasket(@RequestBody @ItemAlreadyExistInBasket ProductEntity product) {
    basketService.addToBasket(product);
    return new ResponseEntity(HttpStatus.OK);
}

思考是注释

  

@ItemAlreadyExistInBasket

永远不会被触发,我不知道为什么。这是我使用约束验证的注释

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ItemAlreadyExistInBasketConstraint.class)
public @interface ItemAlreadyExistInBasket {
    String message() default "Item already exist in basket";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

public class ItemAlreadyExistInBasketConstraint implements ConstraintValidator<ItemAlreadyExistInBasket, ProductEntity> {

    @Autowired
    private BasketRepository basketRepository;

    @Autowired
    private UserRepository userRepository;

    @Override
    public void initialize(ItemAlreadyExistInBasket constraintAnnotation) {

    }

    @Override
    public boolean isValid(ProductEntity productEntity, ConstraintValidatorContext context) {
        userRepository.findByLogin(UserUtil.getAuthenticatedUserName());
        return basketRepository.findByUserAndStatusAndProduct(userRepository.findByLogin(UserUtil.getAuthenticatedUserName()), Status.ACTIVE, productEntity).isEmpty();
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

我最近也不得不处理这些方法验证,不知道你是否已经找到了这个问题的答案,但我仍然会回答这个问题。以下适用于Spring 4.1.2(也可能是早期版本)

1。创建以下bean(例如在@Configuration类中):

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
    return new MethodValidationPostProcessor();
}

2。使用@Validated

注释@RestController
@RestController
@Validated
[...]
public class YourController ...

3。实施验证器。

就像您在问题中发布的那样,您可以使用JSR303规范实现验证器。

4。处理验证错误

不知何故,当使用@Value和方法验证时,Spring会以不同的方式处理验证错误。因此,如果您希望您的方法返回400错误而不是抛出服务器异常,您还需要实现类似于此方法的内容:

/**
 * Handle Constraint exceptions in order to return a bad request http status
 */
@ExceptionHandler(value = { ConstraintViolationException.class })
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleResourceNotFoundException(ConstraintViolationException e) {
    Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
    StringBuilder strBuilder = new StringBuilder();
    for (ConstraintViolation<?> violation : violations ) {
        strBuilder.append(violation.getMessage() + "\n");
    }
    return strBuilder.toString();
}

奇怪的是,我不得不将此方法放在我的RestController中。我在@Configuration类中测试了它的实现,但它没有用。

重要!

使用@Valid和@Validated

可以进行两种类型的验证

如果您同时需要POJO验证和方法参数验证,请在类级别使用@Validated注释,在方法上使用POJO之前使用@Valid。使用@Valid注释时,将在此POJO中声明的所有内容(例如字段上的@NotNull)也将得到验证。这是我必须实现的用例。

希望这有帮助!