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 配置))
- [(1)`pom.xml` 依赖](#(1)
- [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 并测试))
- [(1)`pom.xml` 依赖(与 Provider 一致)](#(1)
- [1. 服务提供者(`dubbo-provider`)](#1. 服务提供者(
- [五、JavaConfig 配置方式实现](#五、JavaConfig 配置方式实现)
-
- [1. 服务提供者(`dubbo-provider`)](#1. 服务提供者(
dubbo-provider)) -
- [(1)配置类 `DubboProviderConfig`](#(1)配置类
DubboProviderConfig) - [(2)服务实现类(用 `@DubboService` 注解)](#(2)服务实现类(用
@DubboService注解)) - (3)启动类(导入配置类)
- [(1)配置类 `DubboProviderConfig`](#(1)配置类
- [2. 服务消费者(`dubbo-consumer`)](#2. 服务消费者(
dubbo-consumer)) -
- [(1)配置类 `DubboConsumerConfig`](#(1)配置类
DubboConsumerConfig) - [(2)调用远程服务的组件(用 `@DubboReference` 注解)](#(2)调用远程服务的组件(用
@DubboReference注解)) - (3)启动类(测试调用)
- [(1)配置类 `DubboConsumerConfig`](#(1)配置类
- [1. 服务提供者(`dubbo-provider`)](#1. 服务提供者(
- 六、运行与验证
-
- [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模块)) -
- (1)实现接口(服务逻辑)
- [(2)配置服务暴露(Dubbo 配置)](#(2)配置服务暴露(Dubbo 配置))
-
- [方式 1:JavaConfig 配置(推荐)](#方式 1:JavaConfig 配置(推荐))
- [方式 2:XML 配置(传统方式)](#方式 2:XML 配置(传统方式))
- (3)启动类(加载配置)
- [3. 服务消费者引用接口(`dubbo-consumer` 模块)](#3. 服务消费者引用接口(
dubbo-consumer模块)) -
- (1)引用接口(注入代理对象)
- [(2)配置 Dubbo 消费者(可选,若未全局配置)](#(2)配置 Dubbo 消费者(可选,若未全局配置))
- (3)启动类(测试调用)
- [1. 定义公共接口(`dubbo-api` 模块)](#1. 定义公共接口(
- 三、测试验证
-
- [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):
- 下载地址:https://zookeeper.apache.org/releases.html
- 启动命令:
bin/zkServer.sh start(Linux/Mac)或bin/zkServer.cmd(Windows)
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)
七、关键说明
- Java 8 兼容:Dubbo 3.1.5 完全支持 Java 8,无需额外配置。
- Spring Boot 2.7 集成 :通过
dubbo-spring-boot-starter自动配置 Dubbo 组件,兼容 Spring Boot 2.7.x。 - 注册中心:Provider 启动时将服务注册到 ZooKeeper,Consumer 启动时订阅服务列表。
- 配置差异 :
- XML 配置:通过
<dubbo:service>/<dubbo:reference>声明服务暴露/引用。 - JavaConfig:通过
@DubboService/@DubboReference注解 +@EnableDubbo实现。
- XML 配置:通过
八、新增一个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 或注解暴露服务。以下提供 JavaConfig 和 XML 两种配置方式(任选其一)。
方式 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,避免序列化失败。
五、常见问题排查
- 接口找不到 :检查
dubbo-api模块是否被 Provider 和 Consumer 正确依赖。 - 服务未注册:检查 Provider 的注册中心地址是否正确,ZooKeeper 是否启动。
- 调用失败 :检查 Consumer 的
@DubboReference是否正确注入,接口名是否匹配。
九、扩展建议
- 多注册中心:可配置多个注册中心(如 ZooKeeper + Nacos),提高可用性。
- 负载均衡 :通过
@DubboReference(loadbalance = "roundrobin")配置负载均衡策略。 - 超时与重试 :通过
@DubboReference(timeout = 3000, retries = 2)配置调用超时和重试次数。
相关文献
【微服务组件】Dubbo底层原理以及核心代码解读
【微服务知识】开源RPC框架Dubbo入门介绍
Dubbo框架微服务开发
Dubbo3.x速览