【微服务组件】Springboot结合Dubbo实现RPC调用

Springboot结合Dubbo实现RPC调用

    • 一、环境准备
      • [1. 依赖版本](#1. 依赖版本)
    • 二、项目结构
    • [三、公共接口定义(`dubbo-api` 模块)](#三、公共接口定义(dubbo-api 模块))
    • [四、XML 配置方式实现](#四、XML 配置方式实现)
      • [1. 服务提供者(`dubbo-provider`)](#1. 服务提供者(dubbo-provider))
        • [(1)`pom.xml` 依赖](#(1)pom.xml 依赖)
        • [(2)XML 配置文件 `dubbo-provider.xml`](#(2)XML 配置文件 dubbo-provider.xml)
        • (3)服务实现类
        • [(4)启动类(加载 XML 配置)](#(4)启动类(加载 XML 配置))
      • [2. 服务消费者(`dubbo-consumer`)](#2. 服务消费者(dubbo-consumer))
        • [(1)`pom.xml` 依赖(与 Provider 一致)](#(1)pom.xml 依赖(与 Provider 一致))
        • [(2)XML 配置文件 `dubbo-consumer.xml`](#(2)XML 配置文件 dubbo-consumer.xml)
        • (3)调用远程服务的组件
        • [(4)启动类(加载 XML 并测试)](#(4)启动类(加载 XML 并测试))
    • [五、JavaConfig 配置方式实现](#五、JavaConfig 配置方式实现)
      • [1. 服务提供者(`dubbo-provider`)](#1. 服务提供者(dubbo-provider))
        • [(1)配置类 `DubboProviderConfig`](#(1)配置类 DubboProviderConfig)
        • [(2)服务实现类(用 `@DubboService` 注解)](#(2)服务实现类(用 @DubboService 注解))
        • (3)启动类(导入配置类)
      • [2. 服务消费者(`dubbo-consumer`)](#2. 服务消费者(dubbo-consumer))
        • [(1)配置类 `DubboConsumerConfig`](#(1)配置类 DubboConsumerConfig)
        • [(2)调用远程服务的组件(用 `@DubboReference` 注解)](#(2)调用远程服务的组件(用 @DubboReference 注解))
        • (3)启动类(测试调用)
    • 六、运行与验证
      • [1. 启动注册中心(ZooKeeper)](#1. 启动注册中心(ZooKeeper))
      • [2. 启动服务提供者](#2. 启动服务提供者)
      • [3. 启动服务消费者](#3. 启动服务消费者)
    • 七、关键说明
    • 八、新增一个Provider服务完整步骤
      • 一、前置准备
        • [1. 项目结构(已有 Dubbo 环境)](#1. 项目结构(已有 Dubbo 环境))
      • 二、新增数据提供接口(核心步骤)
        • [1. 定义公共接口(`dubbo-api` 模块)](#1. 定义公共接口(dubbo-api 模块))
        • [2. 服务提供者实现接口(`dubbo-provider` 模块)](#2. 服务提供者实现接口(dubbo-provider 模块))
        • [3. 服务消费者引用接口(`dubbo-consumer` 模块)](#3. 服务消费者引用接口(dubbo-consumer 模块))
      • 三、测试验证
        • [1. 启动注册中心(ZooKeeper)](#1. 启动注册中心(ZooKeeper))
        • [2. 启动服务提供者](#2. 启动服务提供者)
        • [3. 启动服务消费者](#3. 启动服务消费者)
      • 四、关键说明
        • [1. 接口共享](#1. 接口共享)
        • [2. 服务暴露与引用](#2. 服务暴露与引用)
        • [3. 注册中心](#3. 注册中心)
        • [4. 序列化](#4. 序列化)
      • 五、常见问题排查
    • 九、扩展建议
    • 相关文献

以下是基于 Java 8 + Spring Boot 2.7.x + Dubbo 3.1.5 的完整 RPC 实现示例,包含 XML 配置JavaConfig 配置 两种方式,覆盖 公共接口、服务提供者、服务消费者 全流程。

一、环境准备

1. 依赖版本

组件 版本
Spring Boot 2.7.18
Dubbo 3.1.5
Dubbo Spring Boot Starter 3.1.5
ZooKeeper 客户端(Curator) 5.3.0
JDK 1.8

二、项目结构

复制代码
dubbo-demo-java8/
├── dubbo-api/          # 公共接口模块(Provider/Consumer 共享)
├── dubbo-provider/     # 服务提供者(暴露 RPC 服务)
└── dubbo-consumer/     # 服务消费者(调用远程 RPC 服务)

三、公共接口定义(dubbo-api 模块)

定义服务接口,Provider 实现、Consumer 引用此接口:

java 复制代码
// com/example/api/UserService.java
package com.example.api;

public interface UserService {
    /**
     * 根据用户ID获取用户信息
     * @param userId 用户ID
     * @return 用户信息字符串
     */
    String getUserInfo(Long userId);
}

四、XML 配置方式实现

1. 服务提供者(dubbo-provider

(1)pom.xml 依赖
xml 复制代码
<dependencies>
    <!-- Spring Boot 基础 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.7.18</version>
    </dependency>

    <!-- Dubbo Spring Boot Starter -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>3.1.5</version>
    </dependency>

    <!-- ZooKeeper 客户端(注册中心) -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>5.3.0</version>
    </dependency>

    <!-- 公共接口模块 -->
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>dubbo-api</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>
(2)XML 配置文件 dubbo-provider.xml

src/main/resources 下创建 XML 配置:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 1. 应用配置(必填) -->
    <dubbo:application name="dubbo-provider-java8"/>

    <!-- 2. 注册中心配置(ZooKeeper) -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- 3. 协议配置(Dubbo 协议 + 端口 20880) -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- 4. 服务暴露:绑定接口与实现类 -->
    <dubbo:service interface="com.example.api.UserService" ref="userService"/>
    <bean id="userService" class="com.example.provider.service.UserServiceImpl"/>
</beans>
(3)服务实现类
java 复制代码
// com/example/provider/service/UserServiceImpl.java
package com.example.provider.service;

import com.example.api.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public String getUserInfo(Long userId) {
        return "【Provider】User-" + userId + "(XML配置·Java8)";
    }
}
(4)启动类(加载 XML 配置)
java 复制代码
// DubboProviderApplication.java
package com.example.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource(locations = "classpath:dubbo-provider.xml") // 加载 Dubbo XML 配置
public class DubboProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplication.class, args);
        System.out.println("Dubbo Provider(XML·Java8)已启动");
    }
}

2. 服务消费者(dubbo-consumer

(1)pom.xml 依赖(与 Provider 一致)
xml 复制代码
<!-- 依赖同 dubbo-provider,仅替换 artifactId -->
<artifactId>dubbo-consumer</artifactId>
(2)XML 配置文件 dubbo-consumer.xml
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 1. 应用配置 -->
    <dubbo:application name="dubbo-consumer-java8"/>

    <!-- 2. 注册中心配置(与 Provider 一致) -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- 3. 服务引用:生成远程服务的本地代理 -->
    <dubbo:reference id="userService" interface="com.example.api.UserService"/>
</beans>
(3)调用远程服务的组件
java 复制代码
// com/example/consumer/service/ConsumerService.java
package com.example.consumer.service;

import com.example.api.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class ConsumerService {
    @Resource // 注入 Dubbo 生成的代理对象
    private UserService userService;

    public String callProvider(Long userId) {
        return userService.getUserInfo(userId);
    }
}
(4)启动类(加载 XML 并测试)
java 复制代码
// DubboConsumerApplication.java
package com.example.consumer;

import com.example.consumer.service.ConsumerService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource(locations = "classpath:dubbo-consumer.xml")
public class DubboConsumerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DubboConsumerApplication.class, args);
        
        // 测试调用远程服务
        ConsumerService consumer = context.getBean(ConsumerService.class);
        String result = consumer.callProvider(1L);
        System.out.println("Consumer 调用结果(XML·Java8):" + result);
        
        context.close();
    }
}

五、JavaConfig 配置方式实现

1. 服务提供者(dubbo-provider

(1)配置类 DubboProviderConfig
java 复制代码
// DubboProviderConfig.java
package com.example.provider.config;

import com.example.api.UserService;
import com.example.provider.service.UserServiceImpl;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDubbo(scanBasePackages = "com.example.provider.service") // 扫描 @DubboService 注解
public class DubboProviderConfig {

    // 1. 应用配置
    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig config = new ApplicationConfig();
        config.setName("dubbo-provider-java8-config");
        return config;
    }

    // 2. 注册中心配置
    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig config = new RegistryConfig();
        config.setAddress("zookeeper://127.0.0.1:2181");
        return config;
    }

    // 3. 协议配置
    @Bean
    public ProtocolConfig protocolConfig() {
        ProtocolConfig config = new ProtocolConfig();
        config.setName("dubbo");
        config.setPort(20881); // 与 XML 端口区分(测试用)
        return config;
    }

    // 4. 服务暴露(绑定接口与实现类)
    @Bean
    public ServiceConfig<UserService> userServiceConfig(UserService userService) {
        ServiceConfig<UserService> config = new ServiceConfig<>();
        config.setInterface(UserService.class);
        config.setRef(userService);
        config.setProtocol(protocolConfig()); // 使用上面的协议配置
        return config;
    }
}
(2)服务实现类(用 @DubboService 注解)
java 复制代码
// com/example/provider/service/UserServiceImpl.java
package com.example.provider.service;

import com.example.api.UserService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService // 暴露服务(等价于 XML 的 <dubbo:service>)
public class UserServiceImpl implements UserService {
    @Override
    public String getUserInfo(Long userId) {
        return "【Provider】User-" + userId + "(JavaConfig·Java8)";
    }
}
(3)启动类(导入配置类)
java 复制代码
// DubboProviderApplication.java
package com.example.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import(DubboProviderConfig.class) // 导入 Dubbo 配置类
public class DubboProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplication.class, args);
        System.out.println("Dubbo Provider(JavaConfig·Java8)已启动");
    }
}

2. 服务消费者(dubbo-consumer

(1)配置类 DubboConsumerConfig
java 复制代码
// DubboConsumerConfig.java
package com.example.consumer.config;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDubbo(scanBasePackages = "com.example.consumer.service") // 扫描 @DubboReference
public class DubboConsumerConfig {

    // 1. 应用配置
    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig config = new ApplicationConfig();
        config.setName("dubbo-consumer-java8-config");
        return config;
    }

    // 2. 注册中心配置(与 Provider 一致)
    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig config = new RegistryConfig();
        config.setAddress("zookeeper://127.0.0.1:2181");
        return config;
    }
}
(2)调用远程服务的组件(用 @DubboReference 注解)
java 复制代码
// com/example/consumer/service/ConsumerService.java
package com.example.consumer.service;

import com.example.api.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

@Service
public class ConsumerService {
    @DubboReference // 引用远程服务(生成代理对象)
    private UserService userService;

    public String callProvider(Long userId) {
        return userService.getUserInfo(userId);
    }
}
(3)启动类(测试调用)
java 复制代码
// DubboConsumerApplication.java
package com.example.consumer;

import com.example.consumer.service.ConsumerService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import(DubboConsumerConfig.class)
public class DubboConsumerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DubboConsumerApplication.class, args);
        
        // 测试调用
        ConsumerService consumer = context.getBean(ConsumerService.class);
        String result = consumer.callProvider(1L);
        System.out.println("Consumer 调用结果(JavaConfig·Java8):" + result);
        
        context.close();
    }
}

六、运行与验证

1. 启动注册中心(ZooKeeper)

下载并启动 ZooKeeper(默认端口 2181):

2. 启动服务提供者

  • XML 配置:运行 DubboProviderApplication(XML 版)。
  • JavaConfig 配置:运行 DubboProviderApplication(JavaConfig 版)。

3. 启动服务消费者

运行 DubboConsumerApplication,控制台输出:

复制代码
Consumer 调用结果(XML·Java8):【Provider】User-1(XML配置·Java8)
# 或
Consumer 调用结果(JavaConfig·Java8):【Provider】User-1(JavaConfig·Java8)

七、关键说明

  1. Java 8 兼容:Dubbo 3.1.5 完全支持 Java 8,无需额外配置。
  2. Spring Boot 2.7 集成 :通过 dubbo-spring-boot-starter 自动配置 Dubbo 组件,兼容 Spring Boot 2.7.x。
  3. 注册中心:Provider 启动时将服务注册到 ZooKeeper,Consumer 启动时订阅服务列表。
  4. 配置差异
    • XML 配置:通过 <dubbo:service>/<dubbo:reference> 声明服务暴露/引用。
    • JavaConfig:通过 @DubboService/@DubboReference 注解 + @EnableDubbo 实现。

八、新增一个Provider服务完整步骤

Spring Boot 2.7.x + Java 8 环境下新增一个 Dubbo 数据提供接口,需遵循 接口定义→服务实现→服务暴露→服务引用→测试验证 的流程。以下是完整详细步骤,包含代码和配置示例(基于 Dubbo 3.1.5)。

一、前置准备

1. 项目结构(已有 Dubbo 环境)

假设已有 Dubbo 基础项目,结构如下(新增接口需扩展):

复制代码
dubbo-demo/
├── dubbo-api/          # 公共接口模块(新增接口放此处)
├── dubbo-provider/     # 服务提供者(实现新增接口)
└── dubbo-consumer/     # 服务消费者(引用新增接口)

二、新增数据提供接口(核心步骤)

1. 定义公共接口(dubbo-api 模块)

在公共接口模块 dubbo-api 中新增数据提供接口,例如 UserDataService(获取用户数据):

java 复制代码
// com/example/api/UserDataService.java
package com.example.api;

import java.util.List;

/**
 * 新增:用户数据提供接口(Dubbo 服务接口)
 */
public interface UserDataService {
    /**
     * 根据用户ID列表获取用户信息
     * @param userIds 用户ID列表
     * @return 用户信息列表
     */
    List<User> getUserList(List<Long> userIds);

    /**
     * 新增用户数据
     * @param user 用户对象
     * @return 新增结果(成功/失败)
     */
    boolean addUser(User user);
}

// 用户实体类(需序列化,Dubbo 传输需要)
class User implements java.io.Serializable {
    private Long id;
    private String name;
    private Integer age;

    // 构造方法、Getter/Setter 省略(实际需补充)
}

说明

  • 接口需定义在 dubbo-api 模块,Provider 和 Consumer 共享此接口。
  • 实体类需实现 Serializable,避免 Dubbo 序列化失败。
2. 服务提供者实现接口(dubbo-provider 模块)

在服务提供者中实现 UserDataService 接口,并通过 Dubbo 注解暴露服务。

(1)实现接口(服务逻辑)
java 复制代码
// com/example/provider/service/UserDataServiceImpl.java
package com.example.provider.service;

import com.example.api.User;
import com.example.api.UserDataService;
import org.apache.dubbo.config.annotation.DubboService;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@DubboService // Dubbo 3.x 注解:暴露服务(等价于 XML 的 <dubbo:service>)
public class UserDataServiceImpl implements UserDataService {

    /**
     * 模拟数据库查询:根据用户ID列表获取用户信息
     */
    @Override
    public List<User> getUserList(List<Long> userIds) {
        // 模拟数据:从数据库查询(实际替换为真实 DAO 调用)
        return userIds.stream()
                .map(id -> new User(id, "User-" + id, 20 + id % 10))
                .collect(Collectors.toList());
    }

    /**
     * 模拟数据库插入:新增用户数据
     */
    @Override
    public boolean addUser(User user) {
        // 模拟插入数据库(实际替换为真实 DAO 调用)
        System.out.println("新增用户成功:" + user.getName());
        return true; // 返回操作结果
    }
}
(2)配置服务暴露(Dubbo 配置)

需配置 Dubbo 的应用名、注册中心、协议 ,并通过 ServiceConfig 或注解暴露服务。以下提供 JavaConfigXML 两种配置方式(任选其一)。

方式 1:JavaConfig 配置(推荐)

创建 DubboProviderConfig 配置类,定义 Dubbo 核心组件:

java 复制代码
// DubboProviderConfig.java
package com.example.provider.config;

import com.example.api.UserDataService;
import com.example.provider.service.UserDataServiceImpl;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDubbo(scanBasePackages = "com.example.provider.service") // 扫描 @DubboService 注解
public class DubboProviderConfig {

    // 1. 应用配置(必填)
    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig config = new ApplicationConfig();
        config.setName("dubbo-provider-userdata"); // 应用名(唯一标识)
        return config;
    }

    // 2. 注册中心配置(ZooKeeper)
    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig config = new RegistryConfig();
        config.setAddress("zookeeper://127.0.0.1:2181"); // ZooKeeper 地址
        return config;
    }

    // 3. 协议配置(Dubbo 协议 + 端口)
    @Bean
    public ProtocolConfig protocolConfig() {
        ProtocolConfig config = new ProtocolConfig();
        config.setName("dubbo"); // 协议名(默认 dubbo)
        config.setPort(20880); // 端口(默认 20880,可自定义)
        return config;
    }

    // 4. 服务暴露:绑定接口与实现类
    @Bean
    public ServiceConfig<UserDataService> userDataServiceConfig(UserDataService userService) {
        ServiceConfig<UserDataService> config = new ServiceConfig<>();
        config.setInterface(UserDataService.class); // 接口类
        config.setRef(userService); // 接口实现类(@DubboService 已注入)
        config.setProtocol(protocolConfig()); // 使用配置的协议
        return config;
    }
}
方式 2:XML 配置(传统方式)

src/main/resources 下创建 dubbo-provider.xml,声明服务暴露:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 应用配置 -->
    <dubbo:application name="dubbo-provider-userdata"/>

    <!-- 注册中心配置 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!-- 协议配置 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- 服务暴露:绑定接口与实现类 -->
    <dubbo:service interface="com.example.api.UserDataService" ref="userDataService"/>
    <bean id="userDataService" class="com.example.provider.service.UserDataServiceImpl"/>
</beans>

说明

  • 若用 XML 配置,服务实现类无需 @DubboService 注解,通过 <dubbo:service> 声明暴露。
(3)启动类(加载配置)
java 复制代码
// DubboProviderApplication.java
package com.example.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import; // JavaConfig 需导入配置类
// 或 XML 配置:import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
// JavaConfig 方式:导入 Dubbo 配置类
@Import(DubboProviderConfig.class)
// XML 配置方式:加载 XML 文件(二选一)
// @ImportResource(locations = "classpath:dubbo-provider.xml")
public class DubboProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplication.class, args);
        System.out.println("Dubbo Provider(用户数据服务)已启动");
    }
}
3. 服务消费者引用接口(dubbo-consumer 模块)

在服务消费者中引用新增的 UserDataService 接口,通过 Dubbo 代理调用远程服务。

(1)引用接口(注入代理对象)
java 复制代码
// com/example/consumer/service/UserDataConsumerService.java
package com.example.consumer.service;

import com.example.api.User;
import com.example.api.UserDataService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

@Service
public class UserDataConsumerService {

    /**
     * 引用远程服务(Dubbo 生成代理对象)
     */
    @DubboReference // 等价于 XML 的 <dubbo:reference>
    private UserDataService userDataService;

    /**
     * 调用远程方法:获取用户列表
     */
    public List<User> fetchUserList(List<Long> userIds) {
        return userDataService.getUserList(userIds);
    }

    /**
     * 调用远程方法:新增用户
     */
    public boolean addUser(User user) {
        return userDataService.addUser(user);
    }
}
(2)配置 Dubbo 消费者(可选,若未全局配置)

若消费者未全局配置 Dubbo,需创建 DubboConsumerConfig 配置类:

java 复制代码
// DubboConsumerConfig.java
package com.example.consumer.config;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDubbo(scanBasePackages = "com.example.consumer.service") // 扫描 @DubboReference
public class DubboConsumerConfig {

    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig config = new ApplicationConfig();
        config.setName("dubbo-consumer-userdata");
        return config;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig config = new RegistryConfig();
        config.setAddress("zookeeper://127.0.0.1:2181");
        return config;
    }
}
(3)启动类(测试调用)
java 复制代码
// DubboConsumerApplication.java
package com.example.consumer;

import com.example.consumer.service.UserDataConsumerService;
import com.example.api.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import; // JavaConfig 方式
// 或 XML 配置:import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
// JavaConfig 方式:导入 Dubbo 配置类
@Import(DubboConsumerConfig.class)
// XML 配置方式:加载 XML 文件(二选一)
// @ImportResource(locations = "classpath:dubbo-consumer.xml")
public class DubboConsumerApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DubboConsumerApplication.class, args);

        // 测试调用新增接口
        UserDataConsumerService consumer = context.getBean(UserDataConsumerService.class);

        // 测试获取用户列表
        List<Long> userIds = Arrays.asList(1L, 2L, 3L);
        List<User> users = consumer.fetchUserList(userIds);
        System.out.println("获取用户列表结果:" + users);

        // 测试新增用户
        User newUser = new User(4L, "NewUser", 25);
        boolean success = consumer.addUser(newUser);
        System.out.println("新增用户结果:" + success);

        context.close();
    }
}

三、测试验证

1. 启动注册中心(ZooKeeper)

确保 ZooKeeper 已启动(默认端口 2181):

bash 复制代码
# Linux/Mac
bin/zkServer.sh start

# Windows
bin/zkServer.cmd
2. 启动服务提供者

运行 DubboProviderApplication,控制台输出:

复制代码
Dubbo Provider(用户数据服务)已启动
3. 启动服务消费者

运行 DubboConsumerApplication,控制台输出:

复制代码
获取用户列表结果:[User{id=1, name='User-1', age=21}, User{id=2, name='User-2', age=22}, User{id=3, name='User-3', age=23}]
新增用户成功:NewUser
新增用户结果:true

四、关键说明

1. 接口共享

dubbo-api 模块的接口需被 Provider 和 Consumer 依赖,确保接口定义一致。

2. 服务暴露与引用
  • Provider :通过 @DubboService(注解)或 <dubbo:service>(XML)暴露服务。
  • Consumer :通过 @DubboReference(注解)或 <dubbo:reference>(XML)注入代理对象。
3. 注册中心

Provider 启动时将服务注册到 ZooKeeper,Consumer 启动时订阅注册中心的服务列表,实现动态发现。

4. 序列化

Dubbo 默认使用 Hessian2 序列化,实体类需实现 Serializable,避免序列化失败。

五、常见问题排查

  1. 接口找不到 :检查 dubbo-api 模块是否被 Provider 和 Consumer 正确依赖。
  2. 服务未注册:检查 Provider 的注册中心地址是否正确,ZooKeeper 是否启动。
  3. 调用失败 :检查 Consumer 的 @DubboReference 是否正确注入,接口名是否匹配。

九、扩展建议

  • 多注册中心:可配置多个注册中心(如 ZooKeeper + Nacos),提高可用性。
  • 负载均衡 :通过 @DubboReference(loadbalance = "roundrobin") 配置负载均衡策略。
  • 超时与重试 :通过 @DubboReference(timeout = 3000, retries = 2) 配置调用超时和重试次数。

相关文献

【微服务组件】Dubbo底层原理以及核心代码解读
【微服务知识】开源RPC框架Dubbo入门介绍
Dubbo框架微服务开发
Dubbo3.x速览

相关推荐
I'm Jie4 小时前
(二)Gradle 依赖仓库及安全凭证配置
java·spring boot·spring·gradle·maven
老王熬夜敲代码4 小时前
ES安装和简单讲解
c++·微服务
李少兄5 小时前
记一次 Spring Boot 项目中 Redis 工具类的重构实践
spring boot·redis·重构
摇滚侠6 小时前
Spring Boot3零基础教程,生命周期启动加载机制,笔记64
spring boot·笔记
摇滚侠6 小时前
Spring Boot3零基础教程,整合 Redis,笔记69
spring boot·redis·笔记
bug攻城狮7 小时前
Spring Boot 2.6+ 整合 PageHelper 启动报错:循环依赖解决方案全解析
java·spring boot·后端
摇滚侠8 小时前
Spring Boot3零基础教程,生命周期监听,自定义监听器,笔记59
java·开发语言·spring boot·笔记
摇滚侠9 小时前
Spring Boot3零基础教程,事件驱动开发,设计登录成功后增加积分记录信息功能,笔记61
java·spring boot·笔记·后端
这周也會开心10 小时前
SpringBoot的搭建方式
java·spring boot·后端