1.一个简单的分布式项目架构
- 订单服务功能:创建订单,根据用户id查询订单详情
- 用户服务功能:创建订单,根据用户id查询订单详情
2.配置开发环境 搭建Maven项目(父项目)
- 创建Maven项目
- 修改pom.xml文件 :修改为父项目 & 修改jdk为1.8 & 设置阿里云仓库
<?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>org.learn</groupId> <artifactId>dubbo-demo</artifactId> <version>1.0-SNAPSHOT</version> <!-- 设置为父项目 --> <packaging>pom</packaging> <!-- Maven默认的jdk版本是1.5 这里要设置jdk版本是1.8 --> <profiles> <profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile> </profiles> <!-- 设置阿里云仓库(因为在中央仓库下载jar包很慢 所以要在这里配置阿里云镜像仓库) --> <repositories> <repository> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
- IDEA进行setting设置:设置字符编码为UTF-8 & 设置忽略文件
3.创建服务生产者项目
- 首先在父项目中创建生产者项目
- 选择Spring Initializr创建SpringBoot项目
- 修改pom.xml文件
将子项目(生产者项目)pom.xml文件中引用的spring-boot-starter-parent转移到父项目中
然后将父项目引入到子项目(生产者项目)中
在父项目中引入子项目(生产者项目)模块
到此父项目与生产者项目pom.xml文件就弄好了,接下来就可以引入Dubbo和Zookeeper的依赖进行使用了!
<!-- Dubbo -->
<dependency>
<groupId>io.dubbo.springboot</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Zookeeper客户端 -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.7</version>
</dependency>
- 下面在生产者项目中创建service包和pojo包
4.生产者代码以及配置编写
- 首先创建订单实体类Orders与统一返回结果实体类CommonResult
package com.learn.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * 订单实体类 */ @Data @AllArgsConstructor // 有参构造 @NoArgsConstructor // 无参构造 public class Orders implements Serializable { private static final long serialVersionUID = 3342666612486674441L; /** * 订单id */ private Long id; /** * 用户id */ private Long userId; /** * 收货人手机号 */ private String mobile; /** * 收货人地址 */ private String address; /** * 支付类型 1:微信支付 2:支付宝支付 */ private Integer pay_method; } package com.learn.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * 统一返回结果集 * @param <T> */ @Data @AllArgsConstructor @NoArgsConstructor public class CommonResult<T> implements Serializable { private static final long serialVersionUID = -5309051212989921435L; // 1.返回结果编码200 private Integer code; // 2.返回结果描述 private String message; // 3.数据 private T data; }
- 编写订单服务接口IOrderService与实现类IOrderServiceImpl
-
package com.learn.service; import com.learn.pojo.CommonResult; import com.learn.pojo.Orders; /** * 订单接口 */ public interface IOrderService { /** * 创建订单 * @param orders */ CommonResult createOrders(Orders orders); /** * 根据用户id查询订单信息 * @param id * @return */ CommonResult findByUserId(Long id); }
package com.learn.service; import com.alibaba.dubbo.config.annotation.Service; import com.learn.pojo.CommonResult; import com.learn.pojo.Orders; import com.sun.org.apache.xpath.internal.operations.Or; /** * 订单业务层 */ @Service // 将这个类提供的方法对外发布,将访问的地址IP 端口 路径 注册到注册中心(注意一定要选dubbo服务中的service注意 而不要选spring框架中的service注解) public class IOrderServiceImpl implements IOrderService{ @Override public CommonResult createOrders(Orders orders) { // 模拟从数据库查询出结果并返回 CommonResult commonResult = new CommonResult(); commonResult.setCode(200); commonResult.setMessage("订单创建成功"); commonResult.setData(null); return commonResult; } @Override public CommonResult findByUserId(Long id) { Orders orders = new Orders(); orders.setId(00001L); orders.setUserId(00001L); orders.setMobile("15840565641"); orders.setAddress("上海"); orders.setPay_method(1); // 模拟从数据库中查询出结果并返回 CommonResult<Orders> commonResult = new CommonResult(); commonResult.setCode(200); commonResult.setMessage("查询订单成功"); commonResult.setData(orders); return commonResult; } }
- 配置application.propreties文件
# 1. 配置项目名称 spring.dubbo.application.name=orders-producer # 2. 配置注册中心 spring.dubbo.refistry.address=zookeeper://192.168.66.100 spring.dubbo.registry.port=2181 # 3. 指定dubbo使用的协议以及端口号 sping.dubbo.protocol.name=dubbo sping.dubbo.protocol.port=20880 # 4. 指定注册到zk上的超时时间 sping.dubbo.registry.timeout=10000 # 5. 配置Dubbo的包扫描 spring.dubbo.scan=com.learn.service
- 到此 服务生产者开发完成 启动项目即可。
5.创建服务消费者项目
与创建服务生产者项目类似:
- 首先创建springBoot项目
- 选择需要的工具
- 将pom.xml文件添加到Maven项目中(如果有必要的话)
- 修改消费者pom.xml文件,删掉springBoot的父项目,将创建的父项目引入进来;同时将服务生产者项目引入服务消费者,目的是继承Dubbo和Zookeeper依赖以及可以调用服务生产者中的接口
- 修改父项目的pom.xml文件,将服务消费者项目引入
- 最后创建包结构即可完成服务消费者创建
6.生产者代码以及配置编写
- 首先创建服务消费者的用户实体类
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 1884700022143299743L;
/**
* 用户id
*/
private Long id;
/**
* 用户名字
*/
private String name;
}
- 创建服务消费者的service接口以及实现类,并完成远程调用
package com.example.service;
import com.learn.pojo.CommonResult;
/**
* 用户接口
*/
public interface IUserService {
/**
* 根据用户id查询用户订单详情
*
* @param userId 用户id
* @return
*/
CommonResult findByUserId(Long userId);
}
package com.example.service.impl;
import com.alibaba.dubbo.config.annotation.Reference;
import com.example.service.IUserService;
import com.learn.pojo.CommonResult;
import com.learn.service.IOrderService;
import org.springframework.stereotype.Service;
/**
* 用户服务
*/
@Service // 这里要选spring的service注解而不是dubbo的 因为服务消费者里的service层要被放到容器中供controller层使用
public class IUserServiceImpl implements IUserService {
/**
* @Autowired : 本地注入
*
* @Reference : 远程调用
* 1.从Zookeeper注册中心获取IOrderService访问的url
* 2.进行远程调用RPC
* 3.将结果封装为一个代理对象,赋值给iOrderService (这里是通过序列化和反序列化实现的远程调用,所以实体类都要实现序列化接口)
*/
@Reference
private IOrderService iOrderService;
/**
* 根据用户id查询用户订单详情
*
* @param userId 用户id
* @return
*/
@Override
public CommonResult findByUserId(Long userId) {
return iOrderService.findByUserId(userId);
}
}
将服务生产者项目用pom.xml文件引入服务消费者,就可以在服务消费者中使用服务生产者的接口,并通过@Reference注解注入
需要注意的是:服务生产者中的@Service是dubbo中的,而服务消费者中的@Service是spring框架中的,因为要将服务消费者的service类注入到bean容器中,方便@Controller的使用。
7.总结
到目前为止,实现dubbo远程调用的两个注解:
@Service (注意该注解是dubbo中的注解而不是spring框架中的)服务提供者接口注解
@Reference 服务消费者注解