目录
1.前提准备条件
1.1 pom.xml文件依赖:
1.2 枚举类:
1.3 controller接口:
1.4 实体参数:
1.5 knife4j的配置
2.实现要求
3.实现步骤
3.1 自定义注解类:
3.2 使用注解:
3.3 添加注解校验类:
3.4 启动测试
4.扩展
1.前提准备条件
了解注解是什么以及怎样创建注解,大家可以查看这篇文章:java注解了解-CSDN博客https://blog.csdn.net/weixin_57259781/article/details/144827277?spm=1001.2014.3001.5502
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,
找到扩展依赖中的如下两个依赖,查看其他的可用的参数校验注解:
打开之后,根据下述提示找到可使用的注解,自己可测试使用哦
嗯,完结了,希望大家能多多对我提出点建议。