震惊!为了逃避判空小伙竟然
1.问题:
最近在做接口开发时,遇到了一个问题,如下代码
令人奇怪的是,此处就算前端或者接口文档中,没有传递参数,此处也不会进入这个判断,因为 userLoginRequest 对象并不为空,那么就产生疑问了? 是框架中的哪一部操作帮助我们 new 了一个对象出来呢?(七夕要到了!你 new 对象了吗)
带着疑问,我上网查询了一下,发现这与 SpringMvc 的@RequestBody 有关,那么查看源码后发现,是在这个方法中实现。 readWithMessageConverters
维护了一个 HttpMessageConverter 列表,如果其中某个 HttpMessageConverter 支持给定内容类型的请求体转换为类对象,就使用它读取请求体转换为类对象。
那么这样直接校验是否为空,看来是不可行的,但是如果要一个一个获取出来进行判断校验非空,又感觉很麻烦,那么有没有一种优雅一点的方式获取呢?
2.解决方式:
于是我使用反射的方式配合注解写了个工具类,用于判断参数是否为空,代码如下: package com.juzipi.utils;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; import java.util.Map;
/**
- 校验参数是否为空
- @author juzipi
- @date 2024/8/6 16:35 */
public class DataValidationTool { public boolean validate(T data) { Class<?> clazz = data.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); Annotation[] annotations = field.getAnnotations(); boolean isNullable = Arrays.stream(annotations).anyMatch(annotation -> annotation.annotationType() == Nullable.class); try { Object value = field.get(data); if (value == null && !isNullable) { return false; }
▼text复制代码if (value instanceof String) { String strValue = (String) value; if (strValue.isEmpty() && !isNullable) { return false; } } if (value instanceof List) { List<?> listValue = (List<?>) value; if (listValue.isEmpty() && !isNullable) { return false; } } if (value instanceof Integer) { Integer intValue = (Integer) value; if (intValue < 0 && !isNullable) return false; } if (value instanceof Long) { Long longValue = (Long) value; if (longValue < 0 && !isNullable) return false; } if (value instanceof Double) { Double doubleValue = (Double) value; if (doubleValue < 0 && !isNullable) return false; } if (value instanceof Float) { Float floatValue = (Float) value; if (floatValue < 0 && !isNullable) return false; } if (value instanceof Map) { Map<?, ?> mapValue = (Map<?, ?>) value; if (mapValue.isEmpty() && !isNullable) { return false; } } } catch (Exception e) { e.printStackTrace(); return false; } } return true; }
}
package com.juzipi.utils;
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;
/**
- 自定义可为空字段标识
- @author juzipi
- @date 2024/8/6 16:43 */ @Retention(RetentionPolicy.RUNTIME) public @interface Nullable { }
3.使用方式:
写入具体校验实体类的到工具类的泛型中,然后调用 validate 方法,判断返回值即可。
4.思考 这样校验真的可以吗?这种校验只适用于 Post 请求类型接口,然后是这种校验方式和直接判空,效率会差距多少呢?橘式疑问。
