bos*_*ava 14 java jpa-2.0 spring-boot
我已经在我的Entity类中定义了用于验证电子邮件的模式.在我的验证异常处理程序类中,我为ConstraintViolationException添加了处理程序.我的应用程序使用SpringBoot 1.4.5.
Profile.java
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "profile")
public class Profile extends AuditableEntity {
private static final long serialVersionUID = 8744243251433626827L;
@Column(name = "email", nullable = true, length = 250)
@NotNull
@Pattern(regexp = "^([^ @])+@([^ \\.@]+\\.)+([^ \\.@])+$")
@Size(max = 250)
private String email;
....
}
Run Code Online (Sandbox Code Playgroud)
ValidationExceptionHandler.java
@ControllerAdvice
public class ValidationExceptionHandler extends ResponseEntityExceptionHandler {
private MessageSource messageSource;
@Autowired
public ValidationExceptionHandler(MessageSource messageSource) {
this.messageSource = messageSource;
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex,
WebRequest request) {
List<String> errors = new ArrayList<String>();
....
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行我的代码并传递无效的电子邮件地址时,我得到以下异常.handleConstraintViolation中的代码永远不会执行.在异常中返回的http状态是500,但我想返回400.任何想法我怎么能实现这一点?
2017-07-12 22:15:07.078 ERROR 55627 --- [nio-9000-exec-2] o.h.c.s.u.c.UserProfileController : Validation failed for classes [org.xxxx.common.service.user.domain.Profile] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must match "^([^ @])+@([^ \.@]+\.)+([^ \.@])+$"', propertyPath=email, rootBeanClass=class org.xxxx.common.service.user.domain.Profile, messageTemplate='{javax.validation.constraints.Pattern.message}'}]
javax.validation.ConstraintViolationException: Validation failed for classes [org.xxxx.common.service.user.domain.Profile] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must match "^([^ @])+@([^ \.@]+\.)+([^ \.@])+$"', propertyPath=email, rootBeanClass=class org.xxxx.common.service.user.domain.Profile, messageTemplate='{javax.validation.constraints.Pattern.message}'}]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:78)
Run Code Online (Sandbox Code Playgroud)
nim*_*mai 18
你无法捕捉,ConstraintViolationException.class因为它没有传播到你的代码层,它被较低层捕获,包裹并在另一种类型下重新抛出.因此,触及您的Web图层的异常不是ConstraintViolationException.
就我而言,它是一个TransactionSystemException.我正在使用@TransactionalSpring中的注释JpaTransactionManager.EntityManager中抛出一个异常回滚出头时出现错误的交易,将其转化为一个TransactionSystemException由JpaTransactionManager.
所以你可以这样做:
@ExceptionHandler({ TransactionSystemException.class })
public ResponseEntity<RestResponseErrorMessage> handleConstraintViolation(Exception ex, WebRequest request) {
Throwable cause = ((TransactionSystemException) ex).getRootCause();
if (cause instanceof ConstraintViolationException) {
Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) cause).getConstraintViolations();
// do something here
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
以下解决方案基于 Spring Boot 2.1.2。
为了澄清事情......正如nimai已经正确提到的那样:
您无法捕获 ConstraintViolationException.class,因为它不会传播到代码的该层,而是被较低层捕获,包装并在另一种类型下重新抛出。因此,访问 Web 层的异常不是 ConstraintViolationException。
在您的情况下,它可能是 a DataIntegrityViolationException,它指出了持久层中的问题。但你不想让它发展到那么远。
正如Ena提到的,使用@Valid作为方法参数给出的实体的注释。在我的版本中,它缺少注释(如果没有注释,则无法正确解析到您的实体中,并且属性会产生值,例如。):org.springframework.web.bind.annotation.RequestBody@RequestBodyProfileDtoProfileDtonullNullPointerException
@RequestMapping(value = "/profile", method = RequestMethod.POST)
public ProfileDto createProfile(@Valid @RequestBody ProfileDto profile){
...
}
Run Code Online (Sandbox Code Playgroud)
org.springframework.web.bind.MethodArgumentNotValidException然后,这将返回您想要的状态代码 400 和一些默认响应正文,甚至在到达持久层之前还附有。的处理MethodArgumentNotValidException在 中定义org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler。
这是另一个主题,但您可以选择通过创建@ControllerAdvicewith@ExceptionHandler(MethodArgumentNotValidException.class)并根据您的需要自定义响应正文来覆盖该行为,因为默认错误响应正文不是最佳的,甚至在排除 ErrorMvcAutoConfiguration 时不存在。
注意:找到将结果扩展为 的@ExceptionHandler(MethodArgumentNotValidException.class)内部,因为其中已经有为 定义的异常处理程序。因此,只需将其放入另一个类中即可,无需扩展任何内容。@ControllerAdviceResponseEntityExceptionHandlerIllegalStateExceptionResponseEntityExceptionHandlerMethodArgumentNotValidException@ControllerAdvice
我看到您还可以手动触发电子邮件模式的验证(请参阅手动调用 Spring Annotation Validation)。我自己没有测试过,但我个人不喜欢这种方法,因为它只会使控制器代码变得臃肿,而且我目前无法想到需要它的用例。
我希望能够帮助遇到类似问题的其他人。
只是想补充一点。我试图做同样的事情,验证实体。然后我意识到如果您验证控制器的输入,Spring 已经具备了开箱即用的所有功能。
@RequestMapping(value = "/profile", method = RequestMethod.POST)
public ProfileDto createProfile(@Valid ProfileDto profile){
...
}
Run Code Online (Sandbox Code Playgroud)
该@Valid批注将使用 javax.validation 批注触发验证。
假设您的个人资料用户名上有一个 Pattern 注释,正则表达式不允许空格。
Spring 将构建一个状态为 400(错误请求)的响应和一个像这样的主体:
{
"timestamp": 1544453370570,
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"Pattern.ProfileDto.username",
"Pattern.username",
"Pattern.java.lang.String",
"Pattern"
],
"arguments": [
{
"codes": [
"profileDto.username",
"username"
],
"arguments": null,
"defaultMessage": "username",
"code": "username"
},
[],
{
"defaultMessage": "^[A-Za-z0-9_\\-.]+$",
"arguments": null,
"codes": [
"^[A-Za-z0-9_\\-.]+$"
]
}
],
"defaultMessage": "must match \"^[A-Za-z0-9_\\-.]+$\"",
"objectName": "profileDto",
"field": "username",
"rejectedValue": "Wr Ong",
"bindingFailure": false,
"code": "Pattern"
}
],
"message": "Validation failed for object='profileDto'. Error count: 1",
"path": "/profile"
}
Run Code Online (Sandbox Code Playgroud)
我认为你应该添加@ResponseStatus(HttpStatus.BAD_REQUEST)到你的@ExceptionHandler:
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request) {
List<String> errors = new ArrayList<String>();
....
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11388 次 |
| 最近记录: |