利用递归遍历获取复杂对象中所有目标属性的值(三)

       关于遍历复杂对象中目标属性的值的文章,这是我写的第三篇,也是目前为止我能想到的遍历效率最高的一篇,再前两篇基础上做了相关完善和优化,主要是思路改变了。

      具体实现思路:在复杂对象的目标属性上增加自定义注解,目标属性所属类也可能是某个bo的属性,则在这个属性上增加另一个自定义注解,然后利用递归遍历。

      闲话少说,直接上代码

     一、两个自定义注解

/**
 * @author: lsl
 * @date: 2019/3/1
 *  作用:字典类属性注解
 */
@Target(value = {ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DictClass {
    public String value() default "";
}
/**
 * @author: lsl
 * @date: 2019/3/1
 *  字典属性注解
 */
@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DictField {
    public String dictCode();

    public String transColumName() default "";

    public String isSpeRule() default "0";
}

 

 

 二、核心代码,递归遍历类。主要方法是ergodicObject。入口方法是objectCodeTrans。

package com.newcore.pcms.common.support.codetrans.util;

import com.halo.core.cache.api.CacheMetaInfoFactory;
import com.halo.core.cache.api.CacheService;
import com.halo.core.cache.models.IndexItem;
import com.halo.core.cache.support.redis.holder.TableHolder;
import com.halo.core.common.SpringContextHolder;
import com.halo.core.common.models.XOR;
import com.halo.core.exception.BusinessException;
import com.newcore.pcms.common.support.codetrans.annotation.DictClass;
import com.newcore.pcms.common.support.codetrans.annotation.DictField;
import com.newcore.pcms.common.support.codetrans.dao.api.ServiceAttrDictDao;
import com.newcore.pcms.common.support.codetrans.models.po.pcms.PCodeTransDefPO;
import com.newcore.pcms.common.support.codetrans.models.po.pcms.ServiceAttrDictBO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 对象级的码表转换工具类
 * @author: lsl
 * @date: 2018/12/12
 */
public class CodeTransHolderUtils {

    private static Logger logger = LoggerFactory.getLogger(CodeTransHolderUtils.class);

    int num=0;
//    public static CacheMetaInfoFactory getCacheMetaInfoFactory() {
//        return (CacheMetaInfoFactory) SpringContextHolder.getBean("cacheMetaInfoFactory");
//    }
//
//    public static CacheService getCacheService() {
//        return (CacheService) SpringContextHolder.getBean("cacheService");
//    }

    /**
     * 对服务中参数中的属性是字典,进行全部码值转换
     * @param srcSysCode            源系统
     * @param destSysCode           目标系统
     * @param obj                    服务中方法入参
     * @return
     */
    public static List<String> objectCodeTrans(String srcSysCode, String destSysCode,  Object obj) {
        List<String> listNotIncludeAttr = new ArrayList<>();
//        boolean methodParamNameNotBlank = (ConstantTools.FLAG_Y).equals(forwardFlag) ? StringUtils.isNotBlank(serMethodParamName) : true;
        boolean notBlankFlag = StringUtils.isNotBlank(srcSysCode) && StringUtils.isNotBlank(destSysCode) && (null!= obj) ;
        logger.info("objectCodeTrans方法的参数:srcSysCode=" + srcSysCode + ",destSysCode=" + destSysCode );
        CodeTransHolderUtils utils = new CodeTransHolderUtils();
        long startTime = System.currentTimeMillis();
        if (notBlankFlag){

            if (obj instanceof List<?>) {
                utils.ergodicList(srcSysCode, destSysCode,  (List) obj , listNotIncludeAttr);
            } else {
                utils.ergodicObject(srcSysCode, destSysCode,  obj, listNotIncludeAttr);
            }
        }
        long endTime = System.currentTimeMillis();
        System.err.println("对象级码表转换耗时=" + (endTime-startTime) + ",递归次数=" + utils.num);
        return listNotIncludeAttr;
    }



    /**
     *
     * @param srcSysCode            源系统
     * @param destSysCode           目标系统
     * @param listParam             服务方法入参(list)
     * @param listNotIncludeAttr   入参字典属性未在码表中找到对应的目标系统字典值的属性名
     * @param <T>                    码表转换后的入参
     */
    public  <T> void ergodicList(String srcSysCode, String destSysCode,  List<T> listParam,  List<String> listNotIncludeAttr) {
        listParam.stream().forEach(t -> {
            ergodicObject(srcSysCode, destSysCode,  t, listNotIncludeAttr);
        });
    }

    /**
     * 对象级码表转换。把t中指定attribute属性的值更改为目标系统的字典值,并把在目标系统中没有找到字典值的属性放到listNotIncludeAttr
     * 注意:
     * 1、t中的属性类型不能包含以下集合嵌套类型:Set、List<Map<K,V>、Map<K,List<BO>>
     * 2、t中的属性类型可以是BO、数组、List<BO>、Map<K,BO>
     * 3、属性名一定要规范,比如private PCodeTransDefPO pCodeTransDefPO(不规范),这样利用反射找不到getter方法,应该改成codeTransDefPO或者PCodeTransDefPO
     * @param srcSysCode            源系统
     * @param destSysCode           目标系统
     * @param t                       入参对象(是BO非list)
     * @param listNotIncludeAttr    没有在码表中找到目标系统中对应的码值的字典属性
     * @param <T>                      码表转换后的入参
     */
    public  <T> void ergodicObject(String srcSysCode, String destSysCode,  T t,  List<String> listNotIncludeAttr) {
        num++;
        Class clazz = t.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
//                String attrType = field.getType().getSimpleName();//属性类型
                String attrShortName = field.getName();//属性名

                if (field.isAnnotationPresent(DictField.class)){
                    String attrValue = (String)field.get(t);//属性值
                    String dictCode = field.getAnnotation(DictField.class).dictCode();//字典名
                    String transColumName = field.getAnnotation(DictField.class).transColumName();//词汇名
                    String isSpeRule = field.getAnnotation(DictField.class).isSpeRule();//是否特殊
                    if(ConstantTools.DEFAULT_0.equals(isSpeRule) ){
                        transColumName="";
                    }
//                    String destCodeVal = "";
                    String destCodeVal =CodeTransDefTools.queryOneUnCodeTransValPOrder(srcSysCode,destSysCode,dictCode,attrValue,isSpeRule,transColumName);
                    //如果t中的目标属性的值为null或者"",则不需要修改其值
                    if (attrValue != null && !"".equals(attrValue)){
                        if (destCodeVal != null && !"".equals(destCodeVal)) {
                            //如果从目标系统中查到的字典值非null或者非空字符串,则重新给属性赋值,否则把属性放到listNotIncludeAttr
                            field.set(t, destCodeVal);
                        } else {
                            listNotIncludeAttr.add(attrShortName);
                            logger.info("在目标系统" + destSysCode + "中,没有找到源系统" + srcSysCode + "中属性是" + attrShortName + "对应的字典" + dictCode + ",找到的字典值是:" + destCodeVal);
                        }
                    }
                }else if (field.isAnnotationPresent(DictClass.class)){
                    if (isList(field)){
                        //对List/ArrayList类型的属性遍历
                        try {
                            PropertyDescriptor descriptor = new PropertyDescriptor(attrShortName, clazz);
                            Method method = descriptor.getReadMethod();
                            List list = (List) method.invoke(t);
                            if (list != null && list.size() > 0) {
                                list.stream().forEach(p -> {
                                    // 递归
                                    ergodicObject(srcSysCode, destSysCode, p,  listNotIncludeAttr);
                                });
                            }
                        } catch (IntrospectionException e) {
                            logger.info(e.getMessage());
                        } catch (InvocationTargetException e) {
                            logger.info(e.getMessage());
                        }
                    }else if(isMap(field)){
                        //对Map/HashMap类型的属性遍历
                        try {
                            PropertyDescriptor descriptor = new PropertyDescriptor(attrShortName, clazz);
                            Method method = descriptor.getReadMethod();
                            Map map = (Map) method.invoke(t);
                            if (map != null && map.size() > 0) {
                                for (Object obj : map.values()) {
                                    // 递归
                                    ergodicObject(srcSysCode, destSysCode,  obj,  listNotIncludeAttr);
                                }
                            }
                        } catch (IntrospectionException e) {
                            logger.info(e.getMessage());
                        } catch (InvocationTargetException e) {
                            logger.info(e.getMessage());
                        }
                    }else if (field.getType().isArray()) {
                        //对数组类型的属性遍历
                        field.setAccessible(true);
                        Object[] objArr = (Object[]) field.get(t);
                        if (objArr != null && objArr.length > 0) {
                            for (Object arr : objArr) {
                                //递归
                                ergodicObject(srcSysCode, destSysCode, arr, listNotIncludeAttr);
                            }
                        }
                    }else {
                        //对自定义类的属性递归
                        try {
                            PropertyDescriptor descriptor = new PropertyDescriptor(attrShortName, clazz);
                            Method method = descriptor.getReadMethod();
                            Object obj = method.invoke(t);
                            if (obj != null) {
                                //递归
                                ergodicObject(srcSysCode, destSysCode, obj, listNotIncludeAttr);
                            } else {
                                continue;
                            }
                        } catch (IntrospectionException e) {
                            logger.info(e.getMessage());
                        } catch (InvocationTargetException e) {
                            logger.info(e.getMessage());
                        }
                    }
                }else {
                    continue;
                }

            }
        } catch (IllegalAccessException e) {
            logger.info(e.getMessage());
        }

    }

    /**
     * 判断是否是List或者ArrayList
     * @param field
     * @return
     */
    public  boolean isList(Field field){
        boolean flag = false;
        String simpleName = field.getType().getSimpleName();
        if ("List".equals(simpleName) || "ArrayList".equals(simpleName)){
            flag = true;
        }
        return flag;
    }

    /**
     * 判断是否是Map或者HashMap
     * @param field
     * @return
     */
    public  boolean isMap(Field field){
        boolean flag = false;
        String simpleName = field.getType().getSimpleName();
        if ("Map".equals(simpleName) || "HashMap".equals(simpleName)){
            flag = true;
        }
        return flag;
    }


} 

