我有一个ConstraintViolationException
处理程序类,如下所示:
@Produces
@Singleton
@Requires(classes = {ConstraintViolationException.class, ExceptionHandler.class})
public class ConstraintsViolationsExceptionHandler
implements ExceptionHandler<ConstraintViolationException, HttpResponse> {
@Override
public HttpResponse
handle(HttpRequest request, ConstraintViolationException exception) {
return HttpResponse
.status(HttpStatus.FORBIDDEN)
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8")
.body(new SignUpPhoneNumberErrorResponse<>(400,
"Wrong data used",
new ArrayList<>(exception.getConstraintViolations())));
}
}
其中SignUpPhoneNumberErrorResponse
是我处理POJO的错误,它正好可以序列化为JSON。
我的控制器如下:
@Controller(PhoneAuthAndLoginConstants.CONTROLLER_BASE_PATH)
@Validated
public class UserPhoneNumberRegistrationAndLoginController {
@Inject
MongoDbUserSignUpPhoneNumberDAO mongoDbUserSignUpPhoneNumberDAO;
@Post(uri = PhoneAuthAndLoginConstants.CONTROLLER_SIGN_UP_PATH,
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON)
public Single<ResponseDataEncapsulate>
signUpForPhoneVerification(@Valid @Body UserSignUpPhoneNumberEntity phoneNumber) {
return mongoDbUserSignUpPhoneNumberDAO.sendVerification(phoneNumber);
}
@Post(uri = PhoneAuthAndLoginConstants.CONTROLLER_SIGN_UP_PATH
+
PhoneAuthAndLoginConstants.CONTROLLER_SIGN_UP_VERIFICATION_CODE_PARAM,
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON)
public Single<ResponseDataEncapsulate>
sendUserSignUpConfirmation(@Valid @Body UserAccountStateSignUpEntity verificationData,
HttpHeaders httpHeaders) {
return mongoDbUserSignUpPhoneNumberDAO.signUp(verificationData);
}
}
我对UserAccountStateSignUpEntity
的POJO如下所示:
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserAccountStateSignUpEntity implements UserSignUpEntity {
@NotNull @NotBlank @Size(min = 5, max = 13) private String phoneNumber;
@NotNull @NotBlank @Size(min = 7, max = 7) private String verificationCode;
@JsonIgnore private Boolean verifiedAccount = Boolean.FALSE;
public UserAccountStateSignUpEntity(String phoneNumber, String verificationCode) {
this.phoneNumber = phoneNumber;
this.verificationCode = verificationCode;
this.verifiedAccount = Boolean.TRUE;
}
@Override
public Map<String, Object> makePhoneEntityMapForMongo() {
HashMap<String, Object> returnMap = new HashMap<String, Object>() {{
put("phoneNumber", phoneNumber);
put("verificationCode", verificationCode);
put("verifiedAccount", verifiedAccount);
}};
return Collections.unmodifiableMap(returnMap);
}
}
我发送这样的请求有效负载:
{
"phoneNumber" : "91-123456789",
"verificationCode" : "18887"
}
这应该触发ConstraintViolationException
,并且我的处理程序代码应该执行,并且我应该获得HTTP禁止。但是相反,我得到了默认的HTTP Bad Request错误消息。
为什么我的处理程序没有被执行? 如何使其执行?
我正在使用 Micronaut 1.1.3 作为网络框架,并使用 Hibernate Validator 作为javax.validation
实现。
答案 0 :(得分:1)
我删除了@Requires(classes = {ConstraintViolationException.class, ExceptionHandler.class})
注释,并用逗号分隔的字符串替换了正文中的ArrayList<>
,它开始正常工作。虽然我不知道删除注释的后果。
答案 1 :(得分:1)
我最近在Micronaut中处理错误时遇到了同样的问题。如我所知,没有抛出org.hibernate.exception.ConstraintViolationException
,而是抛出了javax.persistence.PersistenceException
。
对我来说,它与@Error(exception = PersistenceException::class)
(科特琳)一起使用。
答案 2 :(得分:1)
@Error
的 ConstraintViolationException
注释处理仅在控制器上时才对我有用。
最终设法通过替换 micronaut ConstraintExceptionHandler
bean 来处理它:
@Produces
@Replaces(io.micronaut.validation.exceptions.ConstraintExceptionHandler.class)
@Requires(classes = {ConstraintViolationException.class, ExceptionHandler.class})
public class ConstraintExceptionHandler extends io.micronaut.validation.exceptions.ConstraintExceptionHandler {
@Override
public HttpResponse handle(HttpRequest request, ConstraintViolationException exception) {
return return HttpResponse
.badRequest();
}
}
答案 3 :(得分:0)
@Error,当发生任何ConstraintViolationException时,SignUpPhoneNumberErrorResponse将作为错误响应主体返回。
有关更多详细信息,请访问Micronaut docs
@Controller("/${path}")
@Validated
public class UserPhoneNumberRegistrationAndLoginController {
@Post
public HttpResponse method(@Valid @Body UserAccountStateSignUpEntity verificationData, HttpHeaders httpHeaders) {
return null;
}
@Error(exception = ConstraintViolationException.class)
public SignUpPhoneNumberErrorResponse onSavedFailed(HttpRequest request, ConstraintViolationException ex) {
return new SignUpPhoneNumberErrorResponse(500,
"Wrong data used",
String.valueOf(ex.getConstraintViolations().stream().map( e -> e.getPropertyPath()+": "+e.getMessage()).collect(Collectors.toList())),
"Application",
"Error",
System.currentTimeMillis());
}
@Error(status = HttpStatus.NOT_FOUND, global = true)
public HttpResponse notFound(HttpRequest request) {
//return custom 404 error body
}
}
答案 4 :(得分:0)
我认为这里的错误是 Micronaut 已经为 ConstraintViolationException
定义了一个异常处理程序,如here
为了覆盖这个,我建议只从我链接的页面复制和粘贴定义。
@Produces
@Singleton
@Primary
@Requires(classes={javax.validation.ConstraintViolationException.class,ExceptionHandler.class})
public class ConstraintExceptionHandler
extends java.lang.Object
implements ExceptionHandler<javax.validation.ConstraintViolationException,HttpResponse<JsonError>>
(您可以填写正文。extends java.lang.Object
不是必需的)
这里的重要部分是我添加了 io.micronaut.context.annotation.Primary
注释。这将有利于您的处理程序而不是另一个定义的处理程序。我从 ConversionErrorHandler 那里偷了这个技巧,因为我遇到了和你一样的问题,但使用了那个处理程序。
现在您当然可以将 HttpResponse<JsonError>
更改为适合您需要的 HttpResponse<*>
。