如何使用 RestTemplate 进行 Spring Boot 微服务通信示例

铁佛  金牌会员 | 2023-12-13 14:58:55 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 904|帖子 904|积分 2712

概述

下面我们将学习如何创建多个 Spring boot 微服务以及如何使用 RestTemplate 类在多个微服务之间进行同步通信。
微服务通信有两种风格:

  • 同步通讯
  • 异步通信
同步通讯

在同步通信的情况下,客户端发送请求并等待服务的响应。这里重要的一点是协议(HTTP/HTTPS)是同步的,客户端代码只有在收到 HTTP 服务器响应时才能继续其任务。
例如,Microservice1 作为客户端发送请求并等待 Microservice2 的响应。
我们可以使用 RestTemplate 或 WebClient 或 Spring Cloud Open Feign 库来同步通信多个微服务。
异步通信

在异步通信的情况下,客户端发送请求并且不等待服务的响应。客户端将继续执行其任务 - 它不会等待服务的响应。
例如,  微服务1 作为客户端发送请求,并不等待 微服务2 的响应。
我们可以使用RabbitMQ和Apache Kafka等消息代理在多个微服务之间进行异步通信。
我们需要做什么

下面我们将创建两个微服务,例如部门服务和用户服务,并且我们将从用户服务到部门服务进行 REST API 调用以获取特定的用户部门。

并且每个微服务创建一个单独的 MySQL 数据库。
在 IntelliJ IDEA 中创建并设置两个 Spring boot 项目作为两个微服务。
1.创建DepartmentService微服务

首先 在 IntelliJ IDEA 中创建并设置部门服务Spring boot 项目
1.在IntelliJ IDEA中创建并设置spring boot项目(部门服务)
我们使用 springinitializr创建一个 Spring boot 项目。
请查看下面的屏幕截图,在使用 springinitializr创建 Spring Boot 应用程序时输入详细信息 :
点击“GENERATE”按钮以 zip 文件形式下载 Spring boot 项目。解压zip文件并在IntelliJ IDEA中导入Spring boot项目。
pom.xml文件供参考:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.         <modelVersion>4.0.0</modelVersion>
  5.         <parent>
  6.                 <groupId>org.springframework.boot</groupId>
  7.                 <artifactId>spring-boot-starter-parent</artifactId>
  8.                 <version>2.7.17</version>
  9.                 <relativePath/>
  10.         </parent>
  11.         <groupId>io.wz</groupId>
  12.         <artifactId>department-service</artifactId>
  13.         <version>0.0.1-SNAPSHOT</version>
  14.         <name>department-service</name>
  15.         <description>department-service</description>
  16.         <properties>
  17.                 <java.version>1.8</java.version>
  18.         </properties>
  19.         <dependencies>
  20.                 <dependency>
  21.                         <groupId>org.springframework.boot</groupId>
  22.                         <artifactId>spring-boot-starter-data-jpa</artifactId>
  23.                 </dependency>
  24.                 <dependency>
  25.                         <groupId>org.springframework.boot</groupId>
  26.                         <artifactId>spring-boot-starter-web</artifactId>
  27.                 </dependency>
  28.                 <dependency>
  29.                         <groupId>com.mysql</groupId>
  30.                         <artifactId>mysql-connector-j</artifactId>
  31.                         <scope>runtime</scope>
  32.                 </dependency>
  33.                 <dependency>
  34.                         <groupId>org.projectlombok</groupId>
  35.                         <artifactId>lombok</artifactId>
  36.                         <optional>true</optional>
  37.                 </dependency>
  38.                 <dependency>
  39.                         <groupId>org.springframework.boot</groupId>
  40.                         <artifactId>spring-boot-starter-test</artifactId>
  41.                         <scope>test</scope>
  42.                 </dependency>
  43.         </dependencies>
  44.         <build>
  45.                 <plugins>
  46.                         <plugin>
  47.                                 <groupId>org.springframework.boot</groupId>
  48.                                 <artifactId>spring-boot-maven-plugin</artifactId>
  49.                                 <configuration>
  50.                                         <excludes>
  51.                                                 <exclude>
  52.                                                         <groupId>org.projectlombok</groupId>
  53.                                                         <artifactId>lombok</artifactId>
  54.                                                 </exclude>
  55.                                         </excludes>
  56.                                 </configuration>
  57.                         </plugin>
  58.                 </plugins>
  59.         </build>
  60. </project>
复制代码
DepartmentService - 配置 MySQL 数据库

由于我们使用 MySQL 作为数据库,因此我们需要配置 URL、用户名和密码,以便 Spring boot 在启动时可以与数据库建立连接。
打开 src/main/resources/application.properties 文件并向其中添加以下属性:
  1. spring.datasource.url=jdbc:mysql://localhost:3306/department_db
  2. spring.datasource.username=root
  3. spring.datasource.password=Mysql@123
  4. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
  5. spring.jpa.hibernate.ddl-auto=update
复制代码
这里注意修改的MySQL密码,另外在 MySQL 中创建一个名为Department_db的数据库 。
不需要创建任何表。Hibernate 将根据我们将在下一步中定义的Department实体自动创建这些表 。这是通过属性 spring.jpa.hibernate.ddl-auto = update 自动实现的。
DepartmentService - 创建部门 JPA 实体
  1. package io.wz.departmentservice.entity;
  2. import javax.persistence.*;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Getter;
  5. import lombok.NoArgsConstructor;
  6. import lombok.Setter;
  7. @Entity
  8. @Table(name = "departments")
  9. @NoArgsConstructor
  10. @AllArgsConstructor
  11. @Setter
  12. @Getter
  13. public class Department {
  14.     @Id
  15.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  16.     private Long id;
  17.     private String departmentName;
  18.     private String departmentAddress;
  19.     private String departmentCode;
  20. }
复制代码
DepartmentService - 创建 Spring Data JPA 存储库
  1. package io.wz.departmentservice.repository;
  2. import io.wz.departmentservice.entity.Department;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface DepartmentRepository extends JpaRepository<Department, Long> {
  5. }
复制代码
DepartmentService - 创建服务层

DepartmentService
  1. package io.wz.departmentservice.service;
  2. import io.wz.departmentservice.entity.Department;
  3. public interface DepartmentService {
  4.     Department saveDepartment(Department department);
  5.     Department getDepartmentById(Long departmentId);
  6. }
复制代码
DepartmentServiceImpl 类
  1. package io.wz.departmentservice.service.impl;
  2. import lombok.AllArgsConstructor;
  3. import lombok.extern.slf4j.Slf4j;
  4. import io.wz.departmentservice.entity.Department;
  5. import io.wz.departmentservice.repository.DepartmentRepository;
  6. import io.wz.departmentservice.service.DepartmentService;
  7. import org.springframework.stereotype.Service;
  8. @Service
  9. @AllArgsConstructor
  10. @Slf4j
  11. public class DepartmentServiceImpl implements DepartmentService {
  12.     private DepartmentRepository departmentRepository;
  13.     @Override
  14.     public Department saveDepartment(Department department) {
  15.         return departmentRepository.save(department);
  16.     }
  17.     @Override
  18.     public Department getDepartmentById(Long departmentId) {
  19.         return departmentRepository.findById(departmentId).get();
  20.     }
  21. }
复制代码
DepartmentService - 创建Controller层

DepartmentController
  1. package io.wz.departmentservice.controller;
  2. import lombok.AllArgsConstructor;
  3. import io.wz.departmentservice.entity.Department;
  4. import io.wz.departmentservice.service.DepartmentService;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.http.ResponseEntity;
  7. import org.springframework.web.bind.annotation.*;
  8. @RestController
  9. @RequestMapping("api/departments")
  10. @AllArgsConstructor
  11. public class DepartmentController {
  12.     private DepartmentService departmentService;
  13.     @PostMapping
  14.     public ResponseEntity<Department> saveDepartment(@RequestBody Department department){
  15.         Department savedDepartment = departmentService.saveDepartment(department);
  16.         return new ResponseEntity<>(savedDepartment, HttpStatus.CREATED);
  17.     }
  18.     @GetMapping("{id}")
  19.     public ResponseEntity<Department> getDepartmentById(@PathVariable("id") Long departmentId){
  20.         Department department = departmentService.getDepartmentById(departmentId);
  21.         return ResponseEntity.ok(department);
  22.     }
  23. }
复制代码
DepartmentService - 启动 Spring Boot 应用程序

我们可以通过两种方式启动独立的 Spring boot 应用程序。

  • 从应用程序的根目录并键入以下命令来运行它 -
  1. $ mvn spring-boot:run
复制代码

  • 从 IDE 中,将DepartmentServiceApplication.main()方法作为独立 Java 类运行,该方法将在端口 8080 上启动嵌入式 Tomcat 服务器并将浏览器指向 http://localhost:8080/。
DepartmentService - 使用 Postman 客户端测试 REST API

保存部门 REST API:

获取单个部门 REST API:


2.创建UserService微服务

我们首先在 IntelliJ IDEA 中创建并设置UserServiceSpring boot 项目
1.在IntelliJ IDEA中创建并设置spring boot项目(用户服务)
使用 springinitializr创建一个 Spring boot 项目。
请参阅下面的屏幕截图,在使用 springinitializr创建 Spring Boot 应用程序时输入详细信息 :

单击“GENRATE”按钮以 zip 文件形式下载 Spring boot 项目。解压zip文件并在IntelliJ IDEA中导入Spring boot项目。
pom.xml 文件供参考:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.         <modelVersion>4.0.0</modelVersion>
  5.         <parent>
  6.                 <groupId>org.springframework.boot</groupId>
  7.                 <artifactId>spring-boot-starter-parent</artifactId>
  8.                 <version>2.7.17</version>
  9.                 <relativePath/>
  10.         </parent>
  11.         <groupId>io.wz</groupId>
  12.         <artifactId>user-service</artifactId>
  13.         <version>0.0.1-SNAPSHOT</version>
  14.         <name>user-service</name>
  15.         <description>user-service</description>
  16.         <properties>
  17.                 <java.version>1.8</java.version>
  18.         </properties>
  19.         <dependencies>
  20.                 <dependency>
  21.                         <groupId>org.springframework.boot</groupId>
  22.                         <artifactId>spring-boot-starter-data-jpa</artifactId>
  23.                 </dependency>
  24.                 <dependency>
  25.                         <groupId>org.springframework.boot</groupId>
  26.                         <artifactId>spring-boot-starter-web</artifactId>
  27.                 </dependency>
  28.                 <dependency>
  29.                         <groupId>com.mysql</groupId>
  30.                         <artifactId>mysql-connector-j</artifactId>
  31.                         <scope>runtime</scope>
  32.                 </dependency>
  33.                 <dependency>
  34.                         <groupId>org.projectlombok</groupId>
  35.                         <artifactId>lombok</artifactId>
  36.                         <optional>true</optional>
  37.                 </dependency>
  38.                 <dependency>
  39.                         <groupId>org.springframework.boot</groupId>
  40.                         <artifactId>spring-boot-starter-test</artifactId>
  41.                         <scope>test</scope>
  42.                 </dependency>
  43.         </dependencies>
  44.         <build>
  45.                 <plugins>
  46.                         <plugin>
  47.                                 <groupId>org.springframework.boot</groupId>
  48.                                 <artifactId>spring-boot-maven-plugin</artifactId>
  49.                                 <configuration>
  50.                                         <excludes>
  51.                                                 <exclude>
  52.                                                         <groupId>org.projectlombok</groupId>
  53.                                                         <artifactId>lombok</artifactId>
  54.                                                 </exclude>
  55.                                         </excludes>
  56.                                 </configuration>
  57.                         </plugin>
  58.                 </plugins>
  59.         </build>
  60. </project>
复制代码
UserService - 配置 MySQL 数据库

打开 src/main/resources/application.properties 文件并向其中添加以下属性:
  1. spring.datasource.url=jdbc:mysql://localhost:3306/employee_db
  2. spring.datasource.username=root
  3. spring.datasource.password=Mysql@123
  4. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
  5. spring.jpa.hibernate.ddl-auto=update
复制代码
这里注意修改的MySQL密码,另外在 MySQL 中创建一个名为employee_db的数据库 。
不需要创建任何表。Hibernate 将根据我们将在下一步中定义的User实体自动创建这些表 。这是通过属性 spring.jpa.hibernate.ddl-auto = update 自动实现的。
UserService - 更改服务器端口

注意,部门服务 Spring boot 项目运行在默认的 tomcat 服务器端口 8080 上。
对于用户服务,我们需要使用以下属性将嵌入式 tomcat 服务器端口更改为 8081:
  1. server.port = 8081
复制代码
UserService - 创建用户 JPA 实体
  1. package io.wz.userservice.entity;
  2. import javax.persistence.*;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Getter;
  5. import lombok.NoArgsConstructor;
  6. import lombok.Setter;
  7. @Entity
  8. @Table(name = "users")
  9. @Setter
  10. @Getter
  11. @NoArgsConstructor
  12. @AllArgsConstructor
  13. public class User {
  14.     @Id
  15.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  16.     private Long id;
  17.     private String firstName;
  18.     private String lastName;
  19.     @Column(nullable = false, unique = true)
  20.     private String email;
  21.     private String departmentId;
  22. }
复制代码
UserService - 创建 Spring Data JPA 存储库
  1. package io.wz.userservice.repository;
  2. import io.wz.userservice.entity.User;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface UserRepository extends JpaRepository<User, Long> {
  5. }
复制代码
UserService - 创建 DTO 类

DepartmentDto
  1. package io.wz.userservice.dto;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Getter;
  4. import lombok.NoArgsConstructor;
  5. import lombok.Setter;
  6. @Setter
  7. @Getter
  8. @AllArgsConstructor
  9. @NoArgsConstructor
  10. public class DepartmentDto {
  11.     private Long id;
  12.     private String departmentName;
  13.     private String departmentAddress;
  14.     private String departmentCode;
  15. }
复制代码
UserDto
  1. package io.wz.userservice.dto;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Getter;
  4. import lombok.NoArgsConstructor;
  5. import lombok.Setter;
  6. @Setter
  7. @Getter
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. public class UserDto {
  11.     private Long id;
  12.     private String firstName;
  13.     private String lastName;
  14.     private String email;
  15. }
复制代码
ResponseDto
  1. package io.wz.userservice.dto;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Getter;
  4. import lombok.NoArgsConstructor;
  5. import lombok.Setter;
  6. @Setter
  7. @Getter
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. public class ResponseDto {
  11.     private DepartmentDto department;
  12.     private UserDto user;
  13. }
复制代码
UserService - 将 RestTemplate 配置为 Spring Bean

将 RestTemplate 类配置为 Spring bean,以便我们可以注入并使用它。
  1. package io.wz.userservice;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.web.client.RestTemplate;
  6. @SpringBootApplication
  7. public class UserServiceApplication {
  8.     public static void main(String[] args) {
  9.         SpringApplication.run(UserServiceApplication.class, args);
  10.     }
  11.     @Bean
  12.     public RestTemplate restTemplate(){
  13.         return new RestTemplate();
  14.     }
  15. }
复制代码
UserService - 创建服务层

用户服务接口
  1. package io.wz.userservice.service;
  2. import io.wz.userservice.dto.ResponseDto;
  3. import io.wz.userservice.entity.User;
  4. public interface UserService {
  5.     User saveUser(User user);
  6.     ResponseDto getUser(Long userId);
  7. }
复制代码
UserServiceImpl class
  1. package io.wz.userservice.service.impl;
  2. import lombok.AllArgsConstructor;
  3. import io.wz.userservice.dto.DepartmentDto;
  4. import io.wz.userservice.dto.ResponseDto;
  5. import io.wz.userservice.dto.UserDto;
  6. import io.wz.userservice.entity.User;
  7. import io.wz.userservice.repository.UserRepository;
  8. import io.wz.userservice.service.UserService;
  9. import org.springframework.http.ResponseEntity;
  10. import org.springframework.stereotype.Service;
  11. import org.springframework.web.client.RestTemplate;
  12. @Service
  13. @AllArgsConstructor
  14. public class UserServiceImpl implements UserService {
  15.     private UserRepository userRepository;
  16.     private RestTemplate restTemplate;
  17.     @Override
  18.     public User saveUser(User user) {
  19.         return userRepository.save(user);
  20.     }
  21.     @Override
  22.     public ResponseDto getUser(Long userId) {
  23.         ResponseDto responseDto = new ResponseDto();
  24.         User user = userRepository.findById(userId).get();
  25.         UserDto userDto = mapToUser(user);
  26.         ResponseEntity<DepartmentDto> responseEntity = restTemplate
  27.                 .getForEntity("http://localhost:8080/api/departments/" + user.getDepartmentId(),
  28.                 DepartmentDto.class);
  29.         DepartmentDto departmentDto = responseEntity.getBody();
  30.         System.out.println(responseEntity.getStatusCode());
  31.         responseDto.setUser(userDto);
  32.         responseDto.setDepartment(departmentDto);
  33.         return responseDto;
  34.     }
  35.     private UserDto mapToUser(User user){
  36.         UserDto userDto = new UserDto();
  37.         userDto.setId(user.getId());
  38.         userDto.setFirstName(user.getFirstName());
  39.         userDto.setLastName(user.getLastName());
  40.         userDto.setEmail(user.getEmail());
  41.         return userDto;
  42.     }
  43. }
复制代码
请注意,以上我们使用RestTemplate对部门服务进行 REST API 调用:
  1. ResponseEntity<DepartmentDto> responseEntity = restTemplate
  2.                 .getForEntity("http://localhost:8080/api/departments/" + user.getDepartmentId(),
  3.                 DepartmentDto.class);
复制代码
UserService - 创建控制器层:UserController
  1. package io.wz.userservice.controller;
  2. import lombok.AllArgsConstructor;
  3. import io.wz.userservice.dto.ResponseDto;
  4. import io.wz.userservice.entity.User;
  5. import io.wz.userservice.service.UserService;
  6. import org.springframework.http.HttpStatus;
  7. import org.springframework.http.ResponseEntity;
  8. import org.springframework.web.bind.annotation.*;
  9. @RestController
  10. @RequestMapping("api/users")
  11. @AllArgsConstructor
  12. public class UserController {
  13.     private UserService userService;
  14.     @PostMapping
  15.     public ResponseEntity<User> saveUser(@RequestBody User user){
  16.         User savedUser = userService.saveUser(user);
  17.         return new ResponseEntity<>(savedUser, HttpStatus.CREATED);
  18.     }
  19.     @GetMapping("{id}")
  20.     public ResponseEntity<ResponseDto> getUser(@PathVariable("id") Long userId){
  21.         ResponseDto responseDto = userService.getUser(userId);
  22.         return ResponseEntity.ok(responseDto);
  23.     }
  24. }
复制代码
UserService - 启动 Spring Boot 应用程序

我们可以通过两种方式启动独立的 Spring boot 应用程序。

  • 从应用程序的根目录并键入以下命令来运行它 -
  1. $ mvn spring-boot:run
复制代码

  • 在 IDE 中,将 UserServiceApplication.main() 方法作为独立 Java 类运行,该方法将在端口 8080 上启动嵌入式 Tomcat 服务器并将浏览器指向 http://localhost:8081/。
UserService - 使用 Postman 客户端测试 REST API

保存用户 REST API:


获取用户 REST API:


请注意,响应包含用户的部门。这说明我们已成功从 UserService 到 DepartmentService 进行 REST API 调用。
结论

在本教程中,我们学习了如何创建多个 Spring boot 微服务以及如何使用RestTemplate类在多个微服务之间进行同步通信。
从 5.0 开始,  RestTemplate 类处于维护模式,很快就会被弃用。因此 Spring 团队推荐使用 org.springframework.web.reactive.client.WebClient ,它具有现代 API 并支持同步、异步和流场景,下一篇文章继续讲解

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

铁佛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表