返回

从头开始:在不依赖第三方 JAR 包的情况下优雅地进行 Dubbo 调用

后端

在不引入第三方 JAR 包的情况下优雅地进行 Dubbo 调用

作为开发人员,我们经常需要与外部服务进行通信。Dubbo 是一个流行的分布式服务框架,允许我们轻松地进行远程过程调用 (RPC)。然而,在某些情况下,我们可能希望在不引入第三方 JAR 包的情况下使用 Dubbo 服务。

本文将介绍一种优雅的方法,让你能够在不依赖第三方 JAR 包的情况下进行 Dubbo 调用。这对于希望保持应用程序精简和独立的开发人员特别有用。

背景

默认情况下,Dubbo 客户端需要使用生产者提供的客户端 JAR 包才能进行调用。这可能会导致应用程序依赖关系过多,并且难以管理。为了解决这个问题,我们可以使用 Dubbo 的原生协议,它允许客户端直接与服务器进行通信,而无需客户端 JAR 包。

技术要求

  • Java 8 或更高版本
  • Dubbo 3.0 或更高版本

步骤

  1. 使用原生协议

首先,我们需要配置 Dubbo 客户端以使用原生协议。这可以通过在 dubbo.properties 文件中添加以下属性来实现:

dubbo.protocol.dubbo=dubbo://
  1. 确定服务全限定类名

要调用服务,我们需要知道其全限定类名。这可以通过查看生产者提供的接口或实现类来确定。

  1. 创建代理类

接下来,我们需要创建代理类来代表 Dubbo 服务。这可以通过使用 com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler 类来实现。

public class MyProxy implements InvocationHandler {

    private String host;
    private int port;
    private String serviceInterfaceName;

    public MyProxy(String host, int port, String serviceInterfaceName) {
        this.host = host;
        this.port = port;
        this.serviceInterfaceName = serviceInterfaceName;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 构造 Dubbo URL
        URL url = new URL("dubbo", host, port, serviceInterfaceName);

        // 创建 Dubbo 消费者
        Invoker<?> invoker = new JdkRpcInvoker(url);

        // 执行 RPC 调用
        return invoker.invoke(new Invocation(method, args));
    }
}
  1. 创建服务代理

最后,我们需要使用代理类创建服务代理。这可以通过以下方式实现:

ProxyFactory proxyFactory = new ProxyFactory();
Object proxy = proxyFactory.getProxy(MyProxy.class);

示例代码

以下是一个完整的示例代码:

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.ProxyFactory;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DubboClientWithoutJar {

    public static void main(String[] args) {
        // 配置 Dubbo 原生协议
        System.setProperty("dubbo.protocol.dubbo", "dubbo://");

        // 服务地址
        String host = "127.0.0.1";
        int port = 20880;

        // 服务接口全限定类名
        String serviceInterfaceName = "com.example.demo.DemoService";

        // 创建服务代理
        Object proxy = createProxy(host, port, serviceInterfaceName);

        // 调用服务方法
        Method method = proxy.getClass().getMethod("sayHello", String.class);
        Object result = method.invoke(proxy, "World");

        // 打印结果
        System.out.println(result);
    }

    private static Object createProxy(String host, int port, String serviceInterfaceName) {
        // 创建代理类
        MyProxy myProxy = new MyProxy(host, port, serviceInterfaceName);

        // 创建服务代理
        ProxyFactory proxyFactory = new ProxyFactory();
        Object proxy = proxyFactory.getProxy(myProxy);

        return proxy;
    }

    private static class MyProxy implements InvocationHandler {

        private String host;
        private int port;
        private String serviceInterfaceName;

        public MyProxy(String host, int port, String serviceInterfaceName) {
            this.host = host;
            this.port = port;
            this.serviceInterfaceName = serviceInterfaceName;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 构造 Dubbo URL
            URL url = new URL("dubbo", host, port, serviceInterfaceName);

            // 创建 Dubbo 消费者
            Invoker<?> invoker = new JdkRpcInvoker(url);

            // 执行 RPC 调用
            Invocation invocation = new RpcInvocation(method, args);
            Result result = invoker.invoke(invocation);

            // 返回结果
            return result.getValue();
        }
    }
}

优势

使用这种方法具有以下优势:

  • 应用程序精简: 不需要依赖第三方 JAR 包,从而保持应用程序精简。
  • 独立性: 应用程序不再依赖于生产者提供的客户端 JAR 包,从而提高了独立性。
  • 灵活性: 它允许我们在不修改生产者代码的情况下调用 Dubbo 服务。