Spring Boot 整合 Apache Dubbo

Apache Dubbo是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

注意,是 Apache Dubbo,不再是 Alibaba Dubbo。简单来说就是 AlibabaDubbo 移交给 Apache 开源社区进行维护。参见 dubbo-spring-boot-project

Spring Boot 系列:整合 Alibaba Dubbo

一、本文示例说明

1.1 框架版本

  • Dubbo 版本
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.5</version>
</dependency>
  • Spring Boot 版本
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
    <relativePath/>
</parent>

1.2 模块关系

  • 根工程 order:管理工程信息;
  • 子工程 order-api:定义RPC服务的接口、参数以及响应结果的结果集;
  • 子工程 order-providerRPC服务的提供端;
  • 子工程 order-consumerRPC服务的消费端,实际开发过程中实际情况是其它服务的调用该订单RPC服务

二、根工程

2.1 创建项目 order

我这里为了和之前老版本的alibabadubbo项目区分,文件名取为apache-dubbo-demomaven 项目名称为order

该项目主要作用是定义工程信息、管理整个项目依赖版本等等,所以src目录不需要。

2.2 pom.xml

根工程中使用了<dependencyManagement><dependencies>进行依赖管理。

  1. <dependencyManagement>:声明全局依赖,当子项目指定引用才会继承依赖;
  2. <dependencies>:声明全局依赖,子项目直接自动继承依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<span class="hljs-comment">&lt;!-- 父级引用 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.1.1.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">relativePath</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span>

<span class="hljs-comment">&lt;!-- 基本信息 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>${project.artifactId}<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">description</span>&gt;</span>Apache Dubbo 根项目<span class="hljs-tag">&lt;/<span class="hljs-name">description</span>&gt;</span>

<span class="hljs-comment">&lt;!--配置--&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">java.version</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">java.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo.version</span>&gt;</span>2.7.5<span class="hljs-tag">&lt;/<span class="hljs-name">dubbo.version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">zookeeper.version</span>&gt;</span>3.4.14<span class="hljs-tag">&lt;/<span class="hljs-name">zookeeper.version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>

<span class="hljs-comment">&lt;!-- 子项目 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">modules</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>order-api<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>order-provider<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>order-consumer<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">modules</span>&gt;</span>

<span class="hljs-comment">&lt;!--声明全局依赖(子项目需要显示的引用才会继承依赖)--&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- dubbo-start依赖 --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${dubbo.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-comment">&lt;!--zookeeper 注册中心客户端引入 使用的是curator客户端 --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo-dependencies-zookeeper<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${dubbo.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">exclusions</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">exclusion</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>slf4j-log4j12<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">exclusion</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">exclusions</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span>

<span class="hljs-comment">&lt;!--声明全局依赖(子项目不需要显示的引用,自动继承依赖)--&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- spring boot 依赖 --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">exclusions</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">exclusion</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.junit.vintage<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit-vintage-engine<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">exclusion</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">exclusions</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>

<span class="hljs-comment">&lt;!-- 打包插件 --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>

</project>

三、order-api

3.1 项目依赖

无需更多依赖,所以很简单。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order-api<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>${project.artifactId}<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">description</span>&gt;</span>dubbo公共项目<span class="hljs-tag">&lt;/<span class="hljs-name">description</span>&gt;</span>


<span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>

</project>

3.2 封装 RPC 结果集

  • 先封装一个返回码枚举类ResultCodeEnum.java
public enum ResultCodeEnum {
    /*** 通用部分 100 - 599***/
    // 成功请求
    SUCCESS(200, "successful"),
<span class="hljs-comment">/*** 这里可以根据不同模块用不同的区级分开错误码,例如:  ***/</span>

<span class="hljs-comment">// 1000~1999 区间表示用户模块错误</span>
<span class="hljs-comment">// 2000~2999 区间表示订单模块错误</span>
<span class="hljs-comment">// 3000~3999 区间表示商品模块错误</span>
<span class="hljs-comment">// 。。。</span>

ORDER_NOT_FOUND(<span class="hljs-number">2000</span>, <span class="hljs-string">"order not found"</span>),
;
<span class="hljs-comment">/**
 * 响应状态码
 */</span>
<span class="hljs-keyword">private</span> Integer code;
<span class="hljs-comment">/**
 * 响应信息
 */</span>
<span class="hljs-keyword">private</span> String message;

ResultCodeEnum(Integer code, String msg) {
    <span class="hljs-built_in">this</span>.code = code;
    <span class="hljs-built_in">this</span>.message = msg;
}

<span class="hljs-keyword">public</span> Integer <span class="hljs-title function_">getCode</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> code;
}

<span class="hljs-keyword">public</span> String <span class="hljs-title function_">getMessage</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> message;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setMessage</span><span class="hljs-params">(String message)</span> {
    <span class="hljs-built_in">this</span>.message = message;
}

}

  • 先封装一个 RPC 响应结果集RpcResult.java