三、如何使用

复杂对象如下:

package com.lsl.model;

import com.lsl.annotion.DictClass;

import java.util.List;

/**
 * @author: lsl
 * @date: 2019/2/27
 */
public class ParentClass {
    private String fatherName;
    private int fatherAge;
    @DictClass
    private List<SubClass> list;
    @DictClass
    private SubClass subClass;
    public String getFatherName() {
        return fatherName;
    }

    public void setFatherName(String fatherName) {
        this.fatherName = fatherName;
    }

    public int getFatherAge() {
        return fatherAge;
    }

    public void setFatherAge(int fatherAge) {
        this.fatherAge = fatherAge;
    }

    public List<SubClass> getList() {
        return list;
    }

    public void setList(List<SubClass> list) {
        this.list = list;
    }

    public SubClass getSubClass() {
        return subClass;
    }

    public void setSubClass(SubClass subClass) {
        this.subClass = subClass;
    }
}

 

复杂对象ParentClass包含子对象SubClass

子对象SubClass代码:

package com.lsl.model;

import com.lsl.annotion.DictField;

/**
 * @author: lsl
 * @date: 2019/2/27
 */
public class SubClass {
    @DictField(dictCode = "aaa")
    private String subName;
    private int subAge;
    public String getSubName() {
        return subName;
    }

