在日常工作中,往往需要验证参数的合法性,因此,springMVC提供了验证参数的机制,一方面,他可以支持JSR-303注解验证;另一方面,因为业务的复杂性,需要自定义验证规则,本篇来探讨相关问题。立志工具人。一起干饭!
本章主要内容
JSR-303 验证
SpringMVC参数验证机制
1.JSR-303验证
JSR-303验证主要是通过注解的方式进行的。
- 引入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 给参数对象添加校验注解
@Data
public class User {
private Integer id;
@NotBlank(message = "用户名不能为空")
private String username;
@Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$", message = "密码必须为8~16个字母和数字组合")
private String password;
@Email
private String email;
private Integer gender;
}
- Controller 中需要校验的参数Bean前添加 @Valid 开启校验功能
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("")
public Result save (@Valid User user , BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
Map<String , String> map = new HashMap<>();
bindingResult.getFieldErrors().forEach( (item) -> {
String message = item.getDefaultMessage();
String field = item.getField();
map.put( field , message );
} );
return Result.build( 400 , "非法参数 !" , map);
}
return Result.ok();
}
}
- 规范内嵌的约束注解
- 规范内嵌的约束注解
Constraint | 详细信息 |
---|---|
被注释的元素必须是电子邮箱地址 | |
@Length | 被注释的字符串的大小必须在指定的范围内 |
@NotEmpty | 被注释的字符串的必须非空 |
@Range | 被注释的元素必须在合适的范围内 |
2.SpringMVC参数验证机制
- SpringMVC中 的Validator (验证器)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.validation;
public interface Validator {
boolean supports(Class<?> var1);
void validate(Object var1, Errors var2);
}
spring定义验证器接口,它定义了两个方法,其中supports方法参数为需要验证的POJO类型,如果该方法返回true,则Spring会使用当前验证其的validation方法去验证POJO,而validation方法包含需要的target对象和错误对象errors,其中target是参数绑定后的POJO,这样便可以通过这个参数对象进行业务逻辑的自定义验证。如果发现错误,则可以保存到errors对象中,然后返回给控制器。
- 自定义用户验证器
package com.dylan.mall.validation;
import com.dylan.mall.component.Student;
import com.dylan.mall.component.User;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* @author Administrator
*/
public class UserValidator implements Validator {
//验证器只支持User
@Override
public boolean supports(Class<?> clazz) {
return clazz.equals(User.class);
}
/**
* 逻辑验证
*/
@Override
public void validate(Object target, Errors errors) {
if (target == null) {
errors.rejectValue("", null, "用户不能为空");
return;
}
//强制转换
User user = (User) target;
//用户名非空串
if (StringUtils.isEmpty(user.getUserName())) {
//增加错误,可以进入控制器方法
errors.rejectValue("userName", null, "用户名不能为空");
}
}
}
有了验证器,需要spring对象自动启动它。在springMVC中提供了一个注解@InitBinder,他的作用是在执行控制器方法前,处理器会先执行标@InitBinder标注的方法。这时将WebDataBinder对象作为参数传递到方法中,通过这层关系得到WebDataBinder对象,这个对象有一个setValidator方法,它可以绑定自定义验证器,这样就可以在获取参数之后,通过自定义的验证器去验证参数。
package com.dylan.mall.controller;
import com.dylan.mall.component.User;
import com.dylan.mall.validation.UserValidator;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Administrator
*/
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 调用控制器前先执行这个方法
*/
@InitBinder
public void initBinder(WebDataBinder webDataBinder) {
//绑定验证器
webDataBinder.setValidator(new UserValidator());
//定义日期参数格式,参数不在需注解@DateTimeFormat,boolean参数表示是否允许为空
webDataBinder.registerCustomEditor(Date.class,
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false)
);
}
@GetMapping("/validator")
@ResponseBody
public Map<String, Object> validator(@Valid User user, Errors errors,Date date) {
Map<String, Object> map = new HashMap<>();
map.put("user", user);
map.put("date", date);
if (errors.hasErrors()) {
List<ObjectError> oes= errors.getAllErrors();
for (ObjectError oe : oes) {
if (oe instanceof FieldError) {
FieldError fe = (FieldError) oe;
map.put(fe.getField(), fe.getDefaultMessage());
} else {
map.put(oe.getObjectName(), oe.getDefaultMessage());
}
}
}
return map;
}
}
user类
package com.dylan.mall.component;
import lombok.Data;
/**
* @author Administrator
*/
@Data
public class User {
private String userName;
private Integer age;
}
输出结果:
通过这样的自定义,在使用注解@Valid标注User参数后,SpringMVC就会去遍历对应的验证器,当遍历到UserValidator时,会去执行它的supports方法。因为该方法返回true,所以SpringMVC会用这个验证器去验证User类的数据。
不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!
若文章对您有用,请点赞支持哦。