public class RpcResult <T> implements Serializable {
<span class="hljs-comment">/**
 * 是否响应成功
 */</span>
<span class="hljs-keyword">private</span> Boolean success;
<span class="hljs-comment">/**
 * 响应状态码
 */</span>
<span class="hljs-keyword">private</span> Integer code;
<span class="hljs-comment">/**
 * 响应数据
 */</span>
<span class="hljs-keyword">private</span> T data;
<span class="hljs-comment">/**
 * 错误信息
 */</span>
<span class="hljs-keyword">private</span> String message;

<span class="hljs-comment">// 构造器开始</span>
<span class="hljs-comment">/**
 * 无参构造器(构造器私有,外部不可以直接创建)
 */</span>
<span class="hljs-keyword">private</span> <span class="hljs-title function_">RpcResult</span><span class="hljs-params">()</span> {
    <span class="hljs-built_in">this</span>.code = <span class="hljs-number">200</span>;
    <span class="hljs-built_in">this</span>.success = <span class="hljs-literal">true</span>;
}
<span class="hljs-comment">/**
 * 有参构造器
 * <span class="hljs-doctag">@param</span> obj
 */</span>
<span class="hljs-keyword">private</span> <span class="hljs-title function_">RpcResult</span><span class="hljs-params">(T obj)</span> {
    <span class="hljs-built_in">this</span>.code = <span class="hljs-number">200</span>;
    <span class="hljs-built_in">this</span>.data = obj;
    <span class="hljs-built_in">this</span>.success = <span class="hljs-literal">true</span>;
}

<span class="hljs-comment">/**
 * 有参构造器
 * <span class="hljs-doctag">@param</span> resultCode
 */</span>
<span class="hljs-keyword">private</span> <span class="hljs-title function_">RpcResult</span><span class="hljs-params">(ResultCodeEnum resultCode)</span> {
    <span class="hljs-built_in">this</span>.success = <span class="hljs-literal">false</span>;
    <span class="hljs-built_in">this</span>.code = resultCode.getCode();
    <span class="hljs-built_in">this</span>.message = resultCode.getMessage();
}
<span class="hljs-comment">// 构造器结束</span>

<span class="hljs-comment">/**
 * 通用返回成功(没有返回结果)
 * <span class="hljs-doctag">@param</span> &lt;T&gt;
 * <span class="hljs-doctag">@return</span>
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span>&lt;T&gt; RpcResult&lt;T&gt; <span class="hljs-title function_">success</span><span class="hljs-params">()</span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RpcResult</span>();
}

<span class="hljs-comment">/**
 * 返回成功(有返回结果)
 * <span class="hljs-doctag">@param</span> data
 * <span class="hljs-doctag">@param</span> &lt;T&gt;
 * <span class="hljs-doctag">@return</span>
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span>&lt;T&gt; RpcResult&lt;T&gt; <span class="hljs-title function_">success</span><span class="hljs-params">(T data)</span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RpcResult</span>&lt;T&gt;(data);
}

<span class="hljs-comment">/**
 * 通用返回失败
 * <span class="hljs-doctag">@param</span> resultCode
 * <span class="hljs-doctag">@param</span> &lt;T&gt;
 * <span class="hljs-doctag">@return</span>
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span>&lt;T&gt; RpcResult&lt;T&gt; <span class="hljs-title function_">failure</span><span class="hljs-params">(ResultCodeEnum resultCode)</span>{
    <span class="hljs-keyword">return</span>  <span class="hljs-keyword">new</span> <span class="hljs-title class_">RpcResult</span>&lt;T&gt;(resultCode);
}

<span class="hljs-keyword">public</span> Boolean <span class="hljs-title function_">getSuccess</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> success;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setSuccess</span><span class="hljs-params">(Boolean success)</span> {
    <span class="hljs-built_in">this</span>.success = success;
}

<span class="hljs-keyword">public</span> Integer <span class="hljs-title function_">getCode</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> code;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setCode</span><span class="hljs-params">(Integer code)</span> {
    <span class="hljs-built_in">this</span>.code = code;
}

<span class="hljs-keyword">public</span> T <span class="hljs-title function_">getData</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> data;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setData</span><span class="hljs-params">(T data)</span> {
    <span class="hljs-built_in">this</span>.data = data;
}

<span class="hljs-keyword">public</span> String <span class="hljs-title function_">getMessage</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> message;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setMessage</span><span class="hljs-params">(String message)</span> {
    <span class="hljs-built_in">this</span>.message = message;
}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> String <span class="hljs-title function_">toString</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"RpcResult{"</span> +
            <span class="hljs-string">"success="</span> + success +
            <span class="hljs-string">", code="</span> + code +
            <span class="hljs-string">", data="</span> + data +
            <span class="hljs-string">", message='"</span> + message + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">'}'</span>;
}

}

3.3 编写一个 RPC 接口

public interface OrderDubboService {
    RpcResult<OrderDomain> getOrder();
}

实体OrderDomain.java挺简单的,详见 Github 仓库。

四、order-provider

此子项目是一个服务类项目,也就是将接口服务注册到zookeeper注册中心供消费端调取使用。

4.1 项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.van.order</groupId>
        <artifactId>order</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order-provider<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>${project.artifactId}<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">description</span>&gt;</span>Dubbo 服务提供者<span class="hljs-tag">&lt;/<span class="hljs-name">description</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order-api<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- zookeeper依赖 --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo-dependencies-zookeeper<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${dubbo.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">exclusions</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">exclusion</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>slf4j-log4j12<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">exclusion</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">exclusions</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>

</project>

4.2 服务实现接口

@Service
public class OrderDubboServiceImpl implements OrderDubboService {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> RpcResult&lt;OrderDomain&gt; <span class="hljs-title function_">getOrder</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> RpcResult.success(<span class="hljs-keyword">new</span> <span class="hljs-title class_">OrderDomain</span>(<span class="hljs-number">1</span>, <span class="hljs-number">10086</span>, LocalDateTime.now()));
}

}

注意:
@Servicedubbo 包下面的注解不是 Spring 里面的注解。

4.3 项目配置

  1. dubbo 的配置直接用 dubbo,不再以 Spring 开头;
  2. base-packages:指定接口实现所在路径。
server:
  # 服务端口
  port: 7777
spring:
  application:
    name: order-provider
# dubbo 相关配置(dubbo 的配置不再以 Spring 开头)
dubbo:
  application:
    # 应用名称
    name: order-provider
  scan:
    # 接口实现者(服务实现)包
    base-packages: cn.van.order.service.impl
  # 注册中心信息
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    # 协议名称
    name: dubbo
    # 协议端口
    port: 20880

五、order-consumer

此子项目就是一个消费项目,比如商品模块、财务模块等等。

5.1 项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order-consumer<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>${project.artifactId}<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">description</span>&gt;</span>Dubbo 消费者<span class="hljs-tag">&lt;/<span class="hljs-name">description</span>&gt;</span>


<span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>cn.van.order<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>order-api<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- web项目依赖 --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- dubbo依赖 --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- dubbo的zookeeper依赖 --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo-dependencies-zookeeper<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${dubbo.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">exclusions</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">exclusion</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>slf4j-log4j12<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">exclusion</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">exclusions</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>

</project>

5.2 测试接口

模拟一个接口获取订单详情。

@RestController
@RequestMapping("/order")
public class OrderConsumerController {
    @Reference
    OrderDubboService orderDubboService;
<span class="hljs-meta">@GetMapping("getOrder")</span>
<span class="hljs-keyword">public</span> RpcResult <span class="hljs-title function_">getOrder</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> orderDubboService.getOrder();
}

}

注意:@Reference引入的是 Dubbo 接口,所以是 Dubbo 的注解。

5.3 配置文件

server:
  port: 7000
spring:
  application:
    name: order-consumer
# dubbo 相关配置
dubbo:
  application:
    name: order-consumer
  registry:
    address: zookeeper://127.0.0.1:2181

六、测试

一切就绪,如果在order-consumer 的测试接口能成功请求到数据,则证明 Dubbo 服务搭建成功。

6.1 启动 zookeeper

我们选用zookeeper作为注册中心,因此启动项目之前需要先启动它。

6.2 dubbo-admin

dubbo-admin 便于观察 order-provider 是否成功将接口注册,具体安装步骤详见apache/dubbo-admin

默认端口:8080

6.3 启动 dubbo-provider

成功启动后可以在dubbo-admin:已经成功将接口 OrderService 注册到 zookeeper 上如下:

风尘博客

成功将借口注册到注册中心,说明dubbo-provider 注册成功。

6.4 启动 order-cosumer

启动消费者项目,在浏览器请求消费接口:http://localhost:7000/order/getOrder,成功返回数据如下:

{
    "success":true,
    "code":200,
    "data":{
        "id":1,
        "orderNum":10086,
        "gmtCreate":"2020-05-06T11:59:45.535"
    },
    "message":null
}

成功请求到 order-provider 提供的数据,说明 Dubbo 搭建成功!

七、总结

以上的完整代码我已上传到 Github,需要的可以自取测试,欢迎star

文化交流

  1. 风尘博客
  2. 风尘博客 - 掘金
  3. 风尘博客 - 博客园
  4. 风尘博客 -CSDN
  5. Github