    public void setSubName(String subName) {
        this.subName = subName;
    }

    public int getSubAge() {
        return subAge;
    }

    public void setSubAge(int subAge) {
        this.subAge = subAge;
    }
}

 

 简单测试,和二、核心代码部分略有区别

package com.lsl;

import com.alibaba.fastjson.JSON;
import com.lsl.annotion.DictClass;
import com.lsl.annotion.DictField;
import com.lsl.model.ParentClass;
import com.lsl.model.SubClass;
import com.lsl.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author: lsl
 * @date: 2019/2/15
 */
@Controller
@RequestMapping("/lsl")
public class MyTest {

    public static void main(String [] args){

        SubClass sub1 = new SubClass();
        sub1.setSubAge(21);
        sub1.setSubName("aaa");
        SubClass sub2 = new SubClass();
        sub2.setSubName("bbb");
        sub2.setSubAge(20);
        SubClass sub3 = new SubClass();
        sub3.setSubName("ccc");
        sub3.setSubAge(22);
        List<SubClass> list = new ArrayList();
        list.add(sub1);
        list.add(sub2);

        ParentClass parent = new ParentClass();
        parent.setFatherAge(18);
        parent.setFatherName("aaa");
        parent.setSubClass(sub3);
        parent.setList(list);

        ergodicObject(parent);
    }

