SpringBoot接口参数校验(jakarta.validation.constraints)

一.引入pom

        <!-- validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

二.定义实体

注意:存在实体嵌套的时候要在对象类型属性加@Valid注解,否则嵌套实体定义的校验注解不生效

1.定义DTO

package com.example.redission.entity;
import com.example.redission.annotation.LegalEnum;
import com.example.redission.enums.ScopeEnum;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;

/**
 * @version 1.0
 * @date 2024/5/13
 * @description
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class WelcomeDto {
    private String id;

    @NotBlank(message = "标题不能为空")
    private String name;

    @NotBlank(message = "范围不能为空")
    @LegalEnum(value = ScopeEnum.class, message = "范围枚举值不合法")
    private String scope;

    @Valid
    @Size(max = 5, message = "User不能超过5个")
    private List<User> userList;
}

2.User

package com.example.redission.entity;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * @author  土
 * @version 1.0
 * @date 2024/5/15
 * @description
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    @NotBlank(message = "标题不能为空")
    private String name;
    @Valid
    @Size(max = 5, message = "Address不能超过5个")
    @NotNull
    private List<Address> addressList;
}

3.Address

package com.example.redission.entity;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author OP0345
 * @version 1.0
 * @date 2024/5/15
 * @description  
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Address {
    @NotBlank(message = "省份不能为空")
    private String province;
}

三.定义枚举类

package com.example.redission.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.stream.Stream;

@Getter
@AllArgsConstructor
public enum ScopeEnum {
    ALL_USER("all", "全部企微号"),
    TAG("tag", "指定层级"),
    SOME_USER("some", "指定企微号");

    private final String type;
    private final String desc;
    public static ScopeEnum findBy(String value) {
        return Stream.of(ScopeEnum.values())
                .filter(item -> item.getType().equals(value))
                .findFirst()
                .orElse(null);
    }
}

四.自定义枚举参数校验注解

package com.example.redission.annotation;


import jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import jakarta.validation.Payload;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

/**
 * 枚举类型校验
 *
 * @author :
 */
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = LegalEnum.EnumValidator.class)
public @interface LegalEnum {

    String message() default "无效的枚举值";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    Class<? extends Enum<?>> value();

    class EnumValidator implements ConstraintValidator<LegalEnum, Object> {

        private Class enumClass;

        @Override
        public void initialize(LegalEnum constraintAnnotation) {
            this.enumClass = constraintAnnotation.value();
        }

        @Override
        public boolean isValid(Object value, ConstraintValidatorContext context) {
            if (value == null) {
                return false;
            }
            if (!enumClass.isEnum()) {
                throw new IllegalArgumentException(enumClass.getSimpleName() + " is not an enum type");
            }
            try {
            	//基于type属性
                Field field = enumClass.getDeclaredField("type");
                field.setAccessible(true);
                Object[] enumConstants = enumClass.getEnumConstants();
                for (Object enumConstant : enumConstants) {
                    Object fieldValue = field.get(enumConstant);
                    if (fieldValue != null && fieldValue.equals(value)) {
                        return true;
                    }
                }
                return false;
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException("Error validating enum", e);
            }
        }
    }

}

五.controller接口验证

package com.example.redission.controller;

import com.example.redission.annotation.RateLimit;
import com.example.redission.entity.WelcomeDto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @author 土
 * @version 1.0
 * @description controller
 */
@RestController
@RequestMapping("/hello")
@Slf4j
@RequiredArgsConstructor
@Validated
public class ApiController {
    //    @RedisLock(key = "'lock_' + #str")
    @GetMapping(value = "say", produces = MediaType.APPLICATION_JSON_VALUE)
    public String send(@RequestParam(name = "str") @NotNull @NotBlank(message = "str必输") String str) {
        return str;
    }

    @PostMapping(value = "addOne", produces = MediaType.APPLICATION_JSON_VALUE)
    public String addOne(@Validated @RequestBody WelcomeDto dto) {
        System.out.println("进来了");
        return dto.getName();
    }
}

