傳統 MVC 所有邏輯耦合在單體 WAR 包,擴展性差、部署風險大。本文實戰演示:
① 模塊拆分:API 接口模塊、Provider 服務實現模塊、Consumer Web 控制器模塊
② Zookeeper 注冊中心:單機啟動、Dubbo Admin 管控台部署
③ Dubbo 服務暴露/引用:XML 配置、服務啟動類、管控台驗證
為後續微服務架構奠定基礎。
┌─────────────┐ Dubbo RPC ┌──────────────────┐
│ Consumer │ ◄─────────────────► │ Provider │
│ (Web控制器) │ 註冊中心 Zookeeper │ (ServiceImpl) │
└──────┬──────┘ └────────┬─────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Public Interface │◄──── 依賴 ──────►│ Public Interface│
│ (API 模塊) │ │ (API 模塊) │
└──────────────────┘ └──────────────────┘
parent-pom (packaging=pom) ├── public-interface (jar) -- Service 接口、DTO、常量 ├── dubbo-provider (jar) -- ServiceImpl、DAO、Spring+Dubbo 配置 └── web-consumer (war) -- Controller、SpringMVC、Dubbo Consumer 配置
<properties>
<dubbo.version>2.5.3</dubbo.version>
<zookeeper.version>3.3.3</zookeeper.version>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<dependencies>
<!-- 公共接口模塊 -->
<dependency><groupId>com.example</groupId><artifactId>public-interface</artifactId><version>${project.version}</version></dependency>
<!-- Dubbo 核心 -->
<dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version></dependency>
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>${zookeeper.version}</version></dependency>
<!-- Spring Context -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency>
</dependencies>
zookeeper-3.4.xconf/zoo_sample.cfg → zoo.cfg,核心配置:tickTime=2000dataDir=./dataclientPort=2181bin/zkServer.cmd 啟動,日誌顯示 binding to port 2181 即成功dubbo-admin-2.5.3.war,解壓META-INF/dubbo.properties:dubbo.registry.address=zookeeper://127.0.0.1:2181dubbo.admin.root.password=rootdubbo.admin.guest.password=guestwebapps/ROOT 清空,複製解壓文件進去https://localhost:8080,登錄 root/rootpackage com.cl.user.servicei;
public interface UserService {
String sayHello();
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Override public String sayHello() {
System.out.println("hello world----------------------------");
return "hello world";
}
}
<beans xmlns="..." xmlns:dubbo="https://code.alibabatech.com/schema/dubbo" ...>
<dubbo:application name="user-service-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<bean id="userService" class="com.cl.user.serviceImpl.UserServiceImpl"/>
<dubbo:service interface="com.cl.user.servicei.UserService" ref="userService"/>
</beans>
package com.test;
public class ProviderStart {
public static void main(String[] args) {
// Dubbo 容器會自動掃描 classpath:META-INF/spring/*.xml
com.alibaba.dubbo.container.Main.main(args);
}
}
原理:
DubboContainer啟動時調用SpringContainer,掃描META-INF/spring/下所有 XML,故配置文件必須放在此目錄。
<!-- web.xml 加載 SpringMVC + Dubbo Consumer 配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring/*.xml</param-value>
</context-param>
<!-- applicationContext-dubbo-consumer.xml -->
<dubbo:application name="web-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="userService" interface="com.cl.user.servicei.UserService"/>
@Controller
@RequestMapping("/user")
public class UserController {
@Reference // 或 @Autowired 注入 dubbo:reference 的 bean
private UserService userService;
@GetMapping("/hello")
@ResponseBody
public String hello() {
return userService.sayHello(); // 遠程 RPC 調用
}
}
com.cl.user.servicei.UserService 提供者 192.168.x.x:20880https://localhost:8080/user/hello → 返回 hello world| 現象 | 原因 | 解決 |
|---|---|---|
| Provider 啟動報 ClassNotFound | public-interface 未 install 到本地倉庫 | mvn clean install -DskipTests 先裝 API 模塊 |
| Consumer 注入 null | dubbo:reference id 與 @Autowired 名稱不一致 | 統一 bean name 或用 @Reference(version="...") |
| Zookeeper 連接超時 | 防火牆擋 2181/20880 端口 | 放行端口或關閉防火牆測試 |
| Dubbo Admin 顯示空 | dubbo.properties registry.address 錯誤 | 檢查 IP/端口與 Zookeeper 一致 |
@DubboService/@DubboReference 替代 XML架構感悟:微服務拆分的本質是「業務邊界劃分」,技術棧只是手段。先做好「高內聚、低耦合」的模塊劃分,再引入 Dubbo/Zookeeper 解決分佈式調用問題,切忌為拆分而拆分。