如何解决为什么我在带有 spring 5 的 tomcat 9 中收到代码 400 响应而不是错误 json 对象?
控制器:
@RestController
@RequestMapping(value = "/test",produces = MediaType.APPLICATION_JSON_VALUE)
@Validated
public class ApiController {
@PostMapping(value = "/in",consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<InitResponse> inPost(
@ApiParam(required = true) @Valid @RequestBody InRequest inRequest) {
LOG.info("inPost request was received = {}",inRequest);
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
异常处理程序:
@ControllerAdvice(assignableTypes = ApiController .class,annotations = RestController.class)
public class InExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<INErrors> handleConstraintViolation(ConstraintViolationException ex) {
LOG.info("handleConstraintViolation was trigerred");
INError INError = new INError(HttpStatus.BAD_REQUEST.toString(),ex.getLocalizedMessage());
return new ResponseEntity<>(new INErrors(),HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<INErrors> handleMethodArgumentConstraintViolation(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
List<FieldError> fieldErrors = result.getFieldErrors();
return new ResponseEntity<>(processFieldErrors(fieldErrors),HttpStatus.BAD_REQUEST);
}
}
如果 InRequest 的所有字段都在 javax 验证约束内,那么我会得到正确的代码,但是当某个字段与验证不匹配时,我只会得到 400 响应代码。 还定义了其他异常处理程序,但我在各处都放置了断点,但没有触发任何内容。
我还添加了 log4j 属性:
log4j.logger.org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod=DEBUG,stdout
但这在调试时没有产生任何额外的输出。 我还希望将 INErrors 对象发回,但它甚至没有进入这两种处理方法中的任何一种。
解决方法
发生这种情况是因为 Spring 的默认异常处理程序自己处理所有 WebMvc 的标准异常,然后将未处理的异常委托给用户定义的 @ExceptionHandler
方法。
在您的情况下,@Valid
约束违规会引发 Spring 的 MethodArgumentNotValidException
,它由 ResponseEntityExceptionHandler#handleMethodArgumentNotValid
处理。因此,要更改此异常的默认行为,您需要在 @ControllerAdivce
中覆盖此方法。
@ControllerAdvice(assignableTypes = ApiController .class,annotations = RestController.class)
public class InExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,HttpHeaders headers,HttpStatus status,WebRequest request) {
BindingResult result = ex.getBindingResult();
List<FieldError> fieldErrors = result.getFieldErrors();
return ResponseEntity.badRequest().body(processFieldErrors(fieldErrors));
}
}
EDIT:我看到您同时使用 assignableTypes
和 annotations
作为 @ControllerAdvice
异常处理程序。这使得 Spring 为所有 @RestController
注册一个异常处理程序。尝试使用 assignableTypes
或 annotations
。
作为一种选择,您可以为不同的异常处理程序创建自定义注释。
以下代码在将无效数据提供给 /one
时打印“一”,将数据发送到“/two”时打印“二”。
@RestController
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface One {}
@RestController
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Two {}
@One
class ControllerOne {
@PostMapping("one")
String a(@RequestBody @Valid Data data) {
return data.value;
}
}
@Two
class ControllerTwo {
@PostMapping("two")
String a(@RequestBody @Valid Data data) {
return data.value;
}
}
@ControllerAdvice(annotations = One.class)
class HandlerOne extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,WebRequest request) {
return ResponseEntity.badRequest().body("one");
}
}
@ControllerAdvice(annotations = Two.class)
class HandlerTwo extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,WebRequest request) {
return ResponseEntity.badRequest().body("two");
}
}
,
仅当我在控制器中添加方法时,模型的 javax 注释样式验证才对我有用:
public class ApiController {
...
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<INErrors> handleConstraintViolation(MethodArgumentNotValidException exception) {
BindingResult result = exception.getBindingResult();
List<FieldError> fieldErrors = result.getFieldErrors();
return new ResponseEntity<>(processFieldErrors(fieldErrors),HttpStatus.BAD_REQUEST);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。