大纲
前言
学习资源
版本对应关系
Spring 与 Dubbo 的版本必须互相匹配,否则不同版本之间可能会存在兼容性问题,最终导致服务无法正常运行。两者的版本对应关系如下:
Dubbo 版本 | 适配 Spring 版本 | 核心特性 / 注意事项 |
---|
Dubbo 3.x (3.3.0+) | ✅ Spring 6.x ✅ Spring 5.3+ | (1) 原生支持 Spring 6 注解驱动 (2) 依赖 Jakarta EE 9+(需 JDK 17+) (3) 默认集成 Spring Boot 3.x |
Dubbo 3.0.x (3.0.0 - 3.2.x) | ✅ Spring 5.3+ ⚠️ Spring 6.x(需手动适配) | (1) 需手动排除旧版 Jakarta API(jakarta.* ) (2) 建议搭配 Spring Boot 2.7+ |
Dubbo 2.7.x | ✅ Spring 5.2+ ❌ Spring 6.x | (1) 仅支持 Java EE(javax.* ) (2) 官方已停止维护,仅建议旧项目使用 |
Dubbo 整合案例
本节将整合 Spring、SpringMVC 与 Dubbo,并使用 ZooKeeper 作为 Dubbo 的注册中心。
项目结构
版本说明
组件 | 版本 | 说明 |
---|
Spring | 5.2.25.RELEASE | |
Dubbo | 2.7.23 | |
Zookeeper Server | 3.5.7 | ZooKeeper 服务器,作为服务注册中心 |
Curator Recipes | 5.5.0 | 用于 Dubbo 连接 ZooKeeper 注册中心,依赖 Curator Client 5.5.0 和 ZooKeeper Client 3.7.1 |
JDK | 1.8 | 支持 JDK 1.8 及以上版本 |
模块说明
api
:抽取出来的公共模块,存放公用的实体类和接口provider
:服务提供者,实现 api
模块中的接口customer
:服务消费者,调用服务提供者中的接口
案例代码
API 模块
1 2 3 4 5
| public interface UserService {
String sayHello(String name);
}
|
Provider 模块
- 引入依赖,并添加 Maven 的 Tomcat 7 插件,方便一键将应用部署到 Tomcat 7 中运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| <properties> <javax.servlet.version>3.1.0</javax.servlet.version> <spring.version>5.2.25.RELEASE</spring.version> <dubbo.version>2.7.23</dubbo.version> <curator.version>5.5.0</curator.version> <commons.version>3.4</commons.version> <slf4j.version>1.7.21</slf4j.version> </properties>
<dependencies> <dependency> <groupId>com.clay.dubbo</groupId> <artifactId>dubbo-lesson-05-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>${curator.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>9000</port> <path>/</path> </configuration> </plugin> </plugins> </build>
|
- 接口实现类,
@DubboService
注解主要用于暴露服务,使其能够被 Dubbo 框架识别并注册到服务注册中心
1 2 3 4 5 6 7 8 9 10 11
| import org.apache.dubbo.config.annotation.DubboService;
@DubboService public class UserServiceImpl implements UserService {
@Override public String sayHello(String name) { return "Hello " + name; }
}
|
- Spring 的 XML 配置文件(
application-context.xml
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <?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" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.clay.dubbo.producer"/>
<dubbo:application name="dubbo-provider-application"> <dubbo:parameter key="qos.enable" value="true"/> <dubbo:parameter key="qos.port" value="22222"/> <dubbo:parameter key="qos.accept.foreign.ip" value="false"/> </dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181" timeout="5000"/>
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:annotation package="com.clay.dubbo.producer"/>
</beans>
|
- SpringMVC 的 XML 配置文件(
application-mvc.xml
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="com.clay.dubbo.producer.controller"/>
</beans>
|
- Java EE 的 XML 配置文件(
web.xml
),存放在项目中的 /src/main/webapp/WEB-INF
目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/Java EE" xsi:schemaLocation="http://java.sun.com/xml/ns/Java EE http://java.sun.com/xml/ns/Java EE/web-app_2_5.xsd" version="2.5">
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring/application-context.xml</param-value> </context-param>
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/application-mvc.xml</param-value> </init-param> </servlet>
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app>
|
- Log4j 的配置文件(
log4j.properties
)
1 2 3 4 5 6 7 8
| log4j.rootLogger=INFO, stdout, file log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=log/app.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
|
Consumer 模块
- 引入依赖,并添加 Maven 的 Tomcat 7 插件,方便一键将应用部署到 Tomcat 7 中运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| <properties> <javax.servlet.version>3.1.0</javax.servlet.version> <spring.version>5.2.25.RELEASE</spring.version> <dubbo.version>2.7.23</dubbo.version> <curator.version>5.5.0</curator.version> <commons.version>3.4</commons.version> <slf4j.version>1.7.21</slf4j.version> </properties>
<dependencies> <dependency> <groupId>com.clay.dubbo</groupId> <artifactId>dubbo-lesson-05-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>${curator.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8000</port> <path>/</path> </configuration> </plugin> </plugins> </build>
|
- 业务测试类,
@DubboReference
注解主要用于在服务消费者端引用远程服务提供者的服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import org.apache.dubbo.config.annotation.DubboReference;
@RestController @RequestMapping("/user") public class UserController {
@DubboReference private UserService userService;
@GetMapping("/sayHello/{name}") public String sayHello(@PathVariable("name") String name) { return userService.sayHello(name); }
}
|
- Spring 的 XML 配置文件(
application-context.xml
)
1 2 3 4 5 6 7 8 9 10 11
| <?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.clay.dubbo.consumer"/>
</beans>
|
- SpringMVC 的 XML 配置文件(
application-mvc.xml
)
特别注意
在服务消费者模块中,必须先扫描 Dubbo 的注解(如 @DubboReference
,为了引用远程服务),然后再扫描 Spring 的注解(如 @Controller
),否则会出现 @DubboReference
注解失效的问题,详细分析说明请看这里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<dubbo:application name="dubbo-consumer-application"> <dubbo:parameter key="qos.enable" value="true"/> <dubbo:parameter key="qos.port" value="22223"/> <dubbo:parameter key="qos.accept.foreign.ip" value="false"/> </dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181" timeout="5000"/>
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
<dubbo:annotation package="com.clay.dubbo.consumer"/>
<context:component-scan base-package="com.clay.dubbo.consumer.controller"/>
</beans>
|
- Java EE 的 XML 配置文件(
web.xml
),存放在项目中的 /src/main/webapp/WEB-INF
目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/Java EE" xsi:schemaLocation="http://java.sun.com/xml/ns/Java EE http://java.sun.com/xml/ns/Java EE/web-app_2_5.xsd" version="2.5">
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring/application-context.xml</param-value> </context-param>
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/application-mvc.xml</param-value> </init-param> </servlet>
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app>
|
- Log4j 的配置文件(
log4j.properties
)
1 2 3 4 5 6 7 8
| log4j.rootLogger=INFO, stdout, file log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=log/app.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
|
测试代码
- (1) 在 IDEA 开发工具内,通过 Tomcat 的 Maven 插件分别按顺序一键运行 Provider 和 Consumer 模块,如下图所示:
![]()
- (2) 使用 Postman 等工具访问
http://127.0.0.1:8000/user/sayHello/dubbo
接口,若接口可以返回 Hello dubbo
结果,则说明 Spring 与 SpringMVC 整合 Dubbo 成功。
下载代码
- 完整的案例代码可以直接从 GitHub 下载对应章节
dubbo-lesson-05
。
使用 Nacos 注册中心
- (1) 由于不再使用 ZooKeeper 作为注册中心,因此需要移除
curator-recipes
依赖
- (2) 由于需要使用 Nacos 作为注册中心,因此需要引入
dubbo-registry-nacos
依赖
1 2 3 4 5 6 7 8 9 10 11 12 13
| <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.23</version> </dependency>
<dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-common</artifactId> <version>1.4.3</version> </dependency>
|
- (3) 在 Provider 和 Consumer 模块中,指定 Nacos 注册中心的地址
1 2 3 4 5
| <dubbo:registry address="nacos://127.0.0.1:8848" timeout="5000"/>
<dubbo:registry address="nacos://127.0.0.1:8848" timeout="5000"/>
|
- (4) 引入 Nacos 客户端端后,因为不再兼容 Maven 的 Tomcat 7 插件,所以需要注释掉对应的 Maven 配置。另外,在 Maven 仓库中并没有高版本的 Tomcat 插件,因此需要在 IDEA 开发工具内,将各个模块分别手动部署到本地安装的 Tomcat 8+ 服务器中