SpringBoot Hibernate Validation 数据校验(参数验证、@Validated)

需要掌握:

说明

前端提交请求,controller接收数据时,通常要对数据进行校验,否则会引发错误

如:

  • 用户名、密码不能为空,并且要有长度限制
  • 手机号校验

前端已经做校验了,为什么后端还做校验?

同行通过 postman 等工具,或者编写程序,会绕过前端页面,直接访问 controller,如果后端不做校验,会导致报错

校验方法的形参(字符串类型)

环境:springboot 2.2.2 版本

创建 controller,类名上必须加 @Validated 注解,否则校验不生效(加方法名上、形参前面均不生效)

不符合校验规则,会抛出 ConstraintViolationException 异常(可在全局异常里进行配置)

@RestController
@Validated
public class Login2 {

    @RequestMapping("/doLogin")
    public JsonResult doLogin(
                               @NotNull(message = "登录名不能为空")
                               @Size(min = 3, max = 16, message = "登录名长度必须在3-16之间")
                               String username){

        return JsonResult.success("操作成功");
    }
}

测试

测试:

通过 postman 发请求 http://localhost:8085/doLogin :

{
    "password":"adm"
}

报错如下(需要配置全局异常处理):

{
    "code": 400,
    "msg": "登录名不能为空"
}

对方法的形参(bean类型)进行校验

bean

在成员变量上使用 校验注解

package top.malaoshi.netdisk.vo;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {
    private Long id;
    @NotNull(message = "登录名不能为空")
    @Size(min = 3, max = 16, message = "登录名长度必须在3-16之间")
    private String username;
    @NotNull(message = "密码不能为空")
    @Size(min = 5, max = 16, message = "密码长度必须在5-16之间")
    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

校验生效方式1(推荐)

环境:springboot 2.2.2 版本

形参是 bean 类型,形参前面只需要加 @Validated 注解,否则 不会对该形参进行校验

package top.malaoshi.netdisk.ctrl;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import top.malaoshi.netdisk.service.LoginSrvImpl;
import top.malaoshi.netdisk.vo.JsonResult;
import top.malaoshi.netdisk.vo.User;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

@RestController
public class LoginCtrl {

    @PostMapping("/login")
    public JsonResult login(HttpSession session, @Validated @RequestBody User user) throws Exception {
        return JsonResult.success("登录成功!");
    }

}

校验生效方式2

环境:springboot 2.2.2 版本

同时满足下面两个条件,才会 对形参进行校验:

package top.malaoshi.netdisk.ctrl;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import top.malaoshi.netdisk.service.LoginSrvImpl;
import top.malaoshi.netdisk.vo.JsonResult;
import top.malaoshi.netdisk.vo.User;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

@RestController
@Validated
public class LoginCtrl {

    @PostMapping("/login")
    public JsonResult login(HttpSession session, @Valid @RequestBody User user) throws Exception {
        return JsonResult.success("登录成功!");
    }

}

校验失败情况1:不加 @RequestBody

环境:springboot 2.2.2 版本

形参是 bean 类型,但前面 没有加 @RequestBody,导致无法给bean赋值,会抛出 BindException 异常(可在全局异常里进行配置)

package top.malaoshi.netdisk.ctrl;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import top.malaoshi.netdisk.service.LoginSrvImpl;
import top.malaoshi.netdisk.vo.JsonResult;
import top.malaoshi.netdisk.vo.User;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

@RestController
@Validated
public class LoginCtrl {

    @PostMapping("/login")
    public JsonResult login(HttpSession session, @Valid  User user) throws Exception {
        return JsonResult.success("登录成功!");
    }

}

测试:

通过 postman 发请求,提交数据如下:

{
    "password":"adm"
}

报错如下(需要配置全局异常处理):

{
    "code": 400,
    "msg": "密码不能为空; 登录名不能为空"
}

校验失败情况2:提交数据不正确

环境:springboot 2.2.2 版本

controller接收请求时,如果 不符合 bean 中的校验规则,会抛出 MethodArgumentNotValidException 异常(可在全局异常里进行配置)

package top.malaoshi.netdisk.ctrl;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import top.malaoshi.netdisk.service.LoginSrvImpl;
import top.malaoshi.netdisk.vo.JsonResult;
import top.malaoshi.netdisk.vo.User;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

@RestController
@Validated
public class LoginCtrl {

    @PostMapping("/login")
    public JsonResult login(HttpSession session, @Valid @RequestBody User user) throws Exception {
        return JsonResult.success("登录成功!");
    }

}

通过 postman 发请求,提交数据如下:

{
    "password":"adm"
}

报错如下(需要配置全局异常处理):

{
    "code": 400,
    "msg": "密码长度必须在5-16之间; 登录名不能为空"
}

异常处理

详见:
https://www.malaoshi.top/show_1IX759F5VBeO.html

参考:
https://blog.csdn.net/qq_46197017/article/details/119056006

https://www.jianshu.com/p/3267689ebf1b


原文出处:/show_1IX74zIKGJ7j.html