1 dubbo-helloworld xml版
1)需求
某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址;我们现在 需要创建两个服务模块进行测试
模块 | 功能 |
---|---|
订单服务web模块 | 创建订单等 |
用户服务service模块 | 查询用户地址等 |
测试预期结果:订单服务web模块在A服务器,用户服务模块在B服务器,A可以远程调用B的功能。
2)工程架构
根据 dubbo《服务化最佳实践》
(1)分包
建议将服务接口,服务模型,服务异常等均放在 API 包中,因为服务模型及异常也是 API 的一部分,同时,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。如果需要,也可以考虑在 API 包中放置一份 spring 的引用配置,这样使用方,只需在 spring 加载过程中引用此配置即可,配置建议放在模块的包目录下,以免冲突,如:com/alibaba/china/xxx/dubbo-reference.xml。
(2)粒度
服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持。服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
3)创建空工程,新建3个模块
(1)新建一个empty project (maven)
新建3个moudle(maven)
order-service(具体实现)
user-service(具体实现)
common-interface(提取所有的接口和bean)
配置好maven环境变量
(2)user-service moudle
a)添加maven依赖
<dependencies>
<!-- 引入dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 由于我们使用zookeeper作为注册中心,所以需要操作zookeeper
dubbo 2.6以前的版本引入zkclient操作zookeeper
dubbo 2.6及以后的版本引入curator操作zookeeper
下面两个zk客户端根据dubbo版本2选1即可
-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!-- curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.tang</groupId>
<artifactId>common-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
b )新建UserAddress Bean模型
public class UserAdress implements Serializable {
private Integer id;
private String userAddress;
private String userId;
private String consignee;
private String phoneNum;
private String isDefault;
public UserAdress(Integer id, String userAddress, String userId, String consignee, String phoneNum, String isDefault) {
this.id = id;
this.userAddress = userAddress;
this.userId = userId;
this.consignee = consignee;
this.phoneNum = phoneNum;
this.isDefault = isDefault;
}
}
c )编写UserService接口以及UserServiceImpl实现类
public interface UserService {
public List<UserAdress> getUserAddressList(String userId);
}
public class UserServiceImpl implements UserService {
public List<UserAdress> getUserAddressList(String userId){
UserAdress u1=new UserAdress(1,"ezhou","123","","15168242649","y");
UserAdress u2=new UserAdress(1,"ezhou","123","","15168242649","y");
return Arrays.asList(u1,u2);
}
}
d)新建provider.xml配置文件(dubbo服务提供者配置),编辑文件
参考开发文档:dubbo.apache.org/zh-cn/docs/user/quick-start.html
<?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://code.alibabatech.com/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
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 1、指定当前服务/应用的名字(同样的服务名字相同,不要和别的服务同名) -->
<dubbo:application name="userserviceprovider"></dubbo:application>
<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
<!-- 3、指定通信规则(通信协议?通信端口) -->
<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
<!-- 4、暴露服务 ref:指向服务的真正的实现对象 -->
<dubbo:service interface="com.service.UserService"
ref="userService">
<!-- <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> -->
</dubbo:service>
<!--统一设置服务提供方的规则 -->
<dubbo:provider timeout="1000"></dubbo:provider>
<!-- 服务的实现 -->
<bean id="userService" class="com.tang.service.impl.UserServiceImpl"></bean>
</beans>
e)编写测试代码UserApplication
新建 UserApplication
public class UserApplication {
public static void main(String[] args) throws IOException{
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("classpath:provider.xml");
System.in.read();
}
}
f)启动user-service 进行测试
查看dubbo服务管理界面是否有对应的服务提供者,具体参考https://mp.csdn.net/mdeditor/95346703#
在zk安装bin目录下 启动zkServer脚本
java -jar 执行dubbo-admin的maven打包文件
localhost:7001访问
(3) order-service moudle 订单模块(调用用户模块)
a ) 添加maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tang</groupId>
<artifactId>order-service</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.tang</groupId>
<artifactId>common-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!-- curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
</dependencies>
b)编写OrderService接口以及OrderServiceImpl实现
public interface OrderService {
/**
* 初始化订单,查询用户的所有地址并返回
* @param userId
* @return
*/
public List<UserAdress> initOrder(String userId);
}
@Service
public class OrderServiceImpl implements OrderService {
@Resource
UserService userService;
/**
* 初始化订单,查询用户的所有地址并返回
* @param userId
* @return
*/
public List<UserAdress> initOrder(String userId){
return userService.getUserAddressList(userId);
}
}
c)编写consumer.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<context:component-scan base-package=“com.service.impl”></context:component-scan>
<dubbo:application name=“orderserviceconsumer”></dubbo:application>
<!-- 2、指定注册中心的位置 -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry>
<dubbo:reference id="userService" interface="com.service.UserService"></dubbo:reference>
d)编写测试代码
public class OrderApplication {
public static void main(String[] args) throws IOException{
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("classpath:consumer.xml");
OrderService orderService =context.getBean(OrderService.class);
List<UserAdress> address=orderService.initOrder("1");
System.out.println(address.get(0).toString());
System.in.read();
}
}
e) 测试调用
访问orderService的initOrder请求,会调用UserService获取用户地址;
调用成功。说明我们order已经可以调用远程的UserService了;
目前无法调用,因为UserAdress与UserService在用户moudel工程中,需要将这些被第三方调用的接口和bean单独提取出来作为一个moudel工程为其他调用者提供maven依赖
(4)common-interface modile 公共接口层(bean,service,exception…)
作用:定义公共接口,也可以导入公共依赖
a)将user-service moule中的接口和bean实体提取到common-interface modile
b)将order-service moule中的接口和bean实体提取到common-interface modile
c ) 将 common-interface modile 的maven 坐标信息添加到 user-service moule和
order-service moule 的pom.xml文件中
(5)启动 user-service,order-service
查看dubbo服务管理界面
2 注解版
与xml版基本相同,不同的地方如下
1)服务提供方
<dubbo:application name=“gmall-user”></dubbo:application>
<dubbo:registry address=“zookeeper://localhost:2181” />
<dubbo:protocol name=“dubbo” port=“20880” />
<dubbo:annotation package=“com.atguigu.gmall.user.impl”/>需要暴露的接口的包
import com.alibaba.dubbo.config.annotation.Service;
import com.atguigu.gmall.bean.UserAddress;
import com.atguigu.gmall.service.UserService;
import com.atguigu.gmall.user.mapper.UserAddressMapper;
@Service //使用dubbo提供的service注解,注册暴露服务
public class UserServiceImpl implements UserService {
@Autowired
UserAddressMapper userAddressMapper;
2 ) 服务消费方
<dubbo:application name=“gmall-order-web”></dubbo:application>
<dubbo:registry address=“zookeeper://118.24.44.169:2181” />
<dubbo:annotation package=“com.atguigu.gmall.order.controller”/>需要调用的接口的包
@Controller
public class OrderController {
@Reference //使用dubbo提供的reference注解引用远程服务
UserService userService;