在日常工作中队橙,往往需要驗(yàn)證參數(shù)的合法性华弓,因此,springMVC提供了驗(yàn)證參數(shù)的機(jī)制冠句,一方面迷捧,他可以支持JSR-303注解驗(yàn)證织咧;另一方面,因?yàn)闃I(yè)務(wù)的復(fù)雜性漠秋,需要自定義驗(yàn)證規(guī)則笙蒙,本篇來探討相關(guān)問題。立志工具人膛堤。一起干飯手趣!
本章主要內(nèi)容
JSR-303 驗(yàn)證
SpringMVC參數(shù)驗(yàn)證機(jī)制
1.JSR-303驗(yàn)證
JSR-303驗(yàn)證主要是通過注解的方式進(jìn)行的。
- 引入相關(guān)依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 給參數(shù)對象添加校驗(yàn)注解
@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個字母和數(shù)字組合")
private String password;
@Email
private String email;
private Integer gender;
}
- Controller 中需要校驗(yàn)的參數(shù)Bean前添加 @Valid 開啟校驗(yàn)功能
@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 , "非法參數(shù) !" , map);
}
return Result.ok();
}
}
- 規(guī)范內(nèi)嵌的約束注解
- 規(guī)范內(nèi)嵌的約束注解
Constraint | 詳細(xì)信息 |
---|---|
被注釋的元素必須是電子郵箱地址 | |
@Length | 被注釋的字符串的大小必須在指定的范圍內(nèi) |
@NotEmpty | 被注釋的字符串的必須非空 |
@Range | 被注釋的元素必須在合適的范圍內(nèi) |
2.SpringMVC參數(shù)驗(yàn)證機(jī)制
- SpringMVC中 的Validator (驗(yàn)證器)
//
// 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定義驗(yàn)證器接口肥荔,它定義了兩個方法绿渣,其中supports方法參數(shù)為需要驗(yàn)證的POJO類型,如果該方法返回true燕耿,則Spring會使用當(dāng)前驗(yàn)證其的validation方法去驗(yàn)證POJO中符,而validation方法包含需要的target對象和錯誤對象errors,其中target是參數(shù)綁定后的POJO誉帅,這樣便可以通過這個參數(shù)對象進(jìn)行業(yè)務(wù)邏輯的自定義驗(yàn)證淀散。如果發(fā)現(xiàn)錯誤,則可以保存到errors對象中蚜锨,然后返回給控制器档插。
- 自定義用戶驗(yàn)證器
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 {
//驗(yàn)證器只支持User
@Override
public boolean supports(Class<?> clazz) {
return clazz.equals(User.class);
}
/**
* 邏輯驗(yàn)證
*/
@Override
public void validate(Object target, Errors errors) {
if (target == null) {
errors.rejectValue("", null, "用戶不能為空");
return;
}
//強(qiáng)制轉(zhuǎn)換
User user = (User) target;
//用戶名非空串
if (StringUtils.isEmpty(user.getUserName())) {
//增加錯誤,可以進(jìn)入控制器方法
errors.rejectValue("userName", null, "用戶名不能為空");
}
}
}
有了驗(yàn)證器亚再,需要spring對象自動啟動它郭膛。在springMVC中提供了一個注解@InitBinder,他的作用是在執(zhí)行控制器方法前氛悬,處理器會先執(zhí)行標(biāo)@InitBinder標(biāo)注的方法则剃。這時將WebDataBinder對象作為參數(shù)傳遞到方法中,通過這層關(guān)系得到WebDataBinder對象如捅,這個對象有一個setValidator方法棍现,它可以綁定自定義驗(yàn)證器,這樣就可以在獲取參數(shù)之后镜遣,通過自定義的驗(yàn)證器去驗(yàn)證參數(shù)己肮。
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 {
/**
* 調(diào)用控制器前先執(zhí)行這個方法
*/
@InitBinder
public void initBinder(WebDataBinder webDataBinder) {
//綁定驗(yàn)證器
webDataBinder.setValidator(new UserValidator());
//定義日期參數(shù)格式,參數(shù)不在需注解@DateTimeFormat,boolean參數(shù)表示是否允許為空
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;
}
輸出結(jié)果:
通過這樣的自定義朴肺,在使用注解@Valid標(biāo)注User參數(shù)后窖剑,SpringMVC就會去遍歷對應(yīng)的驗(yàn)證器,當(dāng)遍歷到UserValidator時戈稿,會去執(zhí)行它的supports方法。因?yàn)樵摲椒ǚ祷豻rue讶舰,所以SpringMVC會用這個驗(yàn)證器去驗(yàn)證User類的數(shù)據(jù)鞍盗。
不要以為每天把功能完成了就行了,這種思想是要不得的跳昼,互勉~般甲!
若文章對您有用,請點(diǎn)贊支持哦鹅颊。