一、实现的功能(对象多级嵌套对象)
- 属性不能为空(什么校验都行)
- 当某个属性是一个特殊值时,另一个属性不能为空。
二、使用的知识点
自定义注解(标识),反射,递归(多层对象遍历)
三、代码(类似于List 属性的,需判断下处理,见文章最后)
public class People {
@NotNull(errorMsg = "姓名不能为空")
private String name;
private Integer age;
@NotNull(errorMsg = "携带的物品不能为空")
private Goods goods;
//1 男 2女
@Condition(errorMsg = "条件",ifCondition = true,constraintAttributes="flower",constraintValue = "1")
private String sex;
public static void main(String[] args) {
ICheck check = new Check();
Goods goods = new Goods();
//goods.setFlower("玫瑰");
goods.setClothes("干净的衣服");
People man = new People("张三",25,goods,"1");
check.doCheck(man);
People woman = new People("",25,goods,"1");
}
public People(String name, Integer age, Goods goods, String sex) {
this.name = name;
this.age = age;
this.goods = goods;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public class Goods {
//如果是男人则不能为空
@Condition(errorMsg = "男人必须带着鲜花")
private String flower;
@NotNull(errorMsg = "衣服不能为空")
private String clothes;
private String car;
public String getFlower() {
return flower;
}
public void setFlower(String flower) {
this.flower = flower;
}
public String getClothes() {
return clothes;
}
public void setClothes(String clothes) {
this.clothes = clothes;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Condition {
String errorMsg() default "";
//是否是约束条件
boolean ifCondition() default false;
//约束方的属性名 用于找到被约束的属性
String constraintAttributes() default "";
//条件的值 根据实际项目确定 也可以多加个类型
String constraintValue() default "";
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NotNull {
String errorMsg();
}
public interface ICheck {
void doCheck(Object obj);
}
public class Check implements ICheck {
List<String> keys = new ArrayList<>();
Map<String,Map<String,Object>> attributeMap = new HashMap<>();
@Override
public void doCheck(Object obj) {
final Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
//记录下条件语句
if(declaredField.isAnnotationPresent(Condition.class)){
dealCondition(declaredField,obj);
}
if (ICheck.class.isAssignableFrom(declaredField.getType()) || declaredField.isAnnotationPresent(NotNull.class)) {
declaredField.setAccessible(true);
deepCheck(declaredField,obj);
}
}
//最终比对
equCondition();
}
//解决字符串类型为"" 以及里面得属性再校验 递归一下
private void deepCheck(Field declaredField,Object obj) {
try {
final Object declaredFieldValue = declaredField.get(obj);
if (declaredFieldValue instanceof ICheck) {
((ICheck) declaredFieldValue).doCheck(obj);
return;
}
if (declaredFieldValue == null||(declaredField.getType().isAssignableFrom(String.class) && "".equals(declaredFieldValue))) {
final NotNull notNull = declaredField.getAnnotation(NotNull.class);
final String errorMsg = notNull.errorMsg();
throw new IllegalArgumentException(errorMsg);
}
//再处理一下里面的属性
doCheck(declaredFieldValue);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void dealCondition(Field declaredField,Object obj){
//declaredFields
final Condition condition = declaredField.getAnnotation(Condition.class);
if(condition.ifCondition()){
//是条件
String attributes = condition.constraintAttributes();
//条件的值
String constraintValue = condition.constraintValue();
try {
//真实的值
final String declaredFieldValue = (String)declaredField.get(obj);
//条件的值和真实的值对比一下 如果满足 再去约束后面的值
if(constraintValue.equals(declaredFieldValue)){
keys.add(attributes);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}else{
Map<String,Object> map = new HashMap<>();
//是被约束的
String name = declaredField.getName();
try {
final Object declaredFieldValue = declaredField.get(obj);
map.put("value",declaredFieldValue);
map.put("errorMsg",condition.errorMsg());
attributeMap.put(name,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private void equCondition(){
keys.forEach(key->{
Map<String, Object> map = attributeMap.get(key);
if(map.get("value")==null){
throw new IllegalArgumentException(map.get("errorMsg").toString());
}
});
}
}
补充(如果有特殊属性就这么处理一下)
//处理一下list属性
if(declaredField.getType().isAssignableFrom(List.class)){
List list = (List) declaredFieldValue;
list.forEach(o->{
//再处理一下里面的属性
doCheck(o);
});
}else{
//再处理一下里面的属性
doCheck(declaredFieldValue);
}