Java spring 中的对象验证没有注释
Java objects validation in spring without annotations
我正在使用 mybatis 来执行所有数据库操作。我也在使用 Angular 前端,因此客户端中的验证是使用 angular-validation-ghiscoding
和本机 HTML5 验证进行的。我想验证银行端的数据,但我不想使用注释。
代码示例如下:
@RequestMapping(value = SecureApiResources.URI_UPDATE_ACCOUNT, method = RequestMethod.POST, produces = "application/json")
public @ResponseBody Account updateAccount(
@RequestBody final AccountRequestUpdate accountRequest) { // Object to be validated (accountRequest)
Account account = accountMapper.getAccountOfMerchant(authContextHolder.getMerchantId(), authContextHolder.getDefaultAccountId());
if (account == null) {
HttpErrors httpErrors = new HttpErrors(
SecureApiResources.ERROR_ACCOUNTS_NOT_FOUND);
throw new EntityNotFoundException(httpErrors);
}
int resultUpdate;
try {
// In this point I should validate the accountRequest object
account.setAccountName(accountRequest.getAccountName());
account.setCommercialName(accountRequest.getCommerciaName());
account.setCountry(accountRequest.getCountry());
account.setCity(accountRequest.getCity());
resultUpdate = accountMapper.updateMerchant(account);
if (resultUpdate == 0) {
HttpErrors httpErrors = new HttpErrors(
SecureApiResources.ERROR_ACCOUNTS_NOT_FOUND);
throw new EntityNotFoundException(httpErrors);
}
} catch (Exception e) {
HttpErrors httpErrors = new HttpErrors(
SecureApiResources.ERROR_SQL_NOT_EXECUTE);
throw new EntityNotFoundException(httpErrors);
}
return account;
}
在同一个 class 中,我有一个创建帐户的方法,我收到另一个模型对象 (AccountRequestCreate accountRequest
)。
在没有注释的情况下,哪个可能是最推荐的实施选项?xml
最推荐的方法是使用 @Valid
或 @Validated
注释,但由于您对此并不完全满意,您可以 Autowire
将 javax.validation.Validator
添加到您的控制器中并手动执行验证:
@Controller
public class SomeController {
@Autowired private Validator validator;
@RequestMapping(...)
public ResponseEntity<?> someHandler(@RequestBody SomeBody body) {
Set<ConstraintViolation<SomeBody>> violations = validator.validate(body);
if (!violations.isEmpty()) {
List<String> messages = violations
.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(messages);
}
// the rest of controller
}
}
使用这种方法,您将在所有其他控制器中重复验证逻辑,这不是一个好主意。你也违反了 DRY
原则。
正如我所说,最好用 @Valid
或 @Validated
:
注释你的 bean
@RequestMapping(...)
public ResponseEntity<?> someHandler(@RequestBody @Valid SomeBody body) { ... }
如果传递的 bean 违反至少一个验证规则,将抛出 MethodArgumentNotValidException
。为了处理该异常,您可以编写一个 ControllerAdvice
来捕获异常和 return 一个合适的 HTTP 响应,例如 400 Bad Request
:
@ControllerAdvice
public class ValidationAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationError(MethodArgumentNotValidException ex) {
List<String> validationErrors = ex.getBindingResult()
.getAllErrors()
.stream()
.map(ObjectError::getDefaultMessage)
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(validatioErrors);
}
}
我正在使用 mybatis 来执行所有数据库操作。我也在使用 Angular 前端,因此客户端中的验证是使用 angular-validation-ghiscoding
和本机 HTML5 验证进行的。我想验证银行端的数据,但我不想使用注释。
代码示例如下:
@RequestMapping(value = SecureApiResources.URI_UPDATE_ACCOUNT, method = RequestMethod.POST, produces = "application/json")
public @ResponseBody Account updateAccount(
@RequestBody final AccountRequestUpdate accountRequest) { // Object to be validated (accountRequest)
Account account = accountMapper.getAccountOfMerchant(authContextHolder.getMerchantId(), authContextHolder.getDefaultAccountId());
if (account == null) {
HttpErrors httpErrors = new HttpErrors(
SecureApiResources.ERROR_ACCOUNTS_NOT_FOUND);
throw new EntityNotFoundException(httpErrors);
}
int resultUpdate;
try {
// In this point I should validate the accountRequest object
account.setAccountName(accountRequest.getAccountName());
account.setCommercialName(accountRequest.getCommerciaName());
account.setCountry(accountRequest.getCountry());
account.setCity(accountRequest.getCity());
resultUpdate = accountMapper.updateMerchant(account);
if (resultUpdate == 0) {
HttpErrors httpErrors = new HttpErrors(
SecureApiResources.ERROR_ACCOUNTS_NOT_FOUND);
throw new EntityNotFoundException(httpErrors);
}
} catch (Exception e) {
HttpErrors httpErrors = new HttpErrors(
SecureApiResources.ERROR_SQL_NOT_EXECUTE);
throw new EntityNotFoundException(httpErrors);
}
return account;
}
在同一个 class 中,我有一个创建帐户的方法,我收到另一个模型对象 (AccountRequestCreate accountRequest
)。
在没有注释的情况下,哪个可能是最推荐的实施选项?xml
最推荐的方法是使用 @Valid
或 @Validated
注释,但由于您对此并不完全满意,您可以 Autowire
将 javax.validation.Validator
添加到您的控制器中并手动执行验证:
@Controller
public class SomeController {
@Autowired private Validator validator;
@RequestMapping(...)
public ResponseEntity<?> someHandler(@RequestBody SomeBody body) {
Set<ConstraintViolation<SomeBody>> violations = validator.validate(body);
if (!violations.isEmpty()) {
List<String> messages = violations
.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(messages);
}
// the rest of controller
}
}
使用这种方法,您将在所有其他控制器中重复验证逻辑,这不是一个好主意。你也违反了 DRY
原则。
正如我所说,最好用 @Valid
或 @Validated
:
@RequestMapping(...)
public ResponseEntity<?> someHandler(@RequestBody @Valid SomeBody body) { ... }
如果传递的 bean 违反至少一个验证规则,将抛出 MethodArgumentNotValidException
。为了处理该异常,您可以编写一个 ControllerAdvice
来捕获异常和 return 一个合适的 HTTP 响应,例如 400 Bad Request
:
@ControllerAdvice
public class ValidationAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationError(MethodArgumentNotValidException ex) {
List<String> validationErrors = ex.getBindingResult()
.getAllErrors()
.stream()
.map(ObjectError::getDefaultMessage)
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(validatioErrors);
}
}