作者:一一哥
在上一章节,SpringBoot2.x系列教程29--整合SpringMVC之@InitBinder处理请求参数的绑定(上)的内容中,我给大家讲解了@InitBinder的原理及使用教程,本章节我继续讲解SpringMVC中的参数传递及数据绑定。
本章节主要是讲解WebDataBinder的内容。
从上面的代码案例中,我们可以看到另一个类,那就是WebDataBinder!
在servlet中,有一个方法:request.getParameter("paramName")
,它会根据key返回一个String类型的数据。
但是如果我们这样一个一个地去取出web中的请求参数,那就会很麻烦。我们知道Java中有对象的概念,那有没有办法将request中的请求参数自动封装到一个Java对象中呢?
为了解决这个问题,Spring中引入了WebDataBinder。
WebDataBinder的作用是从web request中把web请求里的parameters
绑定到对应的JavaBean
上!
在Controller方法中的参数类型可以是基本类型,也可以是封装后的普通Java类型。若这个普通的Java类型没有声明任何注解,则意味着它的每一个属性都需要到Request中去查找对应的请求参数,而WebDataBinder则可以帮助我们实现从Request中取出请求参数并绑定到JavaBean中。
WebDataBinder是用来绑定请求参数到指定的属性编辑器里的。由于前台传到Controller里的值是String类型,当往Java Bean里设置这个值的时候,如果设置的这个属性是个对象,Spring就会去找到对应的编辑器editor进行转换,然后再设置进去!
Spring自己提供了大量的实现类,诸如CustomDateEditor,CustomBooleanEditor,CustomNumberEditor等,基本上够我们开始使用。
但在平时使用SpringMVC时,可能会碰到Java Bean中有Date类型的参数,表单中传来代表日期的字符串转化为日期类型,SpringMVC在默认时,是不支持这种类型转换的。此时我们就需要手动设置时间格式并在WebDateBinder上注册这个编辑器!
@InitBinder
public void bindingPreparation(WebDataBinder binder) {
DateFormat dateFormat1 = new SimpleDateFormat("dd-MM-yyyy");
CustomDateEditor orderDateEditor = new CustomDateEditor(dateFormat1, true);
DateFormat dateFormat2 = new SimpleDateFormat("MMM d, YYYY");
CustomDateEditor shipDateEditor = new CustomDateEditor(dateFormat2, true);
binder.registerCustomEditor(Date.class, "orderDate", orderDateEditor);
binder.registerCustomEditor(Date.class, "shipDate", shipDateEditor);
}
WebDataBinder一般都要结合@InitBinder来一起使用。
我们在上一个项目的基础之上直接编写本案例。
我们在项目中创建domain包,在该包下创建一个User类。
package com.yyg.boot.domain;
import lombok.Data;
import java.util.Date;
/**
* @Description Description
* @Author 一一哥Sun
* @Date Created in 2020/3/23
*/
@Data
public class User {
private String name;
private String password;
private String email;
private Date birthday;
}
我们创建一个validator包,在该包下面创建一个UserValidator验证类。
package com.yyg.boot.validator;
import com.yyg.boot.domain.User;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
/**
* @Description Description
* @Author 一一哥Sun
* @Date Created in 2020/3/23
*/
@Component
public class UserValidator implements Validator {
/**
* 检验参数是否验证成功的实例类
*/
@Override
public boolean supports(Class> clazz) {
//isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类。
return User.class.isAssignableFrom(clazz);
}
/**
* 如果 supports() 方法返回真, target object 合法. Errors.rejectValue() 方法会用一个字段名注册错误信息;
*/
@Override
public void validate(Object target, Errors errors) {
User user = (User)target;
//配置字段验证信息
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "","Username is empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "", "Password is empty");
//用户名长度不能小于5个字符
if (user.getName().length()<5) {
errors.rejectValue("name","", "Username length is less than 5");
}
}
}
我们创建一个validator包,在该包下面创建一个EmailValidator验证类。
package com.yyg.boot.validator;
import com.yyg.boot.domain.User;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
/**
* @Description Description
* @Author 一一哥Sun
* @Date Created in 2020/3/23
*/
@Component
public class EmailValidator implements Validator {
@Override
public boolean supports(Class> clazz) {
return User.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
User user = (User)target;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "","Email is empty");
if (!user.getEmail().contains("@")) {
errors.rejectValue("email","", "Email is not valid.");
}
}
}
我们创建一个web包,在该包下面创建一个ValidatorController类。
package com.yyg.boot.web;
import com.yyg.boot.domain.User;
import com.yyg.boot.validator.EmailValidator;
import com.yyg.boot.validator.UserValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Description Description
* @Author 一一哥Sun
* @Date Created in 2020/3/23
*/
@Controller
public class ValidatorController {
@Autowired
private UserValidator userValidator;
@Autowired
private EmailValidator emailValidator;
/**
* 接收参数,自定义编辑器
*/
@InitBinder
public void dataBinding(WebDataBinder binder) {
binder.addValidators(userValidator, emailValidator);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//setLenient用于设置Calendar是否宽松解析字符串,如果为false,则严格解析;默认为true,宽松解析
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, "birthday", new CustomDateEditor(dateFormat, true));
}
@ResponseBody
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String createUser(@RequestBody @Valid User user, BindingResult result) {
if (result.hasErrors()) {
return result.getFieldError().getDefaultMessage();
}
System.out.println("Name:" + user.getName());
System.out.println("Email:" + user.getEmail());
System.out.println("Date of Birth:" + user.getBirthday());
return "success";
}
}
我们在postman中,输入地址:
http://localhost:8080/user,
用post请求,传递json参数:
{
"name":"一一哥",
"password":"123",
"email":"sss@33",
"birthday": "2020-03-20"
}
此时可以看到返回的验证数据:
当传入的参数中,email不合格时,有如下返回值。
至此,我们第2篇数据绑定和自定义的属性编辑器,以及自定义参数校验器完成了!