资讯专栏INFORMATION COLUMN

只因数据过滤,方可模拟beanutils框架

yzzz / 943人阅读

摘要:因而,我从中也知道了,很多公司没有实现数据过滤。因为,那样将会造成数据的冗余。因而,我们这时需要过滤数据对象,如代码所示常用的把图片转成结构如上诉代码的转换,公司使用的是这个框架。而栈是存放数据的一种结构,其采用,即先进后出。

导读

上一篇文章已经详细介绍了框架与RTTI的关系,RTTI与反射之间的关系。尤其是对反射做了详细说明,很多培训机构也将其作为高级教程来讲解。

其实,我工作年限也不长,大概八九个月吧。但我见过很多技术人员,而我喜欢与别人讨论技术。因而,我从中也知道了,很多公司没有实现数据过滤。

什么是数据过滤?比如客户端向服务器端发送展示项目图片的请求,服务端接收到前端的请求并从数据库中拿到项目图片的对象,我们只要返回图片在服务端的地址和名称即可,没必要将整个图片对象返回给客户端。因为,那样将会造成数据的冗余。因而,我们这时需要过滤数据(对象),如代码所示:

/**
 * 常用的把图片转成  {id: 1, path: "xxx"}结构
 */
public static JSONObject img2Json(Picture picture) {
    if (isNotNull(picture)) {
        String[] PICTURE_JSON = {"id", "remoteRelativeUrl:path"};
        JSONObject jsonObject = propsFilter(picture, PICTURE_JSON);
        return jsonObject;
    } else {
        return null;
    }
}

如上诉代码的转换,公司使用的是commons-beanutils这个框架。我们只要在项目中农添加其maven配置即可:

 
      commons-beanutils
      commons-beanutils
      1.9.2
    

我个人比较喜欢研究源码,于是,仿照这个框架写了自己的框架,下面,就是介绍我个人的框架。

我的beanutils框架

框架使用的算法或技术

递归算法。我们并不推荐使用递归,因为,方法自调用自己。根据JVM的内部原理,每个方法都是一个方法栈。而栈是存放数据的一种结构,其采用FIFO(First In Last Out),即先进后出。和我们堆放菜盘一样,先垒的最后拿出来。既然是数据存储,肯定会超出容量,因为,内存不是无限大的,恰如水满自溢。但是,我们在这里还是使用递归,因为,在深度调用算法当中,采用递归是合适的。

java的反射机制。我们根据Javabean的属性名称获取值。

核心算法说明。

如果javabean的对象属性类型不是用户自定义的类型,我们根据反射调用get方法拿到属性的值
如果javabean的对象属性类型是用户自定义的类型,我们利用递归重新调用改方法,直到出现遇见上面的条件

 /**
     * Created By zby on 20:28 2019/2/13
     *
     * @param bean  实体对象
     * @param props 属性名称
     */
    public static Object getProperty(Object bean, String props) {
        if (bean == null)
            throw new RuntimeException("实例化对象不存在bean=" + bean);
        if (StringHelper.isBlank(props))
            throw new RuntimeException("属性名称不存在props=" + props);
        Class clazz = null;
        String methodName = null;
        String fieldName = null;
        String typeName = null;
        try {
            clazz = bean.getClass();
            if (props.indexOf(".") != -1) {
                methodName = MethodHelper.propsToGetMethod(props.substring(0, props.indexOf(".")));
                Method method = clazz.getDeclaredMethod(methodName);
                Object obj = method.invoke(bean);
                return getProperty(obj, props.substring(props.indexOf(".") + 1));
            }
            Field field = clazz.getDeclaredField(props);
            typeName = field.getType().getName();
            if (typeName.equalsIgnoreCase("boolean")) {
                field.setAccessible(true);
                return field.getBoolean(bean);
            }

            methodName = MethodHelper.propsToGetMethod(props);
            Method method = clazz.getDeclaredMethod(methodName);
            return method.invoke(bean);
        } catch (NoSuchMethodException e) {
            logger.error(clazz + "类型没有" + methodName + "方法");
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            logger.error(clazz + "类型没有" + fieldName + "属性");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
如何使用上诉算法

我们既然是通过属性名称来获取属性对象。我们可以设计一个算法,算法该算法有两个参数,一个是当前对象,一个是对象的属性数组。属性数组还可以有别名。

为什么需要别名?比如当前对象采用组合关系,使用自定义的类。比如说订单类使用用户类(User)的对象作为属性,我们在订单中希望看到用户姓名,我们可以这样调用user.name,以该字段传给客户端,但客户端需要转换才能拿到用户名,因而,我们需要一个别名,前端不用转换,就可以拿到用户名,比如:user.name:username。

当然,我们需要将对象转化为json格式的框架, 这里使用的阿里巴巴的fastjson框架,我们可以在项目中配置maven:

 
  com.alibaba
  fastjson
  1.2.28

所示,算法设计为:

 /**
 * Created By zby on 9:40 2019/2/13
 * 模拟框架中的数据
 *
 * @param object 参数对象
 * @param props  String类型的变长数组,比如{"id:projectId", "mobile",...}
 *               前半部分是javabean的属性名,后半部分是返回到给客户端的参数名
 */
public static JSONObject propsFilter(Object object, String... props) {
    //【1】判断对象和变长数组的是否为空,以及变长数组的长度是否为0
    boolean isNull = object == null || (null == props && props.length == 0);
    if (isNull) {
        logger.warn("参数为空object=" + object + "props=" + props);
        return null;
    }
    JSONObject jsonObject = new JSONObject();
    for (String prop : props) {
        //【2】再判断对象不为空,或者长度不为0
        if (prop == null && prop.length() == 0) {
            logger.warn("参数为空prop= " + prop);
            throw new RuntimeException("参数为空prop=" + prop);
        }
        Object o = null;
        String[] namePair = StringUtils.split(prop, ":");
        try {
            o = PropertyUtil.getProperty(object, namePair[0]);
        } catch (Exception e) {
            logger.warn("类" + object.getClass() + ",属性" + namePair[0] + "不存在");
        }
        String key = namePair.length <= 1 ? namePair[0] : namePair[1];
        if (o instanceof Date)
            jsonObject.put(key, DateUtil.simpleFormate((Date) o));
        else if (o instanceof BigDecimal)
            jsonObject.put(key, CommonUtil.toFiexd((BigDecimal) o, 2));
        else if (o instanceof TitleEnum)
            jsonObject.put(key, CommonUtil.builderEnum((TitleEnum) o));
        else
            jsonObject.put(key, o);
    }
    return jsonObject;
}
测试框架和类

我们既然写好了这个框,也使用了这个框架,因而,我们可以使用Junit来测试:

   @Test
    public void test(){
            Address address = new Address();
            address.setAddressTag(AddressTagEnum.ADDRESS_TAG_COMPANY);
            address.setArea("杭州市....");
            address.setConsignee("zby");

            User user = new User();
            user.setHobby(HobbyEnum.HOBBY_DANCING);
            user.setGender("男");
            user.setUserName("蒋三");

            OrderSnapshot orderSnapshot = new OrderSnapshot();
            orderSnapshot.setAddress(address);
            orderSnapshot.setId(1L);
            orderSnapshot.setName("复读机");
            orderSnapshot.setOrderNo(Long.valueOf(System.currentTimeMillis()).toString() + "1L");
            orderSnapshot.setUser(user);
            String[] json = {"address.consignee:consignee","user.hobby:hobby",
                    "address.addressTag:addressTag", "address.area:area"
                    ,"address.consignee:consignee","user.userName:userName"};
            System.out.println(JsonUtil.propsFilter(orderSnapshot, json));

测试结果为:

可见,我们算法时成功的。

总结

我们还是要时常看源码,因为,你的目的不是写出框架,而是看别人写框架的思想。毕竟,思想主导一切行为,行为成就一个的未来。致努力的自己。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73730.html

相关文章

  • 回眸曾经的项目,与第三方支付相关,所带来的沟通问题

    摘要:钱可以存储在自己的余额中,这就相当于微信钱包,余额可以提现到银行卡的中。我们的第三方支付平台是连连支付,杭州的一家公司。私钥怎么加签每个公司的加签方式是不一样的,支付宝有支付宝的加签方式,微信有微信的加签方式。 导读 笔者在校期间,通过自学java。学校里也开过这门课,但是,讲的都是一些基础,比如java的表达式、基本类型、自定义类型等等。也都是很基础的东西,就连lambda表达式都没...

    kaka 评论0 收藏0
  • 接口间参数传递的一种解决方案

    摘要:解决链路间参数传递的问题可以简化为解决接口间的参数传递问题。当然,针对这个问题的解决方案,其实还是蛮多的。总结下来,自动化用例的维护和开发成本主要集中在接口间参数传递的维护上面。 引言 做过接口自动化测试的同学肯定都熟悉在全链路测试过程中,很多业务场景的完成并非由单一接口实现,而是由很多接...

    不知名网友 评论0 收藏0
  • Jodd - Java界的瑞士军刀轻量级工具包!

    摘要:介绍是对于开发更便捷的开源迷你框架,包含工具类实用功能的集合,总包体积不到。你可以把想象成的瑞士军刀不仅小,锋利而且包含许多便利的功能。 showImg(https://segmentfault.com/img/remote/1460000015356940); Jodd介绍 Jodd是对于Java开发更便捷的开源迷你框架,包含工具类、实用功能的集合,总包体积不到1.7M。 Jodd构...

    yck 评论0 收藏0
  • java bean 对象属性复制框架BeanMapping-01-入门案例

    摘要:项目简介用于对象属性赋值。示例代码对象的定义其中对象和对象的属性是相同的。名称年龄生日字符串列表属性赋值测试案例我们构建的属性,然后调用类似于和,并验证结果符合我们的预期。 项目简介 Bean-Mapping 用于 java 对象属性赋值。 项目中经常需要将一个对象的属性,赋值到另一个对象中。 常见的工具有很多,但都多少不够简洁,要么不够强大。 特性 支持对象属性的浅拷贝 变更日志 变...

    hot_pot_Leo 评论0 收藏0
  • Apollo源码分析(二): Apollo的代码层次

    摘要:不同与其它中间件框架,中有大量的业务代码,它向我们展示了大神是如何写业务代码的依赖的层次结构,如何进行基础包配置,以及工具类编写,可以称之为之最佳实践。代码参考视图解析器,这里的配置指的是不检查头,而且默认请求为格式。 不同与其它中间件框架,Apollo中有大量的业务代码,它向我们展示了大神是如何写业务代码的:maven依赖的层次结构,如何进行基础包配置,以及工具类编写,可以称之为sp...

    cyqian 评论0 收藏0

发表评论

0条评论

yzzz

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<