Section 9: 实现订单微服务 (02:42:50 - 04:40:50)
创建订单微服务 (02:42:50 - 03:04:11)¶
首先,让我们创建订单微服务。我们将使用 Spring Initializr 或者 IntelliJ IDEA 创建一个新的 Maven 项目,并添加以下依赖项: ⏎
- Spring Web
- Spring Data JPA
- PostgreSQL Driver
- Spring Cloud Starter Config
- Spring Cloud Starter Netflix Eureka Client (或者 Spring Cloud Starter Discovery,取决于 Spring Cloud 版本)
- Lombok
- OpenFeign
创建好项目后,我们需要定义实体类。 ⏎
- Order Entity: 订单实体,包含订单的基本信息,例如订单 ID、订单编号、总金额、支付方式、客户 ID、订单明细列表、创建日期和最后修改日期。 ⏎
- OrderLine Entity: 订单明细实体,表示订单中的每一项商品,包含商品 ID、数量等信息。 ⏎
- PaymentMethod Enum: 支付方式枚举,定义了应用程式支持的支付方式,例如 PayPal、信用卡、Visa 卡、MasterCard 和 Bitcoin。 ⏎
package com.alibou.ecommerce.order;
public enum PaymentMethod {
PAYPAL,
CREDIT_CARD,
VISA_CARD,
MASTERCARD,
BITCOIN
}
实现订单控制器和服务 (03:04:11 - 04:01:07)¶
接下来,我们将实现订单控制器和服务。 ⏎ 订单控制器负责接收来自客户端的请求,并调用订单服务来处理这些请求。订单服务则负责处理订单相关的业务逻辑,例如创建订单、查询订单等。 ⏎
@RestController
@RequestMapping("/api/v1/orders")
@RequiredArgsConstructor
public class OrderController {
private final OrderService service;
@PostMapping
public ResponseEntity<Integer> createOrder(@RequestBody @Valid OrderRequest request) {
return ResponseEntity.ok(service.createOrder(request));
}
// Other methods: findAll, findById
}
在订单服务中,我们需要实现以下步骤:
- 检查客户 (Check Customer): 首先,我们需要检查客户是否存在。我们将使用 OpenFeign 调用客户微服务来获取客户信息。 ⏎ 为了使用 OpenFeign,我们需要创建一个
CustomerClient接口,并使用@FeignClient注解来指定客户微服务的服务名称和 URL。
package com.alibou.ecommerce.customer;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.Optional;
@FeignClient(name = "customer-service", url = "${application.config.customer-url}")
public interface CustomerClient {
@GetMapping("/api/v1/customers/{customer-id}")
Optional<CustomerResponse> findCustomerById(@PathVariable("customer-id") String customerId);
}
@Service
@RequiredArgsConstructor
public class ProductClient {
@Value("${application.config.product-url}")
private String productURL;
private final RestTemplate restTemplate;
public List<PurchaseResponse> purchaseProducts(List<PurchaseRequest> requestBody) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<List<PurchaseRequest>> requestEntity = new HttpEntity<>(requestBody, headers);
ParameterizedTypeReference<List<PurchaseResponse>> responseType = new ParameterizedTypeReference<>() {};
ResponseEntity<List<PurchaseResponse>> responseEntity = restTemplate.exchange(
productURL + "/purchase",
HttpMethod.POST,
requestEntity,
responseType
);
// Error handling
if (responseEntity.getStatusCode().isError()) {
throw new BusinessException("An error occurred while processing the product purchase: " + responseEntity.getStatusCode());
}
return responseEntity.getBody();
}
}
Remember to create a configuration class to expose the RestTemplate as a bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
@RequiredArgsConstructor
public class OrderProducer {
private final KafkaTemplate<String, OrderConfirmation> kafkaTemplate;
public void sendOrderConfirmation(OrderConfirmation orderConfirmation) {
log.info("Sending order confirmation with body {}", orderConfirmation);
Message<OrderConfirmation> message = MessageBuilder
.withPayload(orderConfirmation)
.setHeader(KafkaHeaders.TOPIC, "order-topic")
.build();
kafkaTemplate.send(message);
}
}
最后,我们需要配置 Kafka,包括添加依赖、配置 Kafka 主题等。我们将在下一步中详细介绍 Kafka 的配置。 ⏎
配置 Kafka:
spring:
kafka:
producer:
bootstrap-servers: localhost:9092
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
properties:
spring.json.type.mapping: "orderConfirmation:com.alibou.ecommerce.order.OrderConfirmation" # Replace with actual package name
trusted:
packages: '*' # com.alibou.ecommerce