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;
}
}