SpringBoot2.x系列教程20--WebDataBinder对请求参数进行合法性校验和数据绑定

简介: 前言在上一章节的内容中,壹哥 给大家讲解了@InitBinder的原理及使用教程,我们利用InitBinder实现了对日期类型参数的格式转换。本章节我会利用另一种技术WebDataBinder,继续处理SpringBoot中的参数传递及数据绑定,并在本文中带大家实现自定义的属性编辑器,以及自定义参数校验器。一. WebDataBinder简介在进行代码实现之前,我们先来看看WebDataBinder是个什么东东!1. WebDataBinder的由来在Servlet中,有一个方法:request.getParameter("paramName"),它会根据key返回一个Strin

前言

在上一章节的内容中,壹哥 给大家讲解了@InitBinder的原理及使用教程,我们利用InitBinder实现了对日期类型参数的格式转换。

本章节我会利用另一种技术WebDataBinder,继续处理SpringBoot中的参数传递及数据绑定,并在本文中带大家实现自定义的属性编辑器,以及自定义参数校验器。

一. WebDataBinder简介

在进行代码实现之前,我们先来看看WebDataBinder是个什么东东!

1. WebDataBinder的由来

在Servlet中,有一个方法:request.getParameter("paramName"),它会根据key返回一个String类型的数据,从而获取到前端传递过来的请求参数。

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

2. WebDataBinder类关系

我们再来看看WebDataBinder的类关系图:

3. WebDataBinder的作用

WebDataBinder的作用是从Web 请求中,把请求里的参数都绑定到对应的JavaBean上!

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

4. WebDataBinder工作机制

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

SpringMVC自己提供了大量的editor编辑器实现类,诸如CustomDateEditor,CustomBooleanEditor,CustomNumberEditor等,基本上够我们使用了。

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

5. 示例代码

利用CustomDateEditor实现日期格式转换的示例代码,如下所示:

@InitBinderpublicvoidbindingPreparation(WebDataBinderbinder) {  
DateFormatdateFormat1=newSimpleDateFormat("dd-MM-yyyy");  
CustomDateEditororderDateEditor=newCustomDateEditor(dateFormat1, true);  
DateFormatdateFormat2=newSimpleDateFormat("MMM d, YYYY");  
CustomDateEditorshipDateEditor=newCustomDateEditor(dateFormat2, true);  
binder.registerCustomEditor(Date.class, "orderDate", orderDateEditor);  
binder.registerCustomEditor(Date.class, "shipDate", shipDateEditor);  
}

二. WebDataBinder实现过程

了解了上面的这些理论内容,接下来我就利用WebDataBinder实现参数的转换。

1. 创建Web项目

首先我们要创建一个Web项目,或者也可以直接在上一个项目的基础之上编写本案例代码,具体请参考之前的章节。

2. 创建User类

我们在项目中创建一个domain包,在该包下创建一个User实体类,里面有个日期类型的birthday字段

packagecom.yyg.boot.domain;
importlombok.Data;
importjava.util.Date;
/*** @Description Description* @Author 一一哥Sun* @Date Created in 2020/3/23*/@DatapublicclassUser {
privateStringname;
privateStringpassword;
privateStringemail;
privateDatebirthday;
}

3. Validator接口介绍

在使用Validator之前,我先介绍一下Validator接口。

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

4. 创建UserValidator验证类

我们创建一个validator包,在该包下面创建一个UserValidator验证类,在这里负责对前端传递过来的User类型参数进行必要的校验,判断用户名和密码是否符合规范。

