SpringMVC數(shù)據(jù)校驗(yàn)+VO++脫敏實(shí)戰(zhàn)指南
概念引入
在Spring MVC中,數(shù)據(jù)校驗(yàn)是確保用戶輸入符合預(yù)期規(guī)則的重要環(huán)節(jié)
Spring MVC通過整合 Bean Validation 規(guī)范,提供了靈活的數(shù)據(jù)校驗(yàn)機(jī)制。核心步驟包括:
- 在Java Bean中添加校驗(yàn)注解。
- 在Controller中使用
@Valid
或@Validated
觸發(fā)校驗(yàn)。 - 通過
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中編寫校驗(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)不通過,方法通知執(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)方案
編寫一個(gè)全局異常處理器處理(MethodArgumentNotValidException 校驗(yàn)時(shí)出現(xiàn)的錯(cuò)誤,同時(shí)返回校驗(yàn)出錯(cuò)的信息)
1 沒寫全局校驗(yàn)時(shí):
2 寫了全局校驗(yàn)后:
3 編寫過程:
代碼實(shí)現(xiàn):(出現(xiàn)校驗(yàn)錯(cuò)誤就會(huì)報(bào)錯(cuò),我們將這個(gè)錯(cuò)誤的方法進(jìn)行封裝,達(dá)到全局的效果)
//寫一個(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)建需要的注解
完善類中的內(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 將注解類中Constrain注解中的參數(shù)方法補(bǔ)充
創(chuàng)建這個(gè)類:
將類中的需求寫上:
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ù)需求填寫不同的語言版本)
2 在變量千指定
//實(shí)現(xiàn)國(guó)際化配置 @Gender(message = "{gender.message}") private String gender;
3 在資源包的file文件中填寫數(shù)據(jù)
可能需要調(diào)整編碼
填寫
實(shí)際應(yīng)用:
核心:
五 解決不同需求使用變量的不同校驗(yàn)-VO
VO層(View Object/Value Object)在實(shí)際開發(fā)中的作用
VO層是分層架構(gòu)中的核心組件之一,主要用于前端與后端的數(shù)據(jù)交互,其核心作用如下:
1 為了添加數(shù)據(jù)而準(zhǔn)備的VO類
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類
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)是指通過技術(shù)手段對(duì)敏感信息進(jìn)行處理,使其在不影響業(yè)務(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)文章
自定義Jackson的ObjectMapper如何實(shí)現(xiàn)@ResponseBody的自定義渲染
這篇文章主要介紹了自定義Jackson的ObjectMapper如何實(shí)現(xiàn)@ResponseBody的自定義渲染,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07java中對(duì)list分頁并顯示數(shù)據(jù)到頁面實(shí)例代碼
這篇文章主要介紹了java中對(duì)list分頁并顯示數(shù)據(jù)到頁面實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類
在日常的開發(fā)工作當(dāng)中,我們經(jīng)常需要用到日期相關(guān)的類,下面這篇文章主要給大家介紹了關(guān)于JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09java中Date和Timestamp類型的相互轉(zhuǎn)換方式
這篇文章主要介紹了java中Date和Timestamp類型的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07