java—为什么我在使用Spring5的Tomcat9中得到的是Code400响应而不是ErrorJSON对象?

bbmckpt7  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(308)

控制器:

@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对象发回,但它甚至没有输入这两种处理方法中的任何一种。

xoshrz7s

xoshrz7s1#

这是因为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));
    }
}

编辑:我看到你们两个都在用 assignableTypes 以及 annotations 为了 @ControllerAdvice 异常处理程序。这使得spring注册一个异常处理程序 @RestController s。尝试使用其中一个 assignableTypes 或者 annotations .
作为一个选项,您可以为不同的异常处理程序创建自定义注解。
当提供给的数据无效时,以下代码打印“一” /one 数据发送到“/two”时为“2”。

@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, HttpHeaders headers, HttpStatus status, WebRequest request) {
        return ResponseEntity.badRequest().body("one");
    }
}

@ControllerAdvice(annotations = Two.class)
class HandlerTwo extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        return ResponseEntity.badRequest().body("two");
    }
}

相关问题