SpringMVC(七)数据校验+VO++脱敏

目录

[一 基础原理](#一 基础原理)

[1 先将数据校验的依赖导入](#1 先将数据校验的依赖导入)

[2 在JavaBean中编写校验注解](#2 在JavaBean中编写校验注解)

[3 使用@Valid告诉SpringMVC进行校验(校验不通过,方法通知执行)](#3 使用@Valid告诉SpringMVC进行校验(校验不通过,方法通知执行))

[4 在@Valid参数后面加上一个BindingResult参数,获取校验结果。](#4 在@Valid参数后面加上一个BindingResult参数,获取校验结果。)

[二 改进方案](#二 改进方案)

[1 没写全局校验时:](#1 没写全局校验时:)

[2 写了全局校验后:](#2 写了全局校验后:)

[3 编写过程:](#3 编写过程:)

[三 自定义校验注解-校验注解绑定校验器](#三 自定义校验注解-校验注解绑定校验器)

[1 创建需要的注解](#1 创建需要的注解)

[2 将注解类中Constrain注解中的参数方法补充](#2 将注解类中Constrain注解中的参数方法补充)

[3 在指定的参数加上校验注解](#3 在指定的参数加上校验注解)

[4 运行结果:](#4 运行结果:)

[四 拓展知识点-配置文件中获取](#四 拓展知识点-配置文件中获取)

[1 在资源包中新建file文件(可以根据需求填写不同的语言版本)](#1 在资源包中新建file文件(可以根据需求填写不同的语言版本))

[2 在变量千指定](#2 在变量千指定)

[3 在资源包的file文件中填写数据](#3 在资源包的file文件中填写数据)

[五 解决不同需求使用变量的不同校验-VO](#五 解决不同需求使用变量的不同校验-VO)

[1 为了添加数据而准备的VO类](#1 为了添加数据而准备的VO类)

[2 为了修改数据所添加的VO类](#2 为了修改数据所添加的VO类)

[3 Controller层的业务修改](#3 Controller层的业务修改)

[六 实现脱敏操作](#六 实现脱敏操作)


概念引入

在Spring MVC中,数据校验是确保用户输入符合预期规则的重要环节

Spring MVC通过整合 Bean Validation 规范,提供了灵活的数据校验机制。核心步骤包括:

  1. 在Java Bean中添加校验注解。

  2. 在Controller中使用@Valid@Validated触发校验。

  3. 通过BindingResult或全局异常处理捕获错误。

  4. 可选扩展:分组校验、自定义注解、国际化消息。

一 基础原理

1 先将数据校验的依赖导入

XML 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

2 在JavaBean中编写校验注解

java 复制代码
    @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;
java 复制代码
    // 正则表达式
    @Pattern(regexp = "^男|女$", message = "性别只能是男或女")
    private String gender;

3 使用@Valid告诉SpringMVC进行校验(校验不通过,方法通知执行)

java 复制代码
    // 添加员工,前端发送请求,把 json 数据封装到 Employee 对象中
    @PostMapping(value = "/employee")
    public R add(@RequestBody @Valid Employee employee) {
        employeeService.addEmployee(employee);
        return R.ok();
    }

4 在@Valid参数后面加上一个BindingResult参数,获取校验结果。

可以进行反馈

java 复制代码
    // 添加员工,前端发送请求,把 json 数据封装到 Employee 对象中
    @PostMapping(value = "/employee")
    public R add(@RequestBody @Valid Employee employee, BindingResult bindingResult) {
        // 校验正确
        if (!bindingResult.hasErrors()) {
            employeeService.addEmployee(employee);
            return R.ok();
        }
        Map<String, Object> errorMap = new HashMap<>();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            //获取属性名
            String field = fieldError.getField();
            //获取错误信息描述
            String message = fieldError.getDefaultMessage();
            errorMap.put(field, message);
        }
        return R.error(500, "校验失败", errorMap);
    }

运行结果演示

二 改进方案

编写一个全局异常处理器处理(MethodArgumentNotValidException 校验时出现的错误,同时返回校验出错的信息)

1 没写全局校验时:

2 写了全局校验后:

3 编写过程:

代码实现:(出现校验错误就会报错,我们将这个错误的方法进行封装,达到全局的效果)

java 复制代码
    //写一个全局校验异常的处理(bindingResult中有校验错误的信息,现在我们将它存放到map集合当中进行遍历)
    @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();
            //获取错误信息描述
            String message = fieldError.getDefaultMessage();
            errorMap.put(field, message);
        }
        return R.error(500, "校验失败", errorMap);
    }

三 自定义校验注解-校验注解绑定校验器

1 创建需要的注解

完善类中的内容:

java 复制代码
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注解中的参数方法补充

创建这个类:

将类中的需求写上:

java 复制代码
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 在指定的参数加上校验注解

java 复制代码
    @Gender(message = "性别只能是男或女")
    private String gender;

4 运行结果:

四 拓展知识点-配置文件中获取

1 在资源包中新建file文件(可以根据需求填写不同的语言版本)

2 在变量千指定

java 复制代码
    //实现国际化配置
    @Gender(message = "{gender.message}")
    private String gender;

3 在资源包的file文件中填写数据

可能需要调整编码

填写

实际应用:

核心:

五 解决不同需求使用变量的不同校验-VO

VO层(View Object/Value Object)在实际开发中的作用

VO层是分层架构中的核心组件之一,主要用于前端与后端的数据交互,其核心作用如下:

1 为了添加数据而准备的VO类

java 复制代码
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 为了修改数据所添加的VO类

java 复制代码
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层的业务修改

java 复制代码
    // 添加员工,前端发送请求,把 json 数据封装到 Employee 对象中
    @PostMapping(value = "/employee")
    public R add(@RequestBody @Valid EmployeeAddVo employeeAddVo) {
        //把vo转为do(调用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();
    }

运行代码:

六 实现脱敏操作

数据脱敏 (Data Masking)是指通过技术手段对敏感信息进行处理,使其在不影响业务功能的前提下,无法被直接识别或还原为原始数据,从而保护用户隐私、防范数据泄露风险。

java 复制代码
    //查询所有员工
    @GetMapping(value = "/employees")
    public R all() {
        // 实现脱敏操作将年龄隐藏(返回给前端)
        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);
    }

脱敏成功:

相关推荐
小九没绝活11 分钟前
设计模式-原型模式
java·设计模式·原型模式
时雨h13 分钟前
微服务分层架构技术解析:从 API 到数据访问的全方位探秘
java·微服务·dubbo
pk_xz12345622 分钟前
使用 Flask 进行简单服务器改造的详细步骤和代码
服务器·python·flask
小咖拉眯25 分钟前
蓝桥杯进制问题秒破解法|冲击省一题单(二)
java·数据结构·算法·蓝桥杯
kkk16222451 小时前
C# Winform 实现换肤,并自定义皮肤功能
java·算法·c#
添砖Java中1 小时前
零基础掌握分布式ID生成:从理论到实战的完整指南 [特殊字符]
java·分布式·分布式id
不甘平凡--liang1 小时前
Linux Nginx安装部署、注册服务
linux·运维·服务器
龙仔7251 小时前
打造独一无二的 CI/CD 工厂:Java 应用的自动化之旅
java·spring cloud·ci/cd·自动化·devops
互联网搬砖老肖2 小时前
Python开发合并多个PDF文件
java·python·pdf