packagecom.yyg.boot.validator;
importcom.yyg.boot.domain.User;
importorg.springframework.stereotype.Component;
importorg.springframework.validation.Errors;
importorg.springframework.validation.ValidationUtils;
importorg.springframework.validation.Validator;
/*** @Description Description* @Author 一一哥Sun* @Date Created in 2020/3/23*/@ComponentpublicclassUserValidatorimplementsValidator {
/*** 检验参数是否验证成功的实例类*/@Overridepublicbooleansupports(Class<?>clazz) {
//isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类。returnUser.class.isAssignableFrom(clazz);
    }
/*** 如果 supports() 方法返回真, target object 合法. Errors.rejectValue() 方法会用一个字段名注册错误信息;*/@Overridepublicvoidvalidate(Objecttarget, Errorserrors) {
Useruser= (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验证类,判断用户的邮箱信息是否符合要求。

packagecom.yyg.boot.validator;
importcom.yyg.boot.domain.User;
importorg.springframework.stereotype.Component;
importorg.springframework.validation.Errors;
importorg.springframework.validation.ValidationUtils;
importorg.springframework.validation.Validator;
/*** @Description Description* @Author 一一哥Sun* @Date Created in 2020/3/23*/@ComponentpublicclassEmailValidatorimplementsValidator {
@Overridepublicbooleansupports(Class<?>clazz) {
returnUser.class.isAssignableFrom(clazz);
    }
@Overridepublicvoidvalidate(Objecttarget, Errorserrors) {
Useruser= (User)target;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "","Email is empty");
if (!user.getEmail().contains("@")) {
errors.rejectValue("email","", "Email is not valid.");
        }
    }
}

6. 创建ValidatorController测试接口

接下来我们创建一个web包,在该包下面创建一个ValidatorController类,并且编写一个接口,接受前端传递过来的User参数。而且该类中还要实现InitBinder的参数格式化校验。

packagecom.yyg.boot.web;
importcom.yyg.boot.domain.User;
importcom.yyg.boot.validator.EmailValidator;
importcom.yyg.boot.validator.UserValidator;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.propertyeditors.CustomDateEditor;
importorg.springframework.stereotype.Controller;
importorg.springframework.validation.BindingResult;
importorg.springframework.web.bind.WebDataBinder;
importorg.springframework.web.bind.annotation.*;
importjavax.validation.Valid;
importjava.text.SimpleDateFormat;
importjava.util.Date;
/*** @Description Description* @Author 一一哥Sun* @Date Created in 2020/3/23*/@ControllerpublicclassValidatorController {
@AutowiredprivateUserValidatoruserValidator;
@AutowiredprivateEmailValidatoremailValidator;
/*** 接收参数,自定义编辑器*/@InitBinderpublicvoiddataBinding(WebDataBinderbinder) {
//将UserValidator和EmailValidator添加到WebDataBinder中binder.addValidators(userValidator, emailValidator);
SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-dd");
//setLenient用于设置Calendar是否宽松解析字符串,如果为false,则严格解析;默认为true,宽松解析dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, "birthday", newCustomDateEditor(dateFormat, true));
    }
@ResponseBody@RequestMapping(value="/user", method=RequestMethod.POST)
publicStringcreateUser(@RequestBody@ValidUseruser, BindingResultresult) {
if (result.hasErrors()) {
returnresult.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. 项目结构

完整的项目结构如下图所示,各位可以参考创建。

8. 启动程序进行测试

最后我们启动项目,在Postman中进行测试,输入地址:
http://localhost:8080/user,

8.1 验证用户名长度

这里我们要使用post请求,传递一个json格式的参数:

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

执行完毕后可以看到返回的验证数据:

8.2 验证邮箱格式

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

至此,我们就实现了数据绑定和自定义的属性编辑器,以及自定义的参数校验器效果了!

结语

利用今天的内容,我们就可以对前端传递过来的参数进行统一的合法性校验了,这样就避免了很多非法请求。你学会了吗?

今日小作业:

思考今天的效果,还能不能进一步改进?

相关文章
|
17天前
|
SQL 安全 Java
当心!SpringBoot错误的数据绑定带来安全隐患
【8月更文挑战第31天】在快速发展的软件开发领域,Spring Boot凭借其快速开发、自动配置等特性,成为了众多开发者的首选框架。然而,随着应用的日益复杂,错误的数据绑定不仅可能导致功能上的缺陷,还可能成为安全隐患的温床。本文将围绕“SpringBoot错误的数据绑定带来安全隐患”这一主题,分享一些工作学习中的技术干货,帮助开发者更好地理解和防范这一问题。
22 0
|
2月前
|
Java Spring
springBoot 使用 @NotEmpty,@NotBlank,@NotNull 及@Valid注解校验请求参数
springBoot 使用 @NotEmpty,@NotBlank,@NotNull 及@Valid注解校验请求参数
68 7
|
3月前
|
Java
springboot自定义拦截器,校验token
springboot自定义拦截器,校验token
171 6
|
3月前
|
缓存 NoSQL Java
案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序
案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序
90 5
|
3月前
|
XML 前端开发 Java
SpringBoot参数校验@Validated、@Valid(javax.validation)详解
SpringBoot参数校验@Validated、@Valid(javax.validation)
265 4
|
2月前
|
存储 Java Spring
在Spring Boot中实现数据验证与校验
在Spring Boot中实现数据验证与校验
|
4月前
|
Java API Spring
Spring Boot中的 6 种API请求参数读取方式
本文介绍了Spring Boot中6种常见的请求参数读取方式:@RequestParam用于加载URL查询参数,@PathVariable处理RESTful风格的URL路径参数,@MatrixVariable处理URL路径中的矩阵变量,@RequestBody用于读取POST/PUT请求的复杂请求体,@RequestHeader加载请求头信息,而@CookieValue则用于获取Cookie值。这些注解在不同场景下满足了API参数的多样化需求。
|
4月前
|
Java
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
Springboot 使用自定义注解结合AOP方式校验接口参数
|
4月前
|
前端开发 Java
SpringBoot之自定义注解参数校验
SpringBoot之自定义注解参数校验
47 2
|
4月前
|
存储 JSON 算法
SpringBoot之JWT令牌校验
SpringBoot之JWT令牌校验
140 2