@valid分组校验,手动触发valid校验

业务场景:同一个接口,不同的操作的时候,校验的字段是不同的。比如更改状态,对于请假申请审批和撤销,校验的字段不同的时候。
但是呢,常规的通过@valid的注解是无法满足的(请求的时候参数拦截,触发校验规则)。而我的业务场景必须进行手动触发@valid校验

废话不多说,下面直接展示思路与核心相关代码

1.设计思路

本质来说,常规@Valid不满足需求的原因就是:
1.同一个接口,根据type字段来进行触发不同的分组字段校验;
2.手动触发valid分组校验。
补充:我所说的常规@valid是指@Validated(value = {People.Student.class}),代码如下:

    /**
     * <p>@Description: 请求拦截-根据分组进行参数校验 </p >
     * <p>@param [people]</p >
     * <p>@return com.lzq.learn.domain.CommonResult</p >
     * <p>@throws </p >
     * <p>@date 14:37 14:37</p >
     */
    @PostMapping("validByGroup")
    public CommonResult validByGroup(@RequestBody @Validated(value = {People.Student.class}) People people) {
        System.out.println("People 参数:" + people);
        CommonResult commonResult = CommonResult.success(people);
        return commonResult;
    }

2.完整代码展示

2.1 controller代码

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.lzq.learn.domain.CommonResult;
import com.lzq.learn.domain.People;
import com.lzq.learn.domain.User;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.*;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("valid")
public class TestValidController {


    @Autowired
    private Validator validator;

    /**
     * <p>@Description: 测试手动触发valid分组校验</p >
     * <p>@param [userList]</p >
     * <p>@return com.lzq.learn.domain.CommonResult</p >
     * <p>@throws </p >
     * <p>@date 15:21 15:21</p >
     */
    @PostMapping("validByHand")
    public CommonResult validByHand(@RequestBody People people) {
        System.out.println("people  参数:" + people);
        String validResult = "";
        List<Class> groupList = CollUtil.newArrayList(Default.class);
        if (StrUtil.equals("student", people.getType())) {
            groupList.add(People.Student.class);
        }
        if (StrUtil.equals("teacher", people.getType())) {
            groupList.add(People.Teacher.class);
        }
        Class[] groupArray = groupList.toArray(new Class[groupList.size()]);
        // 写法1:使用ValidatorFactory 获取Validator对象
        Set<ConstraintViolation<People>> violations = Validation.buildDefaultValidatorFactory().getValidator().validate(people, groupArray);
        // 写法2:从springboot上下文 获取Validator对象
        // Set<ConstraintViolation<People>> violations = validator.validate(people, groupArray);
        validResult = getResultFromValidate(violations);
        CommonResult commonResult = CommonResult.success(validResult);
        return commonResult;
    }


    /**
     * <p>@Description: 对于valid校验结果进行转换结果</p >
     * <p>@param </p >
     * <p>@return </p >
     * <p>@throws </p >
     * <p>@date 13:43 13:43</p >
     */
    public static <T> String getResultFromValidate(Set<ConstraintViolation<T>> violations) {
        if (CollUtil.isEmpty(violations)) {
            return "pass";
        }
        StringBuilder sb = new StringBuilder();
        for (ConstraintViolation<T> violation : violations) {
            sb.append(violation.getPropertyPath()).append(": ").append(violation.getMessage()).append("\n");
        }
        return sb.toString();
    }
    
}

注意:我们需要手动触发,则在controller的接口中,不能加上@valid(或@validated)注解,不然又会走请求拦截,根本走不到我们的controller代码中!

2.2 实体类People代码


import lombok.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * @author x
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class People implements Serializable {

    /**     自定义校验分组        **/
    public interface Student{}
    public interface Teacher{}

    private Long id;

    @NotNull(message = "年龄不能为空")
    private Integer age;

    @NotBlank(message = "个人名称不能为空")
    private String myName;

    @NotBlank(message = "学生名称不能为空", groups = Student.class)
    private String studentName;

    @NotBlank(message = "教师名称不能为空", groups = Teacher.class)
    private String teacherName;

    // dto 字段
    private String type;
}

注意:对于本实体类来说,age和myName字段没有指定分组,其实它们两个被指定到了Default.class分组(javax.validation.groups.Default)

3.postMan接口测试

为了简要概述,本文只针对于type=student的情况进行测试分析,按照上述代码,当type=student的时候,会进行Default和Student的分组校验,如下图postman接口测试

3.1 type=student,不传default分组字段

在这里插入图片描述

3.1 type=student,不传student分组字段

在这里插入图片描述

3.1 type=student,不传teacher分组字段

在这里插入图片描述

3.1 type=student,全部分组字段都传

在这里插入图片描述

如图,发现我们编写的代码是正确的,实现了在任意代码执行顺序中,根据type来进行自定义分组校验。但是controller接口一定不要加@valid或@validated注解,不然请求会被拦截,根本走不到我们的自定义方法处。

本博客也只是更改了valid参数校验的执行时机,其实上述代码只是提供最基本的解决方案,后续可以优化为在方法上加上自定义注解,实现aop参数校验拦截!抽象出来这种行为,避免重复的if else代码冗余。

@valid注解通常用在Java的Spring框架中,它是用于请求体的数据校验。通过在方法参数前加上@valid注解,Spring会自动校验方法参数所对应的对象,如果校验不通过,则会抛出一系列的校验异常。当需要对表情包进行校验时,可以通过定义一个DTO(Data Transfer Object)类,并使用JSR-303提供的校验注解来定义校验规则。例如,可以为表情包的大小、格式、是否包含敏感信息等定义规则。 这里是一个简单的例子,展示如何为一个假设的表情包对象定义校验规则: ```java import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; public class EmojiPackageDTO { @NotNull(message = "表情包不能为空") @Size(min = 1, max = 10, message = "表情包的尺寸应在1到10之间") private String name; @Min(value = 1, message = "表情包至少包含1个表情") @Max(value = 100, message = "表情包最多包含100个表情") private Integer size; // 其他与表情包相关的属性和校验规则 // getters and setters } ``` 在处理请求的方法中,可以这样使用@valid注解: ```java @RestController public class EmojiController { @PostMapping("/upload-emoji") public ResponseEntity<String> uploadEmoji(@Valid @RequestBody EmojiPackageDTO emojiPackage) { // 处理上传的表情包 return ResponseEntity.ok("表情包上传成功"); } } ``` 如果表情包的数据不满足上面定义的规则,比如为空、尺寸不在指定范围内或者包含不合法的表情等,Spring就会进行拦截,并返回相应的错误信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值