Section 12: 实现通知微服务 (05:24:10 - 06:12:24)
创建通知微服务 (05:24:10 - 05:44:04)¶
现在,让我们创建通知微服务。我们将使用 Spring Initializr 或 IntelliJ IDEA 创建一个新的 Maven 项目,并添加以下依赖项: ⏎
- Spring Mail
- Spring Data MongoDB (optional, 如果需要持久化通知信息)
- Thymeleaf (如果需要使用模板引擎生成邮件内容)
- Spring Cloud Starter Config
- Spring Cloud Starter Netflix Eureka Client
- Spring for Apache Kafka
- Lombok
创建好项目后,我们需要定义实体类。 ⏎
- Notification Entity: 通知实体,包含通知的基本信息,例如通知 ID、通知类型、通知日期、订单确认信息或支付确认信息。 ⏎
- NotificationType Enum: 通知类型枚举,定义了通知的类型,例如订单确认和支付确认。 ⏎
package com.alibou.ecommerce.notification;
public enum NotificationType {
ORDER_CONFIRMATION,
PAYMENT_CONFIRMATION
}
实现 Kafka 消费者 (05:44:04 - 05:53:58)¶
接下来,我们将实现 Kafka 消费者,用于监听 Kafka 队列并接收订单确认和支付确认消息。 ⏎
创建名为 NotificationConsumer 的类,并添加以下代码:
package com.alibou.ecommerce.kafka;
import com.alibou.ecommerce.email.EmailService;
import com.alibou.ecommerce.notification.NotificationRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.annotation.KafkaListener;
import com.alibou.ecommerce.notification.Kafka.PaymentNotificationRequest;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
@Slf4j
public class NotificationConsumer {
private final NotificationRepository repository;
private final EmailService emailService;
@KafkaListener(topics = "payment-topic")
public void consumePaymentSuccessNotification(PaymentNotificationRequest paymentConfirmation) {
log.info("Consuming message from payment topic {}", paymentConfirmation);
// TODO: Save notification to database (optional)
try {
emailService.sendPaymentSuccessEmail(
paymentConfirmation.getCustomerEmail(),
paymentConfirmation.getCustomerFirstName() + " " + paymentConfirmation.getCustomerLastName(),
paymentConfirmation.getAmount(),
paymentConfirmation.getOrderReference()
);
} catch (MessagingException e) {
log.warn("Cannot send email to {}", paymentConfirmation.getCustomerEmail());
}
}
@KafkaListener(topics = "order-topic")
public void consumeOrderConfirmationNotification(OrderConfirmation orderConfirmation) {
log.info("Consuming message from order topic {}", orderConfirmation);
// TODO: Save notification to database (optional)
try {
emailService.sendOrderConfirmationEmail(
orderConfirmation.getCustomerEmail(),
orderConfirmation.getCustomerFirstName() + " " + orderConfirmation.getCustomerLastName(),
orderConfirmation.getTotalAmount(),
orderConfirmation.getOrderReference(),
orderConfirmation.getProducts()
);
} catch (MessagingException e) {
log.warn("Cannot send email to {}", orderConfirmation.getCustomerEmail());
}
}
}
在这个类中,我们使用 @KafkaListener 注解来指定监听的 Kafka 主题。当 Kafka 队列中有新的消息时,相应的方法会被自动调用。
实现邮件服务 (05:53:58 - 06:12:24)¶
接下来,我们需要实现邮件服务,用于发送邮件通知。 ⏎
创建一个名为 EmailService 的类,并添加以下代码:
package com.alibou.ecommerce.email;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender mailSender;
private final TemplateEngine templateEngine;
@Value("contact@aliboucoding.com")
private String fromEmail;
@Async
public void sendPaymentSuccessEmail(String destinationEmail, String customerName, BigDecimal amount, String orderReference) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
String templateName = EmailTemplates.PAYMENT_CONFIRMATION.getTemplate();
String subject = EmailTemplates.PAYMENT_CONFIRMATION.getSubject();
Map<String, Object> variables = new HashMap<>();
variables.put("customerName", customerName);
variables.put("amount", amount);
variables.put("orderReference", orderReference);
Context context = new Context();
context.setVariables(variables);
String htmlTemplate = templateEngine.process(templateName, context);
helper.setTo(destinationEmail);
helper.setText(htmlTemplate, true);
helper.setSubject(subject);
helper.setFrom(fromEmail);
mailSender.send(message);
}
@Async
public void sendOrderConfirmationEmail(String destinationEmail, String customerName, BigDecimal totalAmount, String orderReference, List<Product> products) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
String templateName = EmailTemplates.ORDER_CONFIRMATION.getTemplate();
String subject = EmailTemplates.ORDER_CONFIRMATION.getSubject();
Map<String, Object> variables = new HashMap<>();
variables.put("customerName", customerName);
variables.put("totalAmount", totalAmount);
variables.put("orderReference", orderReference);
variables.put("products", products);
Context context = new Context();
context.setVariables(variables);
String htmlTemplate = templateEngine.process(templateName, context);
helper.setTo(destinationEmail);
helper.setText(htmlTemplate, true);
helper.setSubject(subject);
helper.setFrom(fromEmail);
mailSender.send(message);
}
}
在这个类中,我们注入了 JavaMailSender 和 TemplateEngine。 ⏎
sendPaymentSuccessEmail 和 sendOrderConfirmationEmail 方法分别用于发送支付成功确认邮件和订单确认邮件。这些方法使用 Thymeleaf 模板引擎来生成邮件内容,并将相关信息传递给模板。 ⏎
我们需要配置邮件服务器的相关信息,例如主机、端口、用户名和密码。 ⏎
这些信息可以在 application.yml 文件中进行配置。
spring:
mail:
host: localhost
port: 1025
username: alibou
password: alibou
properties:
mail:
smtp:
auth: true
starttls:
enable: true
connection:
timeout: 5000
timeout: 3000
writetimeout: 5000
确保你已经安装了 MailDev 工具,并配置了正确的端口。
同时,我们需要在 src/main/resources/templates 目录下创建邮件模板。 ⏎
创建两个 HTML 文件:payment-confirmation.html 和 order-confirmation.html,并添加相应的邮件内容。
至此,通知微服务也完成了配置。