java Copy code
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;
import java.util.List;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface NotEmpty {
String fieldName() default "";
String message() default "";
}
class FieldEmptyException extends RuntimeException {
public FieldEmptyException(String message) {
super(message);
}
}
class Validator {
public static void validate(Object obj) throws IllegalAccessException {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(NotEmpty.class)) {
field.setAccessible(true);
Object fieldValue = field.get(obj);
if (fieldValue == null || isEmptyList(fieldValue)) {
NotEmpty annotation = field.getAnnotation(NotEmpty.class);
String fieldName = annotation.fieldName();
String message = annotation.message();
if (message.isEmpty()) {
message = fieldName + " cannot be null.";
}
throw new FieldEmptyException(message);
} else if (fieldValue instanceof List) {
List> listValue = (List>) fieldValue;
if (listValue.isEmpty()) {
NotEmpty annotation = field.getAnnotation(NotEmpty.class);
String fieldName = annotation.fieldName();
String message = annotation.message();
if (message.isEmpty()) {
message = "The list in " + fieldName + " cannot be empty.";
}
throw new FieldEmptyException(message);
} else {
for (Object item : listValue) {
validate(item); // 递归遍历列表中的元素进行校验
}
}
} else {
validate(fieldValue); // 递归处理其他类型的字段对象进行校验
}
}
}
}
private static boolean isEmptyList(Object obj) {
return obj instanceof List && ((List>) obj).isEmpty();
}
}
class UserDTO {
@NotEmpty(fieldName = "Username", message = "Please provide a valid username.")
private String username;
@NotEmpty(fieldName = "Email")
private String email;
@NotEmpty(fieldName = "Roles")
private List
@NotEmpty(fieldName = "Address")
private AddressDTO address;
// 省略其他字段和构造方法
// getter和setter方法
}
class AddressDTO {
@NotEmpty(fieldName = "Street")
private String street;
@NotEmpty(fieldName = "City")
private String city;
// 省略其他字段和构造方法
// getter和setter方法
}
public class Main {
public static void main(String[] args) {
UserDTO user1 = new UserDTO();
user1.setUsername("John");
user1.setEmail("");
user1.setRoles(List.of());
user1.setAddress(new AddressDTO());
try {
validateUser(user1);
System.out.println("User 1 is valid.");
} catch (FieldEmptyException e) {
System.out.println("Validation failed: " + e.getMessage());
}
UserDTO user2 = new UserDTO();
user2.setUsername("Alice");
user2.setEmail("[email protected]");
user2.setRoles(List.of("admin"));
AddressDTO address = new AddressDTO();
address.setStreet("");
user2.setAddress(address);
try {
validateUser(user2);
System.out.println("User 2 is valid.");
} catch (FieldEmptyException e) {
System.out.println("Validation failed: " + e.getMessage());
}
}
public static void validateUser(@Validate UserDTO user) {
try {
Validator.validate(user);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
在上面的代码示例中,我们使用了自定义注解 @NotEmpty 来标记需要进行非空校验的字段,在 Validator 类中实现了验证逻辑。UserDTO 和 AddressDTO 类分别表示用户和地址的数据传输对象,包含需要进行验证的字段,并通过 getter 和 setter 方法暴露给外部调用。
在 Main 类中,我们创建了两个用户对象 user1 和 user2 作为测试数据,并使用 validateUser() 方法来触发对象的非空校验,根据结果输出相应的信息。
请注意,代码示例中最后的 validateUser() 方法使用了 @Validate 注解,这是一种自定义的注解,用于标记需要进行验证
上面的@Validate注解方法怎么实现呢
在前面的代码示例中,我使用了 @Validate 注解来标记需要进行验证的方法。这是一个自定义的注解,可以通过反射机制来获取并执行相应的验证逻辑。以下是添加 @Validate 注解的方式:
创建自定义注解 @Validate,用于标记需要进行验证的方法。
java
Copy code
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Validate {
}
修改 UserDTO 类,在需要进行验证的方法上添加 @Validate 注解。
java
Copy code
class UserDTO {
private String username;
private String email;
private List
private AddressDTO address;
// 省略其他字段和构造方法
@Validate
public void validate() {
// 执行验证逻辑
Validator.validate(this);
}
// getter和setter方法
}
在 Main 类中修改 validateUser() 方法,用于调用带有 @Validate 注解的验证方法。
java
Copy code
public class Main {
public static void main(String[] args) {
UserDTO user1 = new UserDTO();
user1.setUsername("John");
user1.setEmail("");
user1.setRoles(List.of());
user1.setAddress(new AddressDTO());
try {
user1.validate();
System.out.println("User 1 is valid.");
} catch (FieldEmptyException e) {
System.out.println("Validation failed: " + e.getMessage());
}
UserDTO user2 = new UserDTO();
user2.setUsername("Alice");
user2.setEmail("[email protected]");
user2.setRoles(List.of("admin"));
AddressDTO address = new AddressDTO();
address.setStreet("");
user2.setAddress(address);
try {
user2.validate();
System.out.println("User 2 is valid.");
} catch (FieldEmptyException e) {
System.out.println("Validation failed: " + e.getMessage());
}
}
}
在上述的代码示例中,将 validate() 方法添加到 UserDTO 类中,并在方法上添加了 @Validate 注解。然后,在 Main 类中调用 user1.validate() 和 user2.validate() 来触发对象的验证逻辑。
这样,当调用带有 @Validate 注解的验证方法时,会执行 Validator.validate(this),其中 this 表示当前对象,即 UserDTO 对象。通过这种方式,可以在对象级别实现验证逻辑,并在需要验证的地方进行调用。