<think>嗯,用户想了解Java中各种注解的作用,特别是Lombok、验证、Swagger、数据转换等方面的。首先,我需要回忆一下Lombok的常用注解,比如@Data、@Getter、@Setter这些,它们能自动生成代码,减少样板代码。然后,用户提到的jakarta.validation中的@NotEmpty和@NotNull,这些用于参数校验,确保数据有效性。 接下来是Swagger相关的注解,比如@Schema,用来生成API文档,描述模型属性。还有DictFormat和DictConvert,这些可能属于自定义注解,用于数据字典的转换,比如将编码转成文字。ExcelProperty和DateTimeFormat可能跟EasyExcel库相关,处理Excel导入导出时的列映射和日期格式。 然后,LocalDateTime和PageParam可能是用户自定义的类型或注解,需要解释它们的用途。比如PageParam用于分页查询参数。在组织回答时,需要分门别类,把Lombok、验证、Swagger、数据转换等部分分开说明,每个注解给出简洁的作用说明,并附上示例代码。 还要注意用户提供的引用内容,引用1到4都是关于Lombok的@Data、@AllArgsConstructor和@NoArgsConstructor,所以需要重点覆盖这些。同时,用户的问题中还提到了其他注解,比如ToString、Builder、Jakarta Validation的注解,这些也要涵盖进去,确保全面性。 可能用户是在开发Spring Boot应用,使用了Lombok简化实体类,结合Swagger生成API文档,用验证注解做参数校验,以及处理Excel导入导出和数据字典转换。需要确保解释清晰,每个注解的用途和常见使用场景,让用户能够理解如何在自己的项目中应用这些注解。 最后,生成的相关问题要围绕这些注解的扩展使用,比如组合注解的最佳实践、验证注解的其他选项、Swagger的更多用法等,帮助用户深入学习和解决问题。</think># Java注解使用说明及作用详解 ## 一、Lombok注解 ### 1. 代码生成类 - `@Data`:组合注解,自动生成`getter/setter`、`toString()`、`equals()`、`hashCode()`方法[^2][^3] ```java @Data // 等价于@Getter + @Setter + @ToString + @EqualsAndHashCode public class User { private String username; private Integer age; } ``` - `@Getter`/`@Setter`:生成字段的访问器/修改器 - `@NoArgsConstructor`:生成无参构造函数[^1] ```java @NoArgsConstructor // 生成 public User() {} public class User {} ``` - `@AllArgsConstructor`:生成全参构造函数[^4] ```java @AllArgsConstructor // 生成 public User(String username, Integer age) {...} public class User {} ``` - `@Builder`:生成建造者模式构造器 ```java User.builder().username("test").age(18).build(); ``` ### 2. 方法控制类 - `@ToString`:覆盖`toString()`方法 - `@EqualsAndHashCode`:生成`equals()`和`hashCode()`方法 ## 二、验证注解(jakarta.validation) ### 1. 空值校验 - `@NotEmpty`:验证字符串/集合非空 - `@NotNull`:验证对象引用不为null ```java public class LoginDTO { @NotEmpty(message = "用户名不能为空") private String username; @NotNull(message = "密码强度不能为空") private PasswordLevel level; } ``` ### 2. 范围校验 - `@Size`:验证字符串/集合长度 - `@Min`/`@Max`:数值范围校验 - `@Pattern`:正则表达式校验 ## 三、Swagger注解 ### 1. 接口文档 - `@Schema`:描述模型属性/参数 ```java @Schema(description = "用户登录请求体") public class LoginRequest { @Schema(description = "用户名", example = "admin") private String username; } ``` ### 2. 接口标注 - `@Operation`:描述接口操作 - `@Parameter`:描述接口参数 ## 四、数据转换注解 ### 1. 字典转换 - `@DictFormat`:标注字典编码字段 - `@DictConvert`:自动转换编码为文字 ```java @DictFormat(dictType = "user_status") private Integer status; // 1->启用, 0->禁用 ``` ### 2. Excel处理 - `@ExcelProperty`:定义Excel列映射 ```java @ExcelProperty("用户姓名") private String name; ``` ### 3. 时间格式 - `@DateTimeFormat`:定义时间格式 ```java @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; ``` ## 五、其他实用注解 ### 1. 分页参数 - `@PageParam`:自定义分页参数注解 ```java public Page<User> queryUsers(@PageParam Pageable pageable) { // 分页查询逻辑 } ``` ### 2. 时间类型 - `LocalDateTime`:Java8日期时间类型 ```java private LocalDateTime createTime = LocalDateTime.now(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值