dubbo集成springboot分模块开发流程
- common-api:`公共模块是把consumer和provider两个模块中共有的部分提取出来放到该模块中。比如两个模块间交互的接口可以提取出来`
- provider:`生产者模块是用于提供服务的,相当于service层的接口实现类`
- consumer:`消费者模块是用于消费服务的,相当于service层接口的实际调用者`
创建一个springboot的空项目
所谓的空项目就是指这个项目只保留(.gitignore、pom.xml)文件
![](https://img2022.cnblogs.com/blog/1837173/202208/1837173-20220808091910837-1495967054.png)
项目依赖信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
```xml <properties> <java.version>1.8</java.version> <dubbo.version>3.0.0</dubbo.version> <zookeeper.version>3.4.13</zookeeper.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <!-- <exclusions>--> <!-- <exclusion>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-logging</artifactId>--> <!-- </exclusion>--> <!-- </exclusions>--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>${dubbo.version}</version> <type>pom</type> </dependency> </dependencies> ```
在空项目下创建子模块
子模块使用 maven 工程创建,且不用选择 archetype 子选项
![](https://img2022.cnblogs.com/blog/1837173/202208/1837173-20220808092131670-38151866.png)
项目结构
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
learn-dubbo |-common-api |-src |-main |-java |-com.example.api.service |-xxxService.java |-resources |-test |-target |-pom.xml
pom.xml 文件信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<parent> <artifactId>learn-dubbo</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>common-api</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version>
创建 dubbo-provider 子模块
子模块的方式如 common-api 子模块一样
目录结构
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
learn-dubbo |-dubbo-provider |-src |-main |-java |-com.example.provider |-service |-xxxServiceImpl.java |-ProviderApplicationMain.java |-resources |-static |-application.properties |-test |-target |-pom.xml
pom.xml 文件信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<parent> <artifactId>learn-dubbo</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubbo-provider</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <artifactId>common-api</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
application.properties 配置信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
spring.application.name = provider server.port = 9090 dubbo.application.name = provider demo.service.version = 1.0.0 dubbo.protocol.name = dubbo dubbo.protocol.port = 20880 #ָ 注册中心地址 dubbo.registry.address = zookeeper://localhost:2181 dubbo.provider.timeout = 3000 dubbo.protocol.accesslog=classpath:static\\dubbo-access-log.log
创建 dubbo-consumer 子模块
子模块的方式如 common-api 子模块一样
目录结构
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
learn-dubbo |-dubbo-consumer |-src |-main |-java |-com.example.consumer |-controller |-xxxController.java |-ConsumerApplicationMain.java |-resources |-application.properties |-test |-target |-pom.xml
pom.xml 文件信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<parent> <artifactId>learn-dubbo</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubbo-consumer</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <artifactId>common-api</artifactId> <groupId>com.example</groupId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
application.properties 配置信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
spring.application.name = consumer server.port = 9091 dubbo.application.name = consumer demo.service.version = 1.0.0 dubbo.protocol.name = dubbo dubbo.protocol.port = 20880 dubbo.registry.address = zookeeper://localhost:2181 #dubbo.registry.address = zookeeper://192.168.240.117:2181 dubbo.consumer.timeout = 50000 #dubbo.consumer.loadbalance=failback #dubbo.consumer.cluster=autoStrategyCluster management.endpoints.web.exposure.include=* #management.server.port=10111 management.server.servlet.context-path=/ management.server.ssl.enabled=false management.endpoint.health.show-details=always pf.advisor.global.open =true pf.advisor.global.doc=true
生产/消费者启用 dubbo 功能
生产项目的主类加上 @EnableDubbo 注解,这个注解的作用是类似于 spring 把特定路径下的 bean 扫描进容器中,所以 dubbo 也会扫描当前注解所在的包路径下所有服务,把这些服务注册到注册中心。切记务必要在生产者和消费者都要加上该注解,否则会造成 dubbo 服务无法完成注册
生产者
生产者模块是对 common-api 模块中接口的具体实现,类似于 MVC 架构中的 ServiceImpl 层。@DubboService 注解的作用类似于 spring 框架中的 @Service,dubbo 会扫描特定包下被标注 @DubboService 的类,把它们作为 dubbo 服务注册到注册中心
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @EnableDubbo @SpringBootApplication public class ProviderApplicationMain { public static void main(String[] args) { SpringApplication.run(ProviderApplicationMain.class, args); } }
消费者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @EnableDubbo @SpringBootApplication public class ConsumerApplicationMain { public static void main(String[] args) { SpringApplication.run(ConsumerApplicationMain.class, args); } }
开发 dubbo 服务
生产者和消费者之间的交互需要使用到 common-api 模块的接口,所以这两个子模块都需要引入 common-api 子模块
生产者
生产者模块是对 common-api 模块中接口的具体实现,类似于 MVC 架构中的 ServiceImpl 层。@DubboService 注解的作用类似于 spring 框架中的 @Service,dubbo 会扫描特定包下被标注 @DubboService 的类,把它们作为 dubbo 服务注册到注册中心
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import com.example.api.service.DemoService; import org.apache.dubbo.config.annotation.DubboService; @DubboService public class DemoServiceImpl implements DemoService { @Override public String sayHello(String name) { return "this is dubbo service : " + name; } }
消费者
消费者是实际为客户端提供 api 调用的服务端,类似于 MVC 架构中的 Controller 层。@DubboReference 注解的作用类似于spring 框架中的 @Autowired,区别在于 DubboReference 是从注册中心中拉取服务,而 Autowired 是从容器中拉取 bean
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import com.example.api.service.DemoService; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ConsumerController { @DubboReference(check = false) private DemoService demoService; @RequestMapping("/dubbo/{name}") public String sayHello(@PathVariable("name") String name){ String result = "success"; try { if (null != name && name.length() > 0){ result = demoService.sayHello(name); System.out.println(result); } else { result = "error"; } } catch (Exception e){ e.printStackTrace(); return e.getMessage(); } return result; } }
生产端 dubbo 源码分析
类图架构
服务启动
如下图所示,dubbo 服务的启动类是 ServiceBean,`ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware, ApplicationEventPublisherAware`,它实现了InitializingBean接口的类,在spring初始化Bean的时候就会执行该方法(afterPropertiesSet),而 afterPropertiesSet() 方法中有调用 dubbo 服务启动器`DubboBootstrap.getInstance().service(this)`。
服务配置
dubbo 服务的配置类是 ServiceConfigBase,其中重写了 `preProcessRefresh()` 方法。这个方法的作用是初始化 `ProviderConfig` 也就是`生产者`的配置信息。
服务注册
dubbo 服务的注册类 ServiceConfig,其中注册的操作方法在 `AbstractInterfaceConfig` 类中,而 ServiceConfig 的父类 ServiceConfigBase 继承了 `AbstractInterfaceConfig`,所以 ServiceConfig 也继承了服务注册的逻辑方法 `checkRegistry() 和 convertRegistryIdsToRegistries()`,ServiceConfig 类的注册操作入口 `checkAndUpdateSubConfigs()`。
时序图架构