跳到主要内容
Spring Boot 微服务架构设计与实现 | 极客日志
Java java
Spring Boot 微服务架构设计与实现 Spring Boot 微服务架构将应用拆分为独立服务,具备独立部署、开发、运行及网络通信特点。集成 Spring Cloud Eureka 可实现服务注册与发现,通过 Config Server 集中管理配置。利用 Ribbon 实现负载均衡,Feign 简化远程调用,Hystrix 提供熔断保护。实际场景涵盖产品、用户、订单及支付服务的微服务化改造,提升系统可扩展性、可维护性与可靠性。
剑仙 发布于 2026/3/29 更新于 2026/6/1 18 浏览学习目标与重点提示
学习目标 :掌握 Spring Boot 微服务架构设计与实现的核心概念与使用方法,包括微服务架构的定义与特点、Spring Boot 与微服务的集成、配置及基本方法,学会在实际开发中处理相关问题。
重点 :微服务架构的定义与特点、Spring Boot 与微服务的集成、Spring Boot 与微服务的配置、Spring Boot 与微服务的基本方法、Spring Boot 的实际应用场景。
微服务架构概述
微服务架构是 Java 开发中的重要组件。
微服务架构的定义
定义 :微服务架构是一种软件架构风格,将应用程序拆分为一组独立的服务,每个服务运行在自己的进程中,通过网络进行通信。
作用 :
提高应用程序的可扩展性。
提高应用程序的可维护性。
提高应用程序的可靠性。
常见的微服务架构 :
Spring Cloud:Spring Cloud 是 Spring Boot 提供的微服务框架。
Netflix OSS:Netflix OSS 是 Netflix 提供的微服务框架。
Docker:Docker 是一种容器化技术,用于打包和部署应用程序。
Kubernetes:Kubernetes 是一种容器编排工具,用于管理和调度应用程序。
结论 :微服务架构是一种软件架构风格,作用是提高应用程序的可扩展性、可维护性、可靠性。
微服务架构的特点
特点 :
独立部署:每个服务可以独立部署。
独立开发:每个服务可以独立开发。
独立运行:每个服务运行在自己的进程中。
网络通信:每个服务通过网络进行通信。
结论 :微服务架构的特点包括独立部署、独立开发、独立运行、网络通信。
Spring Boot 与微服务的集成
Spring Boot 与微服务的集成是 Java 开发中的重要内容。
集成 Spring Cloud Eureka 的步骤
步骤 :
创建 Spring Boot 项目。
添加所需的依赖。
配置 Spring Cloud Eureka。
创建服务提供者。
创建服务消费者。
测试应用。
示例 :
服务注册中心(Eureka Server)的 pom.xml 文件中的依赖:
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-netflix-eureka-server</artifactId >
</ >
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR12
pom
import
dependency
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
<scope >
</scope >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId >
</groupId >
<artifactId >
</artifactId >
<version >
</version >
<type >
</type >
<scope >
</scope >
</dependency >
</dependencies >
</dependencyManagement >
服务注册中心(Eureka Server)的 application.properties 文件中的配置:
# 服务器端口
server.port=8761
# Eureka Server 配置
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=localhost
服务注册中心(Eureka Server)的启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main (String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
服务提供者(Product Service)的 pom.xml 文件中的依赖:
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-netflix-eureka-client</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</artifactId >
<scope > test</scope >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-dependencies</artifactId >
<version > Hoxton.SR12</version >
<type > pom</type >
<scope > import</scope >
</dependency >
</dependencies >
</dependencyManagement >
服务提供者(Product Service)的 application.properties 文件中的配置:
# 服务器端口
server.port=8081
# 应用名称
spring.application.name=product-service
# Eureka Client 配置
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.instance.prefer-ip-address=true
服务提供者(Product Service)的实体类:
public class Product {
private Long id;
private String productId;
private String productName;
private double price;
private int sales;
public Product () {}
public Product (Long id, String productId, String productName, double price, int sales) {
this .id = id;
this .productId = productId;
this .productName = productName;
this .price = price;
this .sales = sales;
}
public Long getId () { return id; }
public void setId (Long id) { this .id = id; }
public String getProductId () { return productId; }
public void setProductId (String productId) { this .productId = productId; }
public String getProductName () { return productName; }
public void setProductName (String productName) { this .productName = productName; }
public double getPrice () { return price; }
public void setPrice (double price) { this .price = price; }
public int getSales () { return sales; }
public void setSales (int sales) { this .sales = sales; }
@Override
public String toString () {
return "Product{" +
"id=" + id +
", productId='" + productId + '\'' +
", productName='" + productName + '\'' +
", price=" + price +
", sales=" + sales +
'}' ;
}
}
服务提供者(Product Service)的控制器类:
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private List<Product> products = new ArrayList <>();
public ProductController () {
products.add(new Product (1L , "P001" , "手机" , 1000.0 , 100 ));
products.add(new Product (2L , "P002" , "电脑" , 5000.0 , 50 ));
products.add(new Product (3L , "P003" , "电视" , 3000.0 , 80 ));
products.add(new Product (4L , "P004" , "手表" , 500.0 , 200 ));
products.add(new Product (5L , "P005" , "耳机" , 300.0 , 150 ));
}
@GetMapping("/")
public List<Product> getAllProducts () {
return products;
}
@GetMapping("/{id}")
public Product getProductById (@PathVariable Long id) {
return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null );
}
@PostMapping("/")
public Product addProduct (@RequestBody Product product) {
product.setId((long ) (products.size() + 1 ));
products.add(product);
return product;
}
@PutMapping("/{id}")
public Product updateProduct (@PathVariable Long id, @RequestBody Product product) {
Product existingProduct = getProductById(id);
if (existingProduct != null ) {
existingProduct.setProductId(product.getProductId());
existingProduct.setProductName(product.getProductName());
existingProduct.setPrice(product.getPrice());
existingProduct.setSales(product.getSales());
}
return existingProduct;
}
@DeleteMapping("/{id}")
public void deleteProduct (@PathVariable Long id) {
products.removeIf(product -> product.getId().equals(id));
}
}
服务提供者(Product Service)的启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main (String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
服务消费者(Order Service)的 pom.xml 文件中的依赖:
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-netflix-eureka-client</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-netflix-ribbon</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</artifactId >
<scope > test</scope >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-dependencies</artifactId >
<version > Hoxton.SR12</version >
<type > pom</type >
<scope > import</scope >
</dependency >
</dependencies >
</dependencyManagement >
服务消费者(Order Service)的 application.properties 文件中的配置:
# 服务器端口
server.port=8082
# 应用名称
spring.application.name=order-service
# Eureka Client 配置
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
eureka.instance.prefer-ip-address=true
服务消费者(Order Service)的实体类:
public class Product {
private Long id;
private String productId;
private String productName;
private double price;
private int sales;
public Product () {}
public Product (Long id, String productId, String productName, double price, int sales) {
this .id = id;
this .productId = productId;
this .productName = productName;
this .price = price;
this .sales = sales;
}
public Long getId () { return id; }
public void setId (Long id) { this .id = id; }
public String getProductId () { return productId; }
public void setProductId (String productId) { this .productId = productId; }
public String getProductName () { return productName; }
public void setProductName (String productName) { this .productName = productName; }
public double getPrice () { return price; }
public void setPrice (double price) { this .price = price; }
public int getSales () { return sales; }
public void setSales (int sales) { this .sales = sales; }
@Override
public String toString () {
return "Product{" +
"id=" + id +
", productId='" + productId + '\'' +
", productName='" + productName + '\'' +
", price=" + price +
", sales=" + sales +
'}' ;
}
}
public class Order {
private Long id;
private String orderId;
private List<Product> products;
public Order () {}
public Order (Long id, String orderId, List<Product> products) {
this .id = id;
this .orderId = orderId;
this .products = products;
}
public Long getId () { return id; }
public void setId (Long id) { this .id = id; }
public String getOrderId () { return orderId; }
public void setOrderId (String orderId) { this .orderId = orderId; }
public List<Product> getProducts () { return products; }
public void setProducts (List<Product> products) { this .products = products; }
@Override
public String toString () {
return "Order{" +
"id=" + id +
", orderId='" + orderId + '\'' +
", products=" + products +
'}' ;
}
}
服务消费者(Order Service)的控制器类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
private List<Order> orders = new ArrayList <>();
public OrderController () {
orders.add(new Order (1L , "O001" , new ArrayList <>()));
orders.add(new Order (2L , "O002" , new ArrayList <>()));
orders.add(new Order (3L , "O003" , new ArrayList <>()));
}
@Bean
@LoadBalanced
public RestTemplate restTemplate () {
return new RestTemplate ();
}
@GetMapping("/")
public List<Order> getAllOrders () {
return orders;
}
@GetMapping("/{id}")
public Order getOrderById (@PathVariable Long id) {
return orders.stream().filter(order -> order.getId().equals(id)).findFirst().orElse(null );
}
@PostMapping("/")
public Order addOrder (@RequestBody Order order) {
order.setId((long ) (orders.size() + 1 ));
orders.add(order);
return order;
}
@PutMapping("/{id}")
public Order updateOrder (@PathVariable Long id, @RequestBody Order order) {
Order existingOrder = getOrderById(id);
if (existingOrder != null ) {
existingOrder.setOrderId(order.getOrderId());
existingOrder.setProducts(order.getProducts());
}
return existingOrder;
}
@DeleteMapping("/{id}")
public void deleteOrder (@PathVariable Long id) {
orders.removeIf(order -> order.getId().equals(id));
}
@GetMapping("/{id}/products")
public List<Product> getOrderProducts (@PathVariable Long id) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products;
}
return new ArrayList <>();
}
@PostMapping("/{id}/products")
public Order addOrderProduct (@PathVariable Long id, @RequestBody Product product) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().add(product);
}
return order;
}
@DeleteMapping("/{id}/products/{productId}")
public Order deleteOrderProduct (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().removeIf(product -> product.getId().equals(productId));
}
return order;
}
@GetMapping("/{id}/product/{productId}")
public Product getProductById (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products.stream().filter(product -> product.getId().equals(productId)).findFirst().orElse(null );
}
return null ;
}
}
服务消费者(Order Service)的启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {
public static void main (String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderServiceApplicationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
void contextLoads () {}
@Test
void testGetAllOrders () {
List<Order> orders = restTemplate.getForObject("http://localhost:" + port + "/api/orders/" , List.class);
assertThat(orders).isNotNull();
assertThat(orders.size()).isGreaterThanOrEqualTo(3 );
}
@Test
void testAddOrder () {
Order order = new Order (null , "O004" , new ArrayList <>());
Order savedOrder = restTemplate.postForObject("http://localhost:" + port + "/api/orders/" , order, Order.class);
assertThat(savedOrder).isNotNull();
assertThat(savedOrder.getOrderId()).isEqualTo("O004" );
}
@Test
void testAddOrderProduct () {
Product product = new Product (1L , "P001" , "手机" , 1000.0 , 100 );
HttpEntity<Product> requestEntity = new HttpEntity <>(product);
ResponseEntity<Order> response = restTemplate.exchange("http://localhost:" + port + "/api/orders/1/products" , HttpMethod.POST, requestEntity, Order.class);
assertThat(response.getStatusCodeValue()).isEqualTo(200 );
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getProducts().size()).isGreaterThanOrEqualTo(1 );
}
}
结论 :集成 Spring Cloud Eureka 的步骤包括创建 Spring Boot 项目、添加所需的依赖、配置 Spring Cloud Eureka、创建服务提供者、创建服务消费者、测试应用。
Spring Boot 与微服务的配置 Spring Boot 与微服务的配置是 Java 开发中的重要内容。
配置 Spring Cloud Config
创建 Spring Boot 项目。
添加所需的依赖。
配置 Spring Cloud Config。
创建配置文件。
测试应用。
配置服务器(Config Server)的 pom.xml 文件中的依赖:
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-config-server</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</artifactId >
<scope > test</scope >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-dependencies</artifactId >
<version > Hoxton.SR12</version >
<type > pom</type >
<scope > import</scope >
</dependency >
</dependencies >
</dependencyManagement >
配置服务器(Config Server)的 application.properties 文件中的配置:
# 服务器端口
server.port=8888
# 配置服务器配置
spring.cloud.config.server.git.uri=https://github.com/username/config-repo
spring.cloud.config.server.git.search-paths=config-repo
spring.cloud.config.server.git.username=username
spring.cloud.config.server.git.password=password
配置服务器(Config Server)的启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main (String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
配置客户端(Product Service)的 pom.xml 文件中的依赖:
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-starter-config</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</artifactId >
<scope > test</scope >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId > org.springframework.cloud</groupId >
<artifactId > spring-cloud-dependencies</artifactId >
<version > Hoxton.SR12</version >
<type > pom</type >
<scope > import</scope >
</dependency >
</dependencies >
</dependencyManagement >
配置客户端(Product Service)的 bootstrap.properties 文件中的配置:
# 应用名称
spring.application.name=product-service
# 配置服务器地址
spring.cloud.config.uri=http://localhost:8888
配置客户端(Product Service)的 application.properties 文件中的配置:
配置文件(product-service-dev.properties):
# 应用名称
spring.application.name=product-service
# 服务器端口
server.port=8081
# 数据库连接信息
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
# JPA 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# H2 数据库控制台
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
结论 :配置 Spring Cloud Config 是指使用 Spring Boot 与 Spring Cloud Config 集成的方法,步骤包括创建 Spring Boot 项目、添加所需的依赖、配置 Spring Cloud Config、创建配置文件、测试应用。
Spring Boot 与微服务的基本方法 Spring Boot 与微服务的基本方法包括使用 Ribbon、使用 Feign、使用 Hystrix。
使用 Ribbon 示例 :
服务消费者(Order Service)的控制器类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
private List<Order> orders = new ArrayList <>();
public OrderController () {
orders.add(new Order (1L , "O001" , new ArrayList <>()));
orders.add(new Order (2L , "O002" , new ArrayList <>()));
orders.add(new Order (3L , "O003" , new ArrayList <>()));
}
@Bean
@LoadBalanced
public RestTemplate restTemplate () {
return new RestTemplate ();
}
@GetMapping("/")
public List<Order> getAllOrders () {
return orders;
}
@GetMapping("/{id}")
public Order getOrderById (@PathVariable Long id) {
return orders.stream().filter(order -> order.getId().equals(id)).findFirst().orElse(null );
}
@PostMapping("/")
public Order addOrder (@RequestBody Order order) {
order.setId((long ) (orders.size() + 1 ));
orders.add(order);
return order;
}
@PutMapping("/{id}")
public Order updateOrder (@PathVariable Long id, @RequestBody Order order) {
Order existingOrder = getOrderById(id);
if (existingOrder != null ) {
existingOrder.setOrderId(order.getOrderId());
existingOrder.setProducts(order.getProducts());
}
return existingOrder;
}
@DeleteMapping("/{id}")
public void deleteOrder (@PathVariable Long id) {
orders.removeIf(order -> order.getId().equals(id));
}
@GetMapping("/{id}/products")
public List<Product> getOrderProducts (@PathVariable Long id) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products;
}
return new ArrayList <>();
}
@PostMapping("/{id}/products")
public Order addOrderProduct (@PathVariable Long id, @RequestBody Product product) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().add(product);
}
return order;
}
@DeleteMapping("/{id}/products/{productId}")
public Order deleteOrderProduct (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().removeIf(product -> product.getId().equals(productId));
}
return order;
}
@GetMapping("/{id}/product/{productId}")
public Product getProductById (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products.stream().filter(product -> product.getId().equals(productId)).findFirst().orElse(null );
}
return null ;
}
}
结论 :使用 Ribbon 是指 Spring Boot 与微服务集成的基本方法之一,作用是实现服务间的通信、提高应用程序的性能。
Spring Boot 的实际应用场景 在实际开发中,Spring Boot 微服务架构设计与实现的应用场景非常广泛,如:
实现产品服务的微服务化。
实现用户服务的微服务化。
实现订单服务的微服务化。
实现支付服务的微服务化。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main (String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
@RestController
@RequestMapping("/api/products")
class ProductController {
private List<Product> products = new ArrayList <>();
public ProductController () {
products.add(new Product (1L , "P001" , "手机" , 1000.0 , 100 ));
products.add(new Product (2L , "P002" , "电脑" , 5000.0 , 50 ));
products.add(new Product (3L , "P003" , "电视" , 3000.0 , 80 ));
products.add(new Product (4L , "P004" , "手表" , 500.0 , 200 ));
products.add(new Product (5L , "P005" , "耳机" , 300.0 , 150 ));
}
@GetMapping("/")
public List<Product> getAllProducts () {
return products;
}
@GetMapping("/{id}")
public Product getProductById (@PathVariable Long id) {
return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null );
}
@PostMapping("/")
public Product addProduct (@RequestBody Product product) {
product.setId((long ) (products.size() + 1 ));
products.add(product);
return product;
}
@PutMapping("/{id}")
public Product updateProduct (@PathVariable Long id, @RequestBody Product product) {
Product existingProduct = getProductById(id);
if (existingProduct != null ) {
existingProduct.setProductId(product.getProductId());
existingProduct.setProductName(product.getProductName());
existingProduct.setPrice(product.getPrice());
existingProduct.setSales(product.getSales());
}
return existingProduct;
}
@DeleteMapping("/{id}")
public void deleteProduct (@PathVariable Long id) {
products.removeIf(product -> product.getId().equals(id));
}
}
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {
public static void main (String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
@RestController
@RequestMapping("/api/orders")
class OrderController {
@Autowired
private RestTemplate restTemplate;
private List<Order> orders = new ArrayList <>();
public OrderController () {
orders.add(new Order (1L , "O001" , new ArrayList <>()));
orders.add(new Order (2L , "O002" , new ArrayList <>()));
orders.add(new Order (3L , "O003" , new ArrayList <>()));
}
@Bean
@LoadBalanced
public RestTemplate restTemplate () {
return new RestTemplate ();
}
@GetMapping("/")
public List<Order> getAllOrders () {
return orders;
}
@GetMapping("/{id}")
public Order getOrderById (@PathVariable Long id) {
return orders.stream().filter(order -> order.getId().equals(id)).findFirst().orElse(null );
}
@PostMapping("/")
public Order addOrder (@RequestBody Order order) {
order.setId((long ) (orders.size() + 1 ));
orders.add(order);
return order;
}
@PutMapping("/{id}")
public Order updateOrder (@PathVariable Long id, @RequestBody Order order) {
Order existingOrder = getOrderById(id);
if (existingOrder != null ) {
existingOrder.setOrderId(order.getOrderId());
existingOrder.setProducts(order.getProducts());
}
return existingOrder;
}
@DeleteMapping("/{id}")
public void deleteOrder (@PathVariable Long id) {
orders.removeIf(order -> order.getId().equals(id));
}
@GetMapping("/{id}/products")
public List<Product> getOrderProducts (@PathVariable Long id) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products;
}
return new ArrayList <>();
}
@PostMapping("/{id}/products")
public Order addOrderProduct (@PathVariable Long id, @RequestBody Product product) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().add(product);
}
return order;
}
@DeleteMapping("/{id}/products/{productId}")
public Order deleteOrderProduct (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
order.getProducts().removeIf(product -> product.getId().equals(productId));
}
return order;
}
@GetMapping("/{id}/product/{productId}")
public Product getProductById (@PathVariable Long id, @PathVariable Long productId) {
Order order = getOrderById(id);
if (order != null ) {
List<Product> products = order.getProducts();
return products.stream().filter(product -> product.getId().equals(productId)).findFirst().orElse(null );
}
return null ;
}
}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderServiceApplicationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
void contextLoads () {}
@Test
void testGetAllOrders () {
List<Order> orders = restTemplate.getForObject("http://localhost:" + port + "/api/orders/" , List.class);
assertThat(orders).isNotNull();
assertThat(orders.size()).isGreaterThanOrEqualTo(3 );
}
@Test
void testAddOrder () {
Order order = new Order (null , "O004" , new ArrayList <>());
Order savedOrder = restTemplate.postForObject("http://localhost:" + port + "/api/orders/" , order, Order.class);
assertThat(savedOrder).isNotNull();
assertThat(savedOrder.getOrderId()).isEqualTo("O004" );
}
@Test
void testAddOrderProduct () {
Product product = new Product (1L , "P001" , "手机" , 1000.0 , 100 );
HttpEntity<Product> requestEntity = new HttpEntity <>(product);
ResponseEntity<Order> response = restTemplate.exchange("http://localhost:" + port + "/api/orders/1/products" , HttpMethod.POST, requestEntity, Order.class);
assertThat(response.getStatusCodeValue()).isEqualTo(200 );
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getProducts().size()).isGreaterThanOrEqualTo(1 );
}
}
结论 :在实际开发中,Spring Boot 微服务架构设计与实现的应用场景非常广泛,需要根据实际问题选择合适的微服务架构和工具。
总结 本章我们学习了 Spring Boot 微服务架构设计与实现,包括微服务架构的定义与特点、Spring Boot 与微服务的集成、Spring Boot 与微服务的配置、Spring Boot 与微服务的基本方法、Spring Boot 的实际应用场景,学会了在实际开发中处理微服务架构设计与实现问题。其中,微服务架构的定义与特点、Spring Boot 与微服务的集成、Spring Boot 与微服务的配置、Spring Boot 与微服务的基本方法、Spring Boot 的实际应用场景是本章的重点内容。从下一章开始,我们将学习 Spring Boot 的其他组件、微服务等内容。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online