数据迁移中,我需要对不同实体类的对象的某些字段进行缺失、重复、异常等校验
利用JAVA反射机制简单写了这样一个工具类
直接上代码,如下
public class CheckUtil {
//记录日志
private static org.apache.logging.log4j.Logger LOGGER = LogManager.getLogger(CheckUtil.class);
/**
* 自定义正则表达式校验
* @param source 校验对象
* @param columns 属性名
* @param express 正则表达式
* @return
*/
public static boolean checkExpressData(Object source, List<String> columns, String express){
boolean flag = true;
try {
Pattern pattern = Pattern.compile(express);
// 取到obj的class, 并取到所有属性
Field[] fs = source.getClass().getDeclaredFields();
//如果列名列表不为空
if(columns != null){
for (Field f : fs) {
// 设置私有属性也是可以访问的
f.setAccessible(true);
//如果该属性在列名列表中
if (columns.contains(f.getName())) {
//如果不匹配
if (!(f.get(source) == null) && !pattern.matcher((CharSequence) f.get(source)).matches()) {
flag = false;
break;
}
}
}
}else {
//如果没有给属性名返回false
flag = false;
}
}catch (Exception e){
flag = false;
LOGGER.error("util/CheckUtil/checkExpressData,校验所提供正则表达式失败" + e.getMessage());
}
return flag;
}
/**
* 校验限定符号的状态值
* @param source 校验对象
* @param columns 属性名
* @param state 状态取值或指标
* @return
*/
public static boolean checkStateData(Object source, List<String> columns, List<String> state){
boolean flag = true;
try {
Field[] fs = source.getClass().getDeclaredFields();
//如果列名列表不为空
if(columns != null){
for (Field f : fs) {
// 设置私有属性也是可以访问的
f.setAccessible(true);
//如果该属性在列名列表中
if (columns.contains(f.getName())) {
//如果不为空且不是特定的取值
if (!(f.get(source) == null) && !"".equals(f.get(source).toString()) && !state.contains(f.get(source).toString())) {
flag = false;
break;
}
}
}
}else {
//如果没有给属性名返回false
flag = false;
}
}catch (Exception e){
flag = false;
LOGGER.error("util/CheckUtil/checkStateData,校验状态值失败" + e.getMessage());
}
return flag;
}
/**
* 校验非空值
* @param source 校验对象
* @param columns 属性名
* @return
*/
public static boolean checkNotNullData(Object source, List<String> columns){
boolean flag = true;
try {
Field[] fs = source.getClass().getDeclaredFields();
//如果列名列表不为空
if(columns != null){
for (Field f : fs) {
// 设置私有属性也是可以访问的
f.setAccessible(true);
//如果该属性在列名列表中
if (columns.contains(f.getName())) {
//如果不为空且不是特定的取值
if ("".equals(f.get(source).toString()) || f.get(source) == null) {
flag = false;
break;
}
}
}
}else {
//如果没有给属性名返回false
flag = false;
}
}catch (Exception e){
flag = false;
LOGGER.error("util/CheckUtil/checkNotNullData,校验非空值失败" + e.getMessage());
}
return flag;
}
/**
* 校验重复数据
* @param source 校验对象
* @param list 已有数据
* @param key 主键
* @return
*/
public static boolean checkRepeatData(Object source, List<Object> list, String key){
boolean flag = true;
List<String> ids = new ArrayList<>();
try {
Field[] fs = source.getClass().getDeclaredFields();
//如果列名列表不为空
if(key != null){
//若列表有数据
if(list != null && list.size() > 0){
//取出列表中的主键
Field[] tem = null;
for(int i = 0; i < list.size(); i++){
tem = list.get(i).getClass().getDeclaredFields();
for (Field t : tem) {
// 设置私有属性也是可以访问的
t.setAccessible(true);
if(key.equals(t.getName())){
ids.add(t.get(list.get(i)).toString());
break;
}
}
}
}
//主键列表有值才执行,否则肯定不重复
if(ids != null && ids.size() > 0){
for (Field f : fs) {
// 设置私有属性也是可以访问的
f.setAccessible(true);
if(key.equals(f.getName())){
if(key.equals(f.getName())){
String newKey = f.get(source).toString();
newKey = newKey == null ? "" : newKey;//防止空指针异常
for(int i = 0; i < ids.size(); i++){
if(newKey.equals(ids.get(i))){
//找到相同主键
flag = false;
break;
}
}
}
break;
}
}
}
}else {
//如果没有给属性名返回false
flag = false;
}
}catch (Exception e){
flag = false;
LOGGER.error("util/CheckUtil/checkRepeatData,校验重复值失败" + e.getMessage());
}
return flag;
}
/**
* 校验重复数据(已有主键数据)
* @param source 校验对象
* @param list 已有数据
* @return
*/
public static boolean checkRepeatData(Object source, List<String> list){
boolean flag = true;
try {
Field[] fs = source.getClass().getDeclaredFields();
//主键列表有值才执行,否则肯定不重复
if(list != null && list.size() > 0){
for (Field f : fs) {
// 设置私有属性也是可以访问的
f.setAccessible(true);
if("id".equals(f.getName())){
if("id".equals(f.getName())){
String newKey = f.get(source).toString();
newKey = newKey == null ? "" : newKey;//防止空指针异常
for(int i = 0; i < list.size(); i++){
if(newKey.equals(list.get(i))){
//找到相同主键
flag = false;
break;
}
}
}
break;
}
}
}else {
//如果没有给属性名返回false
flag = false;
}
}catch (Exception e){
flag = false;
LOGGER.error("util/CheckUtil/checkRepeatData,校验重复值失败" + e.getMessage());
}
return flag;
}
}
测试
public static void main(String[] args) {
Bean bean= new Bean();//Bean中有telNo、mobileNo属性
bean.setTelNo("a");
bean.setMobileNo(null);
List<String> list = new ArrayList<>();
list.add("telNo");
list.add("mobileNo");
//使用工具类
boolean flag = CheckUtil.checkStateData(bean,list,Arrays.asList(new String("a"),new String("b")));
System.out.println(flag);
}
日志类的引入,在pom文件加入依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>