java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java枚举类型参数校验

Java自定义注解对枚举类型参数的校验方法

作者:中文很快乐

文章介绍了如何使用Java注解对枚举类型参数进行校验,通过自定义注解和注解校验类实现参数的灵活性校验,感兴趣的朋友一起看看吧

1.前提准备条件

java注解了解https://www.jb51.net/program/287468xs5.htm

1.1 pom.xml文件依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.8-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.knife4j</groupId>
    <artifactId>MyKnife4jDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MyKnife4jDemo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.github.xiaoymin</groupId>
                <artifactId>knife4j-dependencies</artifactId>
                <version>4.5.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>8.0.0.Final</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>nexus-maven</id>
            <name>nexus-maven</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        </repository>
    </repositories>
</project>

1.2 枚举类:

@Getter
@AllArgsConstructor
public enum RoleEnum {
    ADMIN("A", "Administrator"),
    USER("U", "User"),
    GUEST("G", "Guest");
    private final String code;
    private final String name;
    public static RoleEnum fromCode(String code) {
        for (RoleEnum role : RoleEnum.values()) {
            if (role.getCode().equals(code)) {
                return role;
            }
        }
        throw new IllegalArgumentException("Unknown code: " + code);
    }
}

1.3 controller接口:

@RequestMapping("/user")
@RestController
@Tag(name = "用户控制类")
public class UserController {
    @PostMapping("/add")
    @Operation(description = "添加数据")
    public UserDTO validCreate(@RequestBody @Valid UserDTO userDTO) {
        return userDTO;
    }
}

1.4 实体参数:

@NoArgsConstructor
@AllArgsConstructor
@Data
@Schema(description = "用户新增--DTO")
public class UserDTO {
    @Schema(description = "用户名")
    @NotBlank(message = "用户名不能为空")
    private String userName;
    @Schema(description = "用户编号")
    @NotBlank(message = "用户编号不能为空")
    private String userNo;
    @Schema(description = "角色编码")
    private String roleCode;
}

1.5 knife4j的配置

我是结合Knife4j来使用的,knife4j的详细了解使用如下链接:

knife4j的配置如下:

@Configuration
@EnableKnife4j
public class Knife4jConfig {
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("knife4j-openapi3入门测试")
                        .version("1.0")
                        .description("knife4j-openapi3项目的接口文档"));
    }
    @Bean
    public GroupedOpenApi userAPI() {
        return GroupedOpenApi.builder().group("用户信息管理").
                pathsToMatch("/user/**").
                build();
    }
}

2.实现要求

希望对参数UserDTO中的字段roleCode进行自动校验,校验roleCode参数必须且只能是枚举类中的编码的其中一个。通过注解的方式实现,最大程度上提高参数的灵活性。

3.实现步骤

3.1 自定义注解类:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumCodeValidator.class)
public @interface ValidEnumCode {
    String message() default "must be any of enum {enumClass} codes";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    Class<? extends Enum<?>> enumClass();
}

3.2 使用注解:

在字段roleCode上添加自定义注解:

@NoArgsConstructor
@AllArgsConstructor
@Data
@Schema(description = "用户新增--DTO")
public class UserDTO {
    @Schema(description = "用户名")
    @NotBlank(message = "用户名不能为空", groups = {Create.class})
    private String userName;
    @Schema(description = "用户编号")
    @NotBlank(message = "用户编号不能为空", groups = {Update.class})
    private String userNo;
    @Schema(description = "角色编码")
    @ValidEnumCode(enumClass = RoleEnum.class,message = "Role code must be any of {codes} from {enumClass}")
    private String roleCode;
}

3.3  添加注解校验类:

public class EnumCodeValidator implements ConstraintValidator<ValidEnumCode, CharSequence> {
    private List<String> acceptedCodes;
    private String messageTemplate;
    private String enumClassName;
    @Override
    public void initialize(ValidEnumCode constraintAnnotation) {
        Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClass();
        acceptedCodes = Stream.of(enumClass.getEnumConstants())
                .map(this::getEnumCode)
                .collect(Collectors.toList());
        messageTemplate = constraintAnnotation.message();
        enumClassName = enumClass.getSimpleName();
    }
    private String getEnumCode(Enum<?> enumConstant) {
        try {
            Method getCodeMethod = enumConstant.getClass().getMethod("getCode");
            return (String) getCodeMethod.invoke(enumConstant);
        } catch (Exception e) {
            throw new RuntimeException("Failed to get enum code", e);
        }
    }
    @Override
    public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }
        if (!acceptedCodes.contains(value.toString())) {
            String message = messageTemplate.replace("{enumClass}", enumClassName)
                    .replace("{codes}", String.join(", ", acceptedCodes));
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(message)
                    .addConstraintViolation();
            return false;
        }
        return true;
    }
}

3.4 启动测试

若我传的参数如下则不通过:

后端控制台也会打印出如下提示:

若我按要求传参数,就能得到正确的结果:

4.扩展

根据我在pom中引入的参数校验依赖:hibernate-validator,

找到扩展依赖中的如下两个依赖,查看其他的可用的参数校验注解:

打开之后,根据下述提示找到可使用的注解,自己可测试使用哦

嗯,完结了,希望大家能多多对我提出点建议。

到此这篇关于Java自定义注解对枚举类型参数的校验的文章就介绍到这了,更多相关java枚举类型参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文