    public static <T> void ergodicObject(T t){
        Class clazz = t.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
    //                String attrType = field.getType().getSimpleName();//属性类型
                String attrShortName = field.getName();//属性名
                if (field.isAnnotationPresent(DictField.class)){
                    String attrValue = (String)field.get(t);//属性值
                }else if (field.isAnnotationPresent(DictClass.class)){
                    if (isList(field)){
                        //对List/ArrayList类型的属性遍历
                        try {
                            PropertyDescriptor descriptor = new PropertyDescriptor(attrShortName, clazz);
                            Method method = descriptor.getReadMethod();
                            List list = (List) method.invoke(t);
                            if (list != null && list.size() > 0) {

                                for(Object obj : list){
                                    ergodicObject(obj);
                                }
                            }
                        } catch (IntrospectionException e) {
    //                        logger.info(e.getMessage());
                        } catch (InvocationTargetException e) {
    //                        logger.info(e.getMessage());
                        }
                    }else if(isMap(field)){
                        //对Map/HashMap类型的属性遍历
                        try {
                            PropertyDescriptor descriptor = new PropertyDescriptor(attrShortName, clazz);
                            Method method = descriptor.getReadMethod();
                            Map map = (Map) method.invoke(t);
                            if (map != null && map.size() > 0) {
                                for (Object obj : map.values()) {
                                    // 递归
                                    ergodicObject( obj);
                                }
                            }
                        } catch (IntrospectionException e) {
    //                        logger.info(e.getMessage());
                        } catch (InvocationTargetException e) {
    //                        logger.info(e.getMessage());
                        }
                    }else if (field.getType().isArray()) {
                        //对数组类型的属性遍历
                        field.setAccessible(true);
                        Object[] objArr = (Object[]) field.get(t);
                        if (objArr != null && objArr.length > 0) {
                            for (Object arr : objArr) {
                                //递归
                                ergodicObject( arr);
                            }
                        }
                    }else {
                        //对自定义类的属性递归
                        try {
                            PropertyDescriptor descriptor = new PropertyDescriptor(attrShortName, clazz);
                            Method method = descriptor.getReadMethod();
                            Object obj = method.invoke(t);
                            if (obj != null) {
                                //递归
                                ergodicObject( obj);
                            } else {
                                continue;
                            }
                        } catch (IntrospectionException e) {
    //                        logger.info(e.getMessage());
                        } catch (InvocationTargetException e) {
    //                        logger.info(e.getMessage());
                        }
                    }
                }else {
                    continue;
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public  static boolean isList(Field field){
        boolean flag = false;
        String simpleName = field.getType().getSimpleName();
        if ("List".equals(simpleName) || "ArrayList".equals(simpleName)){
            flag = true;
        }
        return flag;
    }

    /**
     * 判断是否是Map或者HashMap
     * @param field
     * @return
     */
    public static   boolean isMap(Field field){
        boolean flag = false;
        String simpleName = field.getType().getSimpleName();
        if ("Map".equals(simpleName) || "HashMap".equals(simpleName)){
            flag = true;
        }
        return flag;
    }

    public static String countMethod(){
        StringBuffer a= new StringBuffer("11");
        try {
            try {
                a = a.append("22");
                int m=1/0;
            } catch (Exception e) {
                System.err.println("内层catch执行");
                throw e;

            }
//            return a.toString();
        } catch (Exception e) {
//            return a.toString();
            System.err.println("外层catch执行");
            throw e;
        } finally {
            a = a.append("33");
            System.err.println("finally==a==" + a);
        }
        return a.toString();
    }

    @Autowired
    MyService service;

//    @Transactional
    @RequestMapping("/lock")
    public  void tranactionalTest(){
        BizLock lock = new BizLock();
        BizLock bizLock = new BizLock();
        bizLock.setBizId("11223344");
        bizLock.setBizNo("aabbccdd");
        bizLock.setBizType("MTNNO");
        long nowTime = System.currentTimeMillis();
        bizLock.setCreateTime(new Timestamp(nowTime));
        bizLock.setPassTime(new Timestamp(nowTime));
        int count = service.addLock(bizLock);

        if (count==1){
            System.err.println("加锁成功" + count);
        }else {
            System.err.println("加锁失败" + count);
        }
//        int aa = 1/0;
//        try {
//            System.err.println("Thread名字"+ Thread.currentThread().getName() + ",开始休眠8888888");
//            Thread.sleep(50000L);
//        } catch (InterruptedException e) {
//
//        }

        int num=12;

        System.err.println("endendendend");
//        return count;
    }


    @RequestMapping("/lock2")
    public  void tranactionalTes2t(){
        BizLock lock = new BizLock();
        BizLock bizLock = new BizLock();
        bizLock.setBizId("11223344");
        bizLock.setBizNo("aabbccdd");
        bizLock.setBizType("MTNNO");
        long nowTime = System.currentTimeMillis();
        bizLock.setCreateTime(new Timestamp(nowTime));
        bizLock.setPassTime(new Timestamp(nowTime));
        int count = service.addLock(bizLock);

        if (count==1){
            System.err.println("加锁成功" + count);
        }else {
            System.err.println("加锁失败" + count);
        }
//


        System.err.println("endendendend");
    }


}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一路奔跑1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值