SpringMVC之WebDataBinder处理请求参数绑定(二)

在上一章节,SpringBoot2.x系列教程29--整合SpringMVC之@InitBinder处理请求参数的绑定(上)的内容中,我给大家讲解了@InitBinder的原理及使用教程,本章节我继续讲解SpringMVC中的参数传递及数据绑定。

本章节主要是讲解WebDataBinder的内容。

一. WebDataBinder简介

从上面的代码案例中,我们可以看到另一个类,那就是WebDataBinder!

1. WebDataBinder的由来

在servlet中,有一个方法:request.getParameter("paramName"),它会根据key返回一个String类型的数据。

但是如果我们这样一个一个地去取出web中的请求参数,那就会很麻烦。我们知道Java中有对象的概念,那有没有办法将request中的请求参数自动封装到一个Java对象中呢? 为了解决这个问题,Spring中引入了WebDataBinder。

2. WebDataBinder类关系

3. WebDataBinder的作用

WebDataBinder的作用是从web request中把web请求里的parameters绑定到对应的JavaBean上!

在Controller方法中的参数类型可以是基本类型,也可以是封装后的普通Java类型。若这个普通的Java类型没有声明任何注解,则意味着它的每一个属性都需要到Request中去查找对应的请求参数,而WebDataBinder则可以帮助我们实现从Request中取出请求参数并绑定到JavaBean中。

4. WebDataBinder工作机制

WebDataBinder是用来绑定请求参数到指定的属性编辑器里的。由于前台传到Controller里的值是String类型,当往Java Bean里设置这个值的时候,如果设置的这个属性是个对象,Spring就会去找到对应的编辑器editor进行转换,然后再设置进去!

Spring自己提供了大量的实现类,诸如CustomDateEditor,CustomBooleanEditor,CustomNumberEditor等,基本上够我们开始使用。

但在平时使用SpringMVC时,可能会碰到Java Bean中有Date类型的参数,表单中传来代表日期的字符串转化为日期类型,SpringMVC在默认时,是不支持这种类型转换的。此时我们就需要手动设置时间格式并在WebDateBinder上注册这个编辑器!

5. 示例代码

@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实现过程

WebDataBinder一般都要结合@InitBinder来一起使用。

1.创建web项目

我们在上一个项目的基础之上直接编写本案例。

项目结构:

2. 创建User类

我们在项目中创建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;

}

3. Validator接口介绍

  • Validator 是一个有两个方法的接口;
  • boolean supports(Class<?> clazz) : 检验参数是否验证成功的实例类;
  • void validate(Object target, Errors errors) : 如果 supports() 方法返回真, target object 合法. Errors.rejectValue() 方法用一个字段名注册错误信息。

4. 创建UserValidator验证类

我们创建一个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");
        }
    }

}

5. 创建EmailValidator验证类

我们创建一个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.");
        }
    }

}

6. 创建ValidatorController测试接口

我们创建一个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";
    }

}

7. 启动程序进行测试

我们在postman中,输入地址: http://localhost:8080/user, 用post请求,传递json参数:

{
    "name":"一一哥",
    "password":"123",
    "email":"sss@33",
    "birthday": "2020-03-20"
}

此时可以看到返回的验证数据:

当传入的参数中,email不合格时,有如下返回值。

至此,我们第2篇数据绑定和自定义的属性编辑器,以及自定义参数校验器完成了!

原创文章 412 获赞 264 访问量 93万+

猜你喜欢

转载自blog.csdn.net/GUDUzhongliang/article/details/105705178