12、SpringBoot服务端数据校验

SpringBoot对Controller中其他参数的校验

  • 编写页面
  • 对参数指定校验规则
  • 在Controller中开启校验
  • 通过全局异常处理来跳转页面

校验规则有Hibernate Validator提供,该校验规则由web起步依赖提供,如下:

修改实体类添加校验规则

/**
* @NotNull: 对基本数据类型的封装类做非空校验(基本数据类型int没有非空校验这种说法)
* @NotBlank: 对字符串类型做非空校验
* @NotEmpty: 对集合类型做非空校验
*/
public class Users {
    @NotNull
    private Integer userid;
    @NotBlank
    private String username;
    @NotBlank
    private String usersex;

    public Integer getUserid() {
        return userid;
    }

    public void setUserid(Integer userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

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

    public String getUsersex() {
        return usersex;
    }

    public void setUsersex(String usersex) {
        this.usersex = usersex;
    }

    public Users(@NotNull Integer userid, @NotBlank String username, @NotBlank String usersex) {
        this.userid = userid;
        this.username = username;
        this.usersex = usersex;
    }

    public Users() {}
    
    @Override
    public String toString() {
        return "Users{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", usersex='" + usersex + '\'' +
                '}';
    }
}

在Controller中开启校验

  • 在需要校验的对象的前面加上@Validated注解即可
  • BindingResult 表示的是前一个对象校验过程中产生的一些不合法的信息
  • BindingResult一定要放在需要校验的对象的后面,一个BindingResult仅代表前一个对象的不合法信息
  • BindingResult包含的不合法信息可以直接携带到视图当中,不需要用model.Attribute()
  • 通过数据校验对象的类名首字母小写“.”对象属性,来获取BindResult中的值
@Controller
@RequestMapping("/user")
public class UsersController {

    /**
     * 添加用户
     */
    @RequestMapping("/addUser")
    public String addUser(@Validated Users users, BindingResult result){
        if(result.hasErrors()){
            List<ObjectError> list = result.getAllErrors();
            for(ObjectError err:list){
                FieldError fieldError = (FieldError) err;
                //校验不合法的属性的名字
                String fieldName = fieldError.getField();
                //默认的提示信息
                String msg = fieldError.getDefaultMessage();
                System.out.print(fieldName+"\t" + msg);
            }
            return "addUser";
        }
        System.out.println(users);
        return "ok";
    }
}

获取BindingResult中的异常信息,是通过校验不合法的对象的类名首字母小写.属性名 来获取

addUser.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form th:action="@{/user/addUser}" method="post">
    <input type="text" name="username"><font color="red"><span th:errors="${users.username}"></span></font>

    <input type="text" name="usersex"><font color="red"><span th:errors="${users.usersex}"></span></font>

    <input type="submit" value="OK">
</form>
</body>
</html>

自定义错误提示信息

由于默认的校验提示信息表示的不够明确,所以可以通过自定义错误提示信息来达到需求

修改pojo,给校验注解添加自定义提示信息,替换掉默认的提示信息

**
* @NotNull: 对基本数据类型的封装类做非空校验(基本数据类型int没有非空校验这种说法)
* @NotBlank: 对字符串类型做非空校验
* @NotEmpty: 对集合类型做非空校验
*/
public class Users {
    @NotNull(message = "用户ID不能为空")
    private Integer userid;
    @NotBlank(message = "用户名不能为空")
    private String username;
    @NotBlank(message = "用户性别不能为空")
    private String usersex;
        ........

在注解里直接定义提示信息,这种编码方式有缺点就是硬编码

通过ValidationMessages.properties进行提示信息的配置

hibernate validator 是读取不到application.properties框架中的配置信息的,因此必须创建一个名为ValidationMessages.properties配置文件,用于存储异常信息;

#定义提示信息
#定义提示信息
userid.notnull=用户ID不能为空
username.notnull=用户姓名不能为空
usersex.notnull=用户性别不能为空

如果异常信息出现中文乱码,idea可以通过这只properties编码设置,解决该问题,如下:

修改参数key的名称

通过@ModelAttribute修改key名称

/**
* 跳转页面的方法
* 解决异常的方式;可以在跳转页面的方法中注入一个Users对象
* 由于spring'MVC会将该对象放入到Model中传递,key的名称会使用该对象类型的驼峰命名规则来作为key
* @param page
* @param users
* @return
*/
@RequestMapping("/{page}")
public String page(@PathVariable String page,@ModelAttribute("aa") Users users){
    return page;
}
/**
* 添加用户
*/
@RequestMapping("/addUser")
public String addUser(@ModelAttribute("aa")@Validated Users users, BindingResult result){
    if(result.hasErrors()){
        List<ObjectError> list = result.getAllErrors();
        for(ObjectError err:list){
            FieldError fieldError = (FieldError) err;
            //校验不合法的属性的名字
            String fieldName = fieldError.getField();
            //默认的提示信息
            String msg = fieldError.getDefaultMessage();
            System.out.print(fieldName+"\t" + msg);
        }
        return "addUser";
    }
    System.out.println(users);
    return "ok";
}

其他校验规则

    @NotNull:判断基本数据类型的对昂类型是否为null
    @NotBlank:判断字符串是否为null或者空串(去掉首位空格)
    @NotEmpty:判断集合是否为空
    @length:判断字符的长度(最大或者最小)
    @Min:判断数值最小值
    @Max:判断数值最大值
    @Email:判断邮箱是否合法

SpringBoot对Controller中其他参数类型的校验

编写页面

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form th:action="@{/user/findUser}" method="post">
    <input type="text" name="username"><font color="red"><span th:text="${error}"></span></font>

    <input type="submit" value="OK">
</form>
</body>
</html>

通过@Validated注解开启SpringBoot对Controller的参数校验,这样@NotBlank才会生效

@Controller
@RequestMapping("/user")
@Validated
public class UsersController {

    @PostMapping("/findUser")
    public String findUser(@NotBlank(message = "用户名不能为空") String username){
        System.out.println(username);
        return "ok";
    }
}

对实体类型之外的数据类型做数据校验时,并不要求需要BindingResult对象获取异常信息,如果该参数校验异常会直接将异常信息返回/error页面显示;

如果想将校验不合法的信息传递回自己指定的页面,并显示的话,就需要通过全局异常类来处理

校验不合法时,会出现异常,全局异常类,通过捕获异常,进行处理,并指定一个视图作为跳转

GloballException

@Configuration
public class GloballException implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) {
        ModelAndView mv = new ModelAndView();
        //判断不同异常类型,做不同视图的跳转
        if(e instanceof NullPointerException){
            mv.setViewName("error5");
        }
        if(e instanceof ArithmeticException){
            mv.setViewName("error6");
        }
        if(e instanceof ConstraintViolationException){
            mv.setViewName("findUser");
        }
        //不管跳到哪个视图,携带的异常信息不变所以不用带入if判断里面
        mv.addObject("error", e.getMessage().split(":")[1]);
        return mv;
    }
}
posted @ 2020-08-28 13:08  lawrence林  阅读(202)  评论(0编辑  收藏  举报