Spring启动REST验证错误响应

时间:2017-01-05 09:57:30

标签: java spring validation spring-boot hibernate-validator

控制器方法:

public Mission createMission(final @Valid @RequestBody Mission mission) {

    //save..

    return mission;
}

我想将所有验证错误消息枚举为json并返回。

我可以创建一个新的异常类,在控制器方法参数中添加BindingResult,在绑定结果出错时抛出新异常并在@ControllerAdvice类中处理异常。

if (bindingResult.hasErrors()) {
        throw new InvalidRequestException("Fix input and try again", bindingResult);
    }

但我想避免在每个控制器方法中检查BindingResult,而是全局处理。如果我能处理异常,我本可以这样做:org.springframework.web.bind.MethodArgumentNotValidException。但不幸的是,Spring启动不允许

@ExceptionHandler(MethodArgumentNotValidException.class)

它显示了不明确的异常处理程序,因为同样的异常是处理ResponseEntityExceptionHandler,我不能覆盖handleException,因为它是final。我尝试通过捕获Exception.class来覆盖受保护的ResponseEntity handleMethodArgumentNotValid(),但是根本不会调用它。

有没有办法实现这个目标?对于一项简单的任务来说,似乎有很多东西:(

3 个答案:

答案 0 :(得分:3)

您应该创建一个使用@ControllerAdvice并扩展ResponseEntityExceptionHandler的类。然后,您可以覆盖方法handleMethodArgumentNotValid。你可以使用类似的东西:

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

@Override
@ResponseStatus(HttpStatus.BAD_REQUEST)
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    final List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
    Map <String, Set<String>> errorsMap =  fieldErrors.stream().collect(
            Collectors.groupingBy(FieldError::getField,
                    Collectors.mapping(FieldError::getDefaultMessage, Collectors.toSet())
            )
    );
    return new ResponseEntity(errorsMap.isEmpty()? ex:errorsMap, headers, status);
    }
}

答案 1 :(得分:0)

我发现了这个问题,控制器的建议被放在了常见的util模块中,虽然它是在组件扫描的相同基础包之下,但它似乎并没有被Spring使用。我所做的是覆盖全局抽象类(在通用模块中)的ResponseEntityExceptionHandler中的方法,然后在其他模块中扩展该类。

答案 2 :(得分:0)

如果您不想延伸至ResponseEntityExceptionHandler,则需要对GlobalExceptionHandler @ControllerAdvice@ResponseBody进行注释。