安装 ZooKeeper brew install zookeeper安装完成以后启动 zookeeper,如果是通过 homebrew 方式安装的话,直接调用 zkServer start即可。
生产者部分
创建一个 Spring Boot 项目,作为其中的生产者。其中,在 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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itcenter.mall</groupId>
<artifactId>provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provider</name>
<description>User service provider project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<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-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.itcenter.mall</groupId>
<artifactId>mallInterface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!-- 引入 zookeeper 的注册中心 -->
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.itcenter.mall.provider.ProviderApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
配置生产者,注意:生产者配置在resources文件夹下的 application.properties 配置以下属性。
# dubbo 的应用名称
dubbo.application.name=userServiceProvider
# dubbo 注册中心相关属性
# 注册中心所用的协议名
dubbo.registry.protocol=zookeeper
# 注册中心的地址
dubbo.registry.address=127.0.0.1:2181
# dubbo RPC 协议部分相关属性
# 协议名
dubbo.protocol.name=dubbo
# 协议端口
dubbo.protocol.port=20880
注意:这些都可以配置成 xml 格式的,但是由于这是 Spring Boot 工程,所以说配置起来的话都是在 properties 文件中配置即可。 5. 创建 Java 类 其中文件目录如下: 其中 UserServiceImpl 当中的代码实现如下:
package com.itcenter.mall.provider.service.impl;
import com.itcenter.mall.entity.UserAddress;
import com.itcenter.mall.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
* UserServiceImpl class
*
* @author apple
*/
@Service
@DubboService
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
var userAddress1 = new UserAddress(1, "1");
var userAddress2 = new UserAddress(2, "2");
// 注意:这个地方不能使用 List.of 方法来进行传递,因为传递的对象不是 ImmutableCollections.List12 类的对象,是他的代理类对象,代理类对象不序列化其中的列表。所以消费者那边会抛出 UnsupportedOperationException 异常
return Arrays.asList(userAddress1, userAddress2);
}
}
其中我们发现,UserAddress 类与 UserService 接口并没有导入,这是因为在 RPC 中,消费者也同时需要引入 UserService 来调用里面的方法,所以说需要将 RPC 调用的接口以及其中需要传输的实体类封装到一个项目当中,并且在生产者与消费者之间的数据传递过程中,都需要依赖该接口包来使用。(生产者负责实现的接口,而消费者需要调用接口来获得数据。)所以说,我们需要创建一个接口项目,来封装整个项目。
注意:在启动项目的类中,添加 @EnableDubbo 注解才能正常启动 Dubbo,否则消费者会找不到生产者而报错。
接口封装项目
在接口封装的项目中,我们使用一个 maven 项目即可。不用使用 Spring Boot 项目进行封装。里面的文件结构如下: 其中的 pom.xml 当中的数据如下:
<?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.itcenter.mall</groupId>
<artifactId>mallInterface</artifactId>
<version>1.0-SNAPSHOT</version>
<name>mallInterface</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
由于 Service 中需要传递实体类数据,所以说传递的实体类也需要封装到该项目当中,并且实现 Serializable 接口,并且需要将 serialVersionUID 生成出来,防止在不同机器的 JVM 中序列化错误。 实体类 UserAddress.java 文件如下:
package com.itcenter.mall.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;
/**
* UserAddress class
*
* @author apple
*/
@Data
@AllArgsConstructor
public class UserAddress implements Serializable {
// 这个地方根据项目的不同生成不同的 serialVersionUID
private static final long serialVersionUID = -7540180539502669771L;
private Integer id;
private String userId;
}
OrderService.java 文件实现如下:
package com.itcenter.mall.service;
import com.itcenter.mall.entity.UserAddress;
import java.util.List;
/**
* OrderService class
*
* @author apple
*/
public interface OrderService {
/**
* 根据用户 id 初始化订单
*
* @param userId 用户 id
* @return 初始化订单信息
*/
List<UserAddress> initOrder(String userId);
}
UserService.java 文件实现如下:
package com.itcenter.mall.service;
import com.itcenter.mall.entity.UserAddress;
import java.util.List;
/**
* UserService class
*
* @author apple
*/
public interface UserService {
List<UserAddress> getUserAddressList(String userId);
}
注意:配置完成了以后,生产者部分需要引入接口依赖
<dependency>
<groupId>com.itcenter.mall</groupId>
<artifactId>mallInterface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
这样生产者部分项目就正常了
消费者配置
创建一个 Spring Boot 项目,作为其中的消费者。其中,在 maven 依赖的时候,pom.xml 格式如下。
<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itcenter.mall</groupId>
<artifactId>consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer</name>
<description>Order service consumer project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.itcenter.mall</groupId>
<artifactId>mallInterface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!-- 引入 zookeeper 的注册中心 -->
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.itcenter.mall.consumer.ConsumerApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
配置 application.properties
# 应用名称
spring.application.name=consumer
# 应用服务 WEB 访问端口
server.port=80
# spring 静态资源扫描路径
spring.resources.static_locations=classpath:/static/
dubbo.application.name=orderServiceImpl
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181
Java 类文件目录如下: 其中 OrderController.java 文件中代码如下:
package com.itcenter.mall.consumer.controller;
import com.itcenter.mall.entity.UserAddress;
import com.itcenter.mall.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* OrderController
*
* @author apple
*/
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/initOrder/{userId}")
public List<UserAddress> initOrder(@PathVariable("userId") String userId) {
return orderService.initOrder(userId);
}
}
OrderServiceImpl.java 文件中代码如下:
package com.itcenter.mall.consumer.service.impl;
import com.itcenter.mall.entity.UserAddress;
import com.itcenter.mall.service.OrderService;
import com.itcenter.mall.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* OrderServiceImpl class
*
* @author apple
*/
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
// 引入 RPC 接口。因为这个接口是生产者实现的 Service,不是本机的 Service。所以说他是用 @DubboReference 注解注入的。
// 注意:这个地方代替的是原来 xml 的 <dubbo:reference> 标签
@DubboReference
private UserService userService;
@Override
public List<UserAddress> initOrder(String userId) {
var userAddressList = userService.getUserAddressList(userId);
log.info("userAddressList = " + userAddressList);
return userAddressList;
}
}
注意:在启动项目的类中,添加 @EnableDubbo 注解才能正常启动 Dubbo,否则消费者会找不到生产者而报错。
消费者部分搭建完成了以后,再分别启动生产者和消费者的程序(注意:这个地方如果不配置检查属性为 false 的话,必须先启动生产者再启动消费者,否则消费者会找不到生产者报错),然后输入http://localhost/initOrder/1 进行验证。最后显示结果如下: 一个生产者与消费者的模型就搭建完成。
搭建源码地址:DubboExample: 自己的 Dubbo 练习仓库