Dubbo泛化调用,暨http版dubbo测试框架

引言

Dubbo通常的调用方式是需要Consumer引入Provider的api包。
期望做一个通用Dubbo测试平台,即前端输入相关信息(zk、service,method、params)即可实现dubbo调用,无需引入对应的api包。
此处使用Dubbo泛化方案。

参考资料:
https://www.jianshu.com/p/3a22a53c7068
https://qsli.github.io/2018/05/02/dubbo-generic-invoke/

具体代码

    @Test
    public void test_baseType(){
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-consumer-test-baseType");

        String zk="zktestserver1.xx.info:22181,zktestserver2.xx.info:22181,zktestserver3.xx.info:22181";
        String service  = "com.xx.entry.service.OrgNewService";
        String method = "queryOrgDetailById";

        RegistryConfig registry = new RegistryConfig();

        registry.setProtocol("zookeeper");
        registry.setAddress(zk);
        registry.setGroup("dubbo_test");

        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setProtocol("dubbo");
        reference.setApplication(applicationConfig);
        reference.setRegistry(registry);
        reference.setInterface(service);

        // 此参数表明为泛化接口
        reference.setGeneric(true);

        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
        GenericService genericService = cache.get(reference);

        Object res = genericService.$invoke(method,
                new String[] { "java.lang.String" },
                new Object[] { "1050001" });

        System.out.println(res);
        System.out.println(JSON.toJSONString(res));

    }

上述例子为基本数据类型,但也可能会出现方法入参数负责Java对象,需要将入参类型字符串,及入参的Map格式传递。如下:

Map<String, String> data = new HashMap<>();
        // 如果参数类型是接口,或者如List等丢失泛型,可以通过class属性指定类型
        data.put("class", "com.xx.entry.param.RouteEntryParam");

        data.put("tid", "00000");
        data.put("vorgId", "1030101");
        data.put("entryId", "03220103");
        data.put("nickName", "JL-10086");

        Object res2 = genericService.$invoke(method,
                new String[] {"com.xx.entry.param.RouteEntryParam"},
                new Object[] { data });
        System.out.println(res2);

FAQ

1. 如果POJO对象没有无参构造函数(如使用 lombok 的 @Builder 构建器),则调用时会报错:java.lang.RuntimeException: Illegal constructor:

问题排查过程:
Step1: com.alibaba.dubbo.common.utils.PojoUtils 中搜Illegal constructor

private static Object newInstance(Class<?> cls) {
        try {
            return cls.newInstance();
        } catch (Throwable t) {
            try {
                Constructor<?>[] constructors = cls.getConstructors();
                if (constructors != null && constructors.length == 0) {
                    throw new RuntimeException("Illegal constructor: " + cls.getName());
                }
                ......

其中catch异常部分的Constructor<?>[] constructors = cls.getConstructors() 读取的是public 构造函数。

Step2:进一步查看cls.newInstance() 源码:

@CallerSensitive
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
        if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }

        // NOTE: the following code may not be strictly correct under
        // the current Java memory model.

        // Constructor lookup
        if (cachedConstructor == null) {
            if (this == Class.class) {
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
                Class<?>[] empty = {};
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
                ......

由此可以看出:因为empty为空,所以Class.newInstance() 只能调用无参的构造函数。

猜测:如AOP 也只支持 public ,不然存在安全风险一样,处于安全考虑!

何解?TODO!!
方案一:修改服务端的Java Bean声明,确保有无参构造器。如修改为 @Data, 如果要保留链式调用,可以加@Accessors(chain = true)

  1. 单独使用 @Data 会产生一个无参构造器
  2. 单独使用 @Builder 会产生一个全参构造器
  3. 混合使用,会产生一个全参构造器

详见:https://blog.csdn.net/w605283073/article/details/89221853

2. 如何获取参数对象的各变量类型元数据?最好是对应一个Map/JSON 格式

何解?TODO!!

暂时想到的一个方案是:定义一套元数据存储系统,首次成功调用时存储,后续根据key自动查找并前端展示。

或者升级到2.7版本以上(包含元数据中心)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值