SpringMVC數(shù)據(jù)校驗(yàn)+VO++脫敏實(shí)戰(zhàn)指南
概念引入
在Spring MVC中,數(shù)據(jù)校驗(yàn)是確保用戶輸入符合預(yù)期規(guī)則的重要環(huán)節(jié)
Spring MVC通過(guò)整合 Bean Validation 規(guī)范,提供了靈活的數(shù)據(jù)校驗(yàn)機(jī)制。核心步驟包括:
- 在Java Bean中添加校驗(yàn)注解。
- 在Controller中使用
@Valid或@Validated觸發(fā)校驗(yàn)。 - 通過(guò)
BindingResult或全局異常處理捕獲錯(cuò)誤。 - 可選擴(kuò)展:分組校驗(yàn)、自定義注解、國(guó)際化消息。
一 基礎(chǔ)原理
1 先將數(shù)據(jù)校驗(yàn)的依賴導(dǎo)入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>2 在JavaBean中編寫(xiě)校驗(yàn)注解
@NotBlank(message = "名字不能為空")
private String name;
private Integer id;
@Min(value = 0, message = "年齡不能小于0")
@Max(value = 200, message = "年齡不能大于200")
private Integer age;
@NotBlank(message = "性別不能為空")
private String gender; // 正則表達(dá)式
@Pattern(regexp = "^男|女$", message = "性別只能是男或女")
private String gender;3 使用@Valid告訴SpringMVC進(jìn)行校驗(yàn)(校驗(yàn)不通過(guò),方法通知執(zhí)行)
// 添加員工,前端發(fā)送請(qǐng)求,把 json 數(shù)據(jù)封裝到 Employee 對(duì)象中
@PostMapping(value = "/employee")
public R add(@RequestBody @Valid Employee employee) {
employeeService.addEmployee(employee);
return R.ok();
}4 在@Valid參數(shù)后面加上一個(gè)BindingResult參數(shù),獲取校驗(yàn)結(jié)果。
可以進(jìn)行反饋
// 添加員工,前端發(fā)送請(qǐng)求,把 json 數(shù)據(jù)封裝到 Employee 對(duì)象中
@PostMapping(value = "/employee")
public R add(@RequestBody @Valid Employee employee, BindingResult bindingResult) {
// 校驗(yàn)正確
if (!bindingResult.hasErrors()) {
employeeService.addEmployee(employee);
return R.ok();
}
Map<String, Object> errorMap = new HashMap<>();
for (FieldError fieldError : bindingResult.getFieldErrors()) {
//獲取屬性名
String field = fieldError.getField();
//獲取錯(cuò)誤信息描述
String message = fieldError.getDefaultMessage();
errorMap.put(field, message);
}
return R.error(500, "校驗(yàn)失敗", errorMap);
}運(yùn)行結(jié)果演示

二 改進(jìn)方案
編寫(xiě)一個(gè)全局異常處理器處理(MethodArgumentNotValidException 校驗(yàn)時(shí)出現(xiàn)的錯(cuò)誤,同時(shí)返回校驗(yàn)出錯(cuò)的信息)

1 沒(méi)寫(xiě)全局校驗(yàn)時(shí):

2 寫(xiě)了全局校驗(yàn)后:

3 編寫(xiě)過(guò)程:

代碼實(shí)現(xiàn):(出現(xiàn)校驗(yàn)錯(cuò)誤就會(huì)報(bào)錯(cuò),我們將這個(gè)錯(cuò)誤的方法進(jìn)行封裝,達(dá)到全局的效果)
//寫(xiě)一個(gè)全局校驗(yàn)異常的處理(bindingResult中有校驗(yàn)錯(cuò)誤的信息,現(xiàn)在我們將它存放到map集合當(dāng)中進(jìn)行遍歷)
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Map<String, Object> errorMap = new HashMap<>();
for (FieldError fieldError : bindingResult.getFieldErrors()) {
//獲取屬性名
String field = fieldError.getField();
//獲取錯(cuò)誤信息描述
String message = fieldError.getDefaultMessage();
errorMap.put(field, message);
}
return R.error(500, "校驗(yàn)失敗", errorMap);
}三 自定義校驗(yàn)注解-校驗(yàn)注解綁定校驗(yàn)器
1 創(chuàng)建需要的注解

完善類(lèi)中的內(nèi)容:
package org.example.springmvc.annotation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import org.example.springmvc.validator.GenderValidator;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = {GenderValidator.class})
@Target({FIELD})
@Retention(RUNTIME)
public @interface Gender {
String message() default "{jakarta.validation.constraints.NotBlank.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}2 將注解類(lèi)中Constrain注解中的參數(shù)方法補(bǔ)充
創(chuàng)建這個(gè)類(lèi):

將類(lèi)中的需求寫(xiě)上:
package org.example.springmvc.validator;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.example.springmvc.annotation.Gender;
public class GenderValidator implements ConstraintValidator<Gender, String> {
@Override
public void initialize(Gender constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return "男".equals(s) || "女".equals(s);
}
}3 在指定的參數(shù)加上校驗(yàn)注解
@Gender(message = "性別只能是男或女")
private String gender;4 運(yùn)行結(jié)果:

四 拓展知識(shí)點(diǎn)-配置文件中獲取
1 在資源包中新建file文件(可以根據(jù)需求填寫(xiě)不同的語(yǔ)言版本)

2 在變量千指定
//實(shí)現(xiàn)國(guó)際化配置
@Gender(message = "{gender.message}")
private String gender;3 在資源包的file文件中填寫(xiě)數(shù)據(jù)
可能需要調(diào)整編碼

填寫(xiě)


實(shí)際應(yīng)用:

核心:

五 解決不同需求使用變量的不同校驗(yàn)-VO

VO層(View Object/Value Object)在實(shí)際開(kāi)發(fā)中的作用
VO層是分層架構(gòu)中的核心組件之一,主要用于前端與后端的數(shù)據(jù)交互,其核心作用如下:
1 為了添加數(shù)據(jù)而準(zhǔn)備的VO類(lèi)
package org.example.springmvc.vo.req;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.example.springmvc.annotation.Gender;
@Data
public class EmployeeAddVo {
@NotBlank(message = "名字不能為空")
private String name;
@Min(value = 0, message = "年齡不能小于0")
@Max(value = 200, message = "年齡不能大于200")
private Integer age;
@Gender(message = "{gender.message}")
private String gender;
}2 為了修改數(shù)據(jù)所添加的VO類(lèi)
package org.example.springmvc.vo.req;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class EmployeeUpdateVo {
@NotNull(message = "id不能為空")
private Integer id;
private String name;
private Integer age;
private String gender;
}3 Controller層的業(yè)務(wù)修改
// 添加員工,前端發(fā)送請(qǐng)求,把 json 數(shù)據(jù)封裝到 Employee 對(duì)象中
@PostMapping(value = "/employee")
public R add(@RequestBody @Valid EmployeeAddVo employeeAddVo) {
//把vo轉(zhuǎn)為do(調(diào)用BeanUtils中的方法將屬性傳遞)
Employee employee = new Employee();
BeanUtils.copyProperties(employeeAddVo, employee);
employeeService.addEmployee(employee);
return R.ok();
}
// 修改員工
@PutMapping(value = "/employee")
public R update(@RequestBody @Valid EmployeeUpdateVo employeeUpdateVo) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeUpdateVo, employee);
employeeService.updateEmployee(employee);
return R.ok();
}運(yùn)行代碼:


六 實(shí)現(xiàn)脫敏操作
數(shù)據(jù)脫敏(Data Masking)是指通過(guò)技術(shù)手段對(duì)敏感信息進(jìn)行處理,使其在不影響業(yè)務(wù)功能的前提下,無(wú)法被直接識(shí)別或還原為原始數(shù)據(jù),從而保護(hù)用戶隱私、防范數(shù)據(jù)泄露風(fēng)險(xiǎn)。

//查詢所有員工
@GetMapping(value = "/employees")
public R all() {
// 實(shí)現(xiàn)脫敏操作將年齡隱藏(返回給前端)
List<Employee> employees = employeeService.getList();
List<EmployeeRespVo> collect = employees.stream().map(employee -> {
EmployeeRespVo employeeRespVo = new EmployeeRespVo();
BeanUtils.copyProperties(employee, employeeRespVo);
return employeeRespVo;
}).toList();
return R.ok(collect);
}脫敏成功:

到此這篇關(guān)于SpringMVC數(shù)據(jù)校驗(yàn)+VO++脫敏的文章就介紹到這了,更多相關(guān)SpringMVC數(shù)據(jù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java char數(shù)據(jù)類(lèi)型原理解析
這篇文章主要介紹了java char數(shù)據(jù)類(lèi)型原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
自定義Jackson的ObjectMapper如何實(shí)現(xiàn)@ResponseBody的自定義渲染
這篇文章主要介紹了自定義Jackson的ObjectMapper如何實(shí)現(xiàn)@ResponseBody的自定義渲染,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼
這篇文章主要介紹了java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02
JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類(lèi)
在日常的開(kāi)發(fā)工作當(dāng)中,我們經(jīng)常需要用到日期相關(guān)的類(lèi),下面這篇文章主要給大家介紹了關(guān)于JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類(lèi)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
java中Date和Timestamp類(lèi)型的相互轉(zhuǎn)換方式
這篇文章主要介紹了java中Date和Timestamp類(lèi)型的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07

