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

 更新时间:2025年01月02日 12:06:56   作者:中文很快乐  
文章介绍了如何使用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枚举类型参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Storm框架整合springboot的方法

    Storm框架整合springboot的方法

    Storm框架中的每个Spout和Bolt都相当于独立的应用,Strom在启动spout和bolt时提供了一个open方法(spout)和prepare方法(bolt)。这篇文章主要介绍了Storm框架整合springboot的方法,需要的朋友可以参考下
    2018-11-11
  • jcrop 网页截图工具(插件)开发

    jcrop 网页截图工具(插件)开发

    今天给大家介绍一下一个web 中经常会用到的截图(如:头像等)工具,需要的朋友可以了解下
    2012-11-11
  • Java scala模式匹配机制详解

    Java scala模式匹配机制详解

    模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断
    2023-02-02
  • 解读String字符串拼接的原理

    解读String字符串拼接的原理

    这篇文章主要介绍了关于String字符串拼接的原理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Mybatis-Plus最优化持久层开发过程

    Mybatis-Plus最优化持久层开发过程

    Mybatis-plus(简称MP)是一个Mybatis的增强工具,在mybatis的基础上只做增强不做改变,提高效率,自动生成单表的CRUD功能,这篇文章主要介绍了Mybatis-Plus最优化持久层开发,需要的朋友可以参考下
    2024-07-07
  • Java探索之Feign入门使用详解

    Java探索之Feign入门使用详解

    这篇文章主要介绍了Java探索之Feign入门使用详解,关于feign,我也是第一次遇到,于是在网上搜集了相关文章,这篇比较详细,介绍了其简介,选择feign的原因以及其他相关内容,需要的朋友可以参考下。
    2017-10-10
  • MyBatis-Plus内置接口方法的具体使用

    MyBatis-Plus内置接口方法的具体使用

    java开发应用程序与数据库交互使用比较多的就是mybatisPlus接口,本文主要介绍了MyBatis-Plus内置接口方法的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • Eclipse可视化插件WindowBuilder的安装方法

    Eclipse可视化插件WindowBuilder的安装方法

    这篇文章主要介绍了Eclipse可视化插件WindowBuilder的安装方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • JPA的多表复杂查询的方法示例

    JPA的多表复杂查询的方法示例

    这篇文章主要介绍了JPA的多表复杂查询的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • java.lang.NullPointerException 如何处理空指针异常的实现

    java.lang.NullPointerException 如何处理空指针异常的实现

    这篇文章主要介绍了java.lang.NullPointerException 如何处理空指针异常的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12

最新评论