[英]How to I make sure that throwing a HttpClientErrorException causes an HTTP 400 response?
[英]How can I make sure exceptions during parsing lead to the same kind of response as the (custom) response returned for validation failures?
我正在使用Spring創建一個API,但是在請求正文驗證(的一部分)中引入自定義錯誤報告時遇到了一些麻煩。
發生解析/驗證錯誤時,我想將自定義響應返回給用戶。
這對於使用@Valid
注釋的字段以及@javax.validation.constraints.NotNull
的驗證器(通過使用@ControllerAdvice
注釋的自定義ResponseEntityExceptionHandler
。
但是,如果在解析請求正文時拋出異常(甚至在驗證運行之前),它將不起作用。 在這種情況下,我得到一個狀態為500 (Server Error)
的html錯誤頁面
如何確保解析期間的異常導致與針對驗證失敗返回的(自定義)響應相同的響應?
我的端點的代碼如下所示:
@RequestMapping(value= "/endpoint"
produces = { "application/json" },
consumes = { "application/json" },
method = RequestMethod.POST)
default ResponseEntity<Object> postSomething(@Valid @RequestBody MyRequestBody requestData){
// ...
}
MyRequestBody類如下所示:
@Validated
public class MyRequestData {
@JsonProperty("stringValue")
private String stringValue = null;
@NotNull
@Valid
public String getStringValue() {
return stringValue;
}
// ...
public enum EnumValueEnum {
VALUE_1("value 1"),
VALUE_1("value 2");
private String value;
EnumValueEnum(String value) {
this.value = value;
}
@Override
@JsonValue
public String toString() {
return String.valueOf(value);
}
@JsonCreator
public static EnumValueEnum fromValue(String text) {
if(text == null){
return null;
}
for (EnumValueEnum b : EnumValueEnum.values()){
if (String.valueOf(b.value).equals(text)) {
return b;
}
}
throw new HttpMessageNotReadableException("EnumValueEnum \"" + text + "\" does not exist");
}
}
@JsonProperty("enumValue")
private EnumValueEnum enumValue = null;
}
自定義驗證錯誤處理(和報告)如下所示:
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class MyValidationHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// return status(BAD_REQUEST).body(new ValidationResponse(ex.getBindingResult().getFieldErrors()));
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// return status(BAD_REQUEST).body(new ValidationResponse((JsonMappingException) ex.getCause()));
}
}
在此代碼中,如果用戶使用不存在的枚舉值發送請求,則將拋出HttpMessageNotReadableException。 我想將其捕獲到某個地方,並用與我執行的其他異常處理一致的自定義響應替換它。 我在哪里/該怎么做?
我找到了解決自己問題的方法。
用@ExceptionHandler
注釋方法將使Spring嘗試將其用於指定異常類型的異常處理(在注釋的value字段或方法的參數中)。 該方法可以放在控制器中,甚至可以放在我用於其他驗證響應處理的ResponseEntityExceptionHandler
。
@ExceptionHandler
public ResponseEntity handle(HttpMessageConversionException e){
// return status(BAD_REQUEST).body(new ValidationResponse((JsonMappingException) e.getCause()));
}
這里的問題是,解析時拋出的異常被包裝在JsonMappingException
該包裝的某些子類型),而JsonMappingException
又被包裝在HttpMessageConversionException
。
e instanceof HttpMessageConversionException
e.getCause() instanceof JsonMappingException
e.getCause().getCause() // == your original exception
因此, @ExceptionHandler
應該接受HttpMessageConversionException
而不是最初引發的異常(在我的情況下是HttpMessageNotReadableException
)
如果您編寫僅接受原始Exception的@ExceptionHandler
,它將不起作用!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.