Spring Boot中的自定义通用请求验证器

时间:2019-08-25 18:26:41

标签: java spring spring-boot

我是Spring Boot的新手,我对请求字段验证有疑问。 我想出了如何在字段级别使用注释来指定自定义错误消息:

public class EmployeeRequest {

    @NotEmpty( message = "field name cannot be empty" )
    @NonNull
    private String name;

    @NotEmpty( message = "field address cannot be empty" )
    @NonNull
    private String address;
}

但是对于使用这些注释,我必须为每个请求类中的每个字段指定错误消息。 同样由于某种原因,我得到的响应不是很好:

"org.springframework.validation.BeanPropertyBindingResult: 1 errors\nField error in object 'employeeRequest' on field 'name': rejected value [null]; codes [NotEmpty.employeeRequest.name,NotEmpty.name,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [employeeRequest.name,name]; arguments []; default message [name]]; default message [provide a name]"

假设所有字段都必须为NotEmptyNonNull,是否有更优雅,更通用的方式针对每个请求进行此类字段验证?

public class EmployeeController {

    @PostMapping("/test")
    @ResponseBody
    public EmployeeResponse testMethod(@RequestBody EmployeeRequest request) {
        genericFieldsValidatorForAllRequests(request);
        doSomeStuffIfRequestIsValid(request);
}

有人可以提供一些想法如何实现请求验证器吗?

1 个答案:

答案 0 :(得分:0)

好像您问了两个问题,希望我能回答两个问题。

为什么JSON响应看起来“不太整洁”?

默认情况下,Spring Boot会捕获Web请求处理程序中引发的任何未捕获异常(例如@RequestMapping@GetMapping等),并将其转换为以下这种结构的JSON响应: / p>

{
 "timestamp": 1500597044204,
 "status": 400,
 "error": "Bad Request",
 "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
 "message": "JSON parse error: Unrecognized token .....",
 "path": "/birds"
}

获得错误响应JSON的另一种方式是制作异常处理程序。基本上,您可以在使用Spring Boot的默认错误处理程序之前捕获所需的错误。为此,您可以将其中之一放在与控制器相同的包装中,或者在比控制器更高的杠杆包装中:

@ControllerAdvice
public class GlobalErrorHandler {

    @ExceptionHandler(ExceptionICareAbout.class)
    public MyErrorResponseObject handleExceptionICareAbout(ExceptionICareAbout e) {
        return new MyErrorResponseObject(<ADD CODE HERE>)
    }

}

在您的情况下,您可以为MethodArgumentNotValidException创建一个异常处理程序,并将其转换为您喜欢的错误响应。 (我相信这是JSR303批注验证失败时抛出的异常,但是请仔细检查我)

您还可以将错误响应对象包装在Spring提供的ResponseEntity<>对象中,以自定义响应中的其他内容,或仅用@ResponseStatus注释异常处理程序方法以仅自定义http状态代码返回。

此外,如果您想捕获每个异常并阻止它们进入Spring Boot的默认异常处理程序,只需为Exception类本身(例如@ExceptionHandler(Exception.class))创建一个异常处理程序。

是否有更“优雅而通用”的方式来进行现场验证?

将您关心的每个对象的每个字段都使用JSR303注释(@NotNull@Size等...),并结合@Valid注释是我所知道的最好方法。我会花时间考虑重用代码和错误消息的方法,但这就是我想到的所有事情。也许我们可以在评论中得到一些好的答案。

Spring确实提供了您可以代替JSR303注释的Validators,但是我对它们没有太多的经验。