Spring Boot中的数据校验 Validation

本文介绍如何使用SpringBoot内置的Validation进行数据校验,包括基本用法、自定义错误信息及异常处理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring Boot中的数据校验

我们可能会经常需要对传入的参数进行校验,如果数据比较少的时候还比较容易处理,但当数据比较多的时候会显得比较麻烦,而且处理不当的时候,还会代码重复。这时候就需要Spring Boot对参数进行校验了。
这时候就需要使用使用Validation对数据进行校验了。

在Spring Boot中使用Validation

有如下的一段代码:

@RestController
public class BookController {
    @PostMapping("/book")
    public Book getBook(Book book) {
        // ...
        return book;
    }
}

可以看到请求传入了一个Book,Book类如下:

public class Book {
    private Integer id;
    private String bookName;
    private String bookAuthor;
    // 省略get和set方法
}

现在需要对book中的属性进行校验,如果使用if else 进行校验会显得很麻烦。这时候可以在Book中的属性上添加Validation注解,如下:

public class Book {
    private Integer id;
    @NotBlank
    private String bookName;
    @NotBlank
    private String bookAuthor;
    // 省略get和set方法
}

其中的NotBlank注解指的是属性值不能为空。
然后还需要在Controller中的方法的需要校验的字段上加上@Valid注解,表明这个参数需要校验,如下:

@RestController
public class BookController {
    @PostMapping("/book")
    public Book getBook(@Valid Book book) {
        // ...
        return book;
    }
}

这时候假如bookName和bookAuthor为空,那么就会出现400的响应码。
这里写图片描述
Spring Boot这时的返回为:

{
    "timestamp": "2018-07-25T01:21:53.644+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "NotBlank.book.bookAuthor",
                "NotBlank.bookAuthor",
                "NotBlank.java.lang.String",
                "NotBlank"
            ],
            "arguments": [
                {
                    "codes": [
                        "book.bookAuthor",
                        "bookAuthor"
                    ],
                    "arguments": null,
                    "defaultMessage": "bookAuthor",
                    "code": "bookAuthor"
                }
            ],
            "defaultMessage": "不能为空",
            "objectName": "book",
            "field": "bookAuthor",
            "rejectedValue": "",
            "bindingFailure": false,
            "code": "NotBlank"
        },
        {
            "codes": [
                "NotBlank.book.bookName",
                "NotBlank.bookName",
                "NotBlank.java.lang.String",
                "NotBlank"
            ],
            "arguments": [
                {
                    "codes": [
                        "book.bookName",
                        "bookName"
                    ],
                    "arguments": null,
                    "defaultMessage": "bookName",
                    "code": "bookName"
                }
            ],
            "defaultMessage": "不能为空",
            "objectName": "book",
            "field": "bookName",
            "rejectedValue": "",
            "bindingFailure": false,
            "code": "NotBlank"
        }
    ],
    "message": "Validation failed for object='book'. Error count: 2",
    "path": "/book"
}

因为使用的是测试工具,所以Spring Boot返回的是Json串。
上面的是Spring Boot的默认返回,我们肯定不希望返回这样的一个东西给前端。所以就需要自定义错误信息和错误处理。

自定义校验信息和错误处理

Validation注解中都有一个message的属性可以通过这个属性自定义错误信息。如下:

public class Book {
    private Integer id;
    @NotBlank(message = "书名不能为空")
    private String bookName;
    @NotBlank(message = "作者不能为空")
    private String bookAuthor;
    // 省略get和set方法
}

Spring Boot的Controller方法中可以传一个BindingResult或者Errors类型的参数,值得注意的一点是这个参数的位置必须是参数列表的被@Valid注解修饰的参数紧跟着的(也就是被@Valid修饰的下一个参数)后面,如果在前面,会出现下面的错误,如果不是下一个,那么这个参数将不起作用

{
    "timestamp": "2018-07-25T01:49:10.742+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the @RequestBody or the @RequestPart arguments to which they apply: public top.mcwebsite.demo.domain.Book top.mcwebsite.demo.web.controller.BookController.getBook(org.springframework.validation.BindingResult,top.mcwebsite.demo.domain.Book,javax.servlet.http.HttpServletResponse)",
    "path": "/book"
}

下面的代码是如何进行自定义错误处理:

@RestController
public class BookController {
    @PostMapping("/book")
    public Book getBook(@Valid Book book, BindingResult result, HttpServletResponse response) {
        if (result.hasErrors()) {
            result.getAllErrors().forEach((error) -> {
                FieldError fieldError = (FieldError) error;
                // 属性
                String field = fieldError.getField();
                // 错误信息
                String message = fieldError.getDefaultMessage();
                System.out.println(field + ":" + message);
            });

        }
        // ...
        return book;
    }
}

结果:
这里写图片描述
这里的错处处理只是简单的打印。

这里的错误消息也可以做成国际化的,具体做法可以自己取研究。

当需要校验的Bean比较多的时候这样也会显得比较麻烦,所以这时候就可以使用Spring Boot的异常处理机制了。

Spring Boot的异常处理+Bean Validation

Spring Boot 中有一个专门处理错误信息的一个类叫做ResponseEntityExceptionHandler。其中有很多关于400的错误处理,也就是参数错误的处理,其中就有一个专门用来处理没有通过校验的参数的方法。我们重写这个类的这个方法即可。

@ControllerAdvice   // Spring 的异常处理的注解
public class BadRequestExceptionHandler extends ResponseEntityExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    
    @Override
    protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

        Map<String, String> messages = new HashMap<>();
        BindingResult result = ex.getBindingResult();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            for (ObjectError error : errors) {
                FieldError fieldError = (FieldError) error;
                messages.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
            logger.error(messages.toString());
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(messages);
    }
}

这时候controller中的方法中就不需要BindingResult或者Errors类型的参数了。

一些常用的Validation注解

注解作用
@NotNull值不能为空
@Null值必须为空
@Pattern(regex=)字符串必须匹配正则表达式
@Size(min, max)集合或者数组元素的数量必须在min和max之间
@CreditCardNumber(ignoreNonDigitCharacters=)字符串必须是信用卡号,按找美国的标准验证
@Email字符串必须是Email地址
@Length(min, max)检查字符串的长度
@NotBlank字符串不能为空串
@NotEmpty字符串不能为null, 集合或者数组的 size 不能为空
@Range(min, max)数字必须大于min, 小于max
@SafeHtml字符串必须是安全的html
@URL字符串必须是合法的URL
@AssertFalse值必须是false
@AssertTrue值必须是true
@DecimalMax(value=, inclusive=)值必须小于等于(inclusive=true)/小于(inclusive=false)属性指定的值,也可以注释在字符串类型的属性上。
@DecimalMin(value=, inclusive=)值必须大于等于(inclusive=true)/小于(inclusive=false)属性指定的值,也可以注释在字符串类型的属性上。
@Digist(integer=,fraction=)数字格式检查。integer指定整数部分的最大长度,fraction指定小数部分的最大长度
@Future时间必须是未来的
@Past事件必须是过去的
@Max(value=)值必须小于等于value指定的值。不能注解在字符串类型属性上。
@Min(value=)值必须小于等于value指定的值。不能注解在字符串类型属性上。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值