[Java Backend Zero to Hello] [Phase 6] BÀI 6.9: EMAIL & NOTIFICATION
📚 Series: Java Backend Zero to Hello 📂 Phân đoạn: Phase 6: REST API & Best Practices 📖 Nội dung: BÀI 6.9: EMAIL & NOTIFICATION 💡 Khóa học lập trình Backend Java & Spring Boot chuẩn doanh nghiệp từ con số 0.
BÀI 6.9: EMAIL & NOTIFICATION
Mục tiêu
- Gửi email với Spring Boot
- Sử dụng template engine
- Gửi SMS, Push notification
- Xử lý async
1. GỬI EMAIL CƠ BẢN
1.1 Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
1.2 Cấu hình
spring:
mail:
host: smtp.gmail.com
port: 587
username: your-email@gmail.com
password: your-password
properties:
mail:
smtp:
auth: true
starttls:
enable: true
1.3 JavaMailSender
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender mailSender;
public void sendSimpleEmail(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
message.setFrom("noreply@example.com");
mailSender.send(message);
}
}
2. HTML EMAIL
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender mailSender;
public void sendHtmlEmail(String to, String subject, String htmlContent) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent, true);
helper.setFrom("noreply@example.com");
mailSender.send(message);
}
}
3. EMAIL VỚI ATTACHMENT
public void sendEmailWithAttachment(String to, String subject, String text,
String attachmentPath) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
File file = new File(attachmentPath);
helper.addAttachment(file.getName(), file);
mailSender.send(message);
}
4. TEMPLATE VỚI THYMELEAF
4.1 Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
4.2 Template templates/email/welcome.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Welcome</title>
</head>
<body>
<h1>Chào mừng <span th:text="${name}">User</span>!</h1>
<p>Cảm ơn bạn đã đăng ký tài khoản.</p>
<a th:href="${activationLink}">Kích hoạt tài khoản</a>
</body>
</html>
4.3 Service
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender mailSender;
private final TemplateEngine templateEngine;
public void sendWelcomeEmail(User user) throws MessagingException {
Context context = new Context();
context.setVariable("name", user.getName());
context.setVariable("activationLink",
"https://example.com/activate?token=" + user.getActivationToken());
String html = templateEngine.process("email/welcome", context);
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(user.getEmail());
helper.setSubject("Chào mừng bạn!");
helper.setText(html, true);
mailSender.send(message);
}
}
5. ASYNC EMAIL
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "emailExecutor")
public Executor emailExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("email-");
executor.initialize();
return executor;
}
}
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender mailSender;
@Async("emailExecutor")
public void sendEmail(String to, String subject, String text) {
// Gửi email bất đồng bộ
}
}
6. SMS VỚI TWILIO
6.1 Dependency
<dependency>
<groupId>com.twilio.sdk</groupId>
<artifactId>twilio</artifactId>
<version>9.43.0</version>
</dependency>
6.2 Service
@Service
public class SmsService {
@Value("${twilio.account.sid}")
private String accountSid;
@Value("${twilio.auth.token}")
private String authToken;
@Value("${twilio.phone.number}")
private String fromNumber;
@PostConstruct
public void init() {
Twilio.init(accountSid, authToken);
}
public void sendSms(String to, String message) {
Message.creator(
new PhoneNumber(to),
new PhoneNumber(fromNumber),
message
).create();
}
}
7. PUSH NOTIFICATION VỚI FCM
7.1 Dependency
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>9.2.0</version>
</dependency>
7.2 Service
@Service
public class PushNotificationService {
private final FirebaseMessaging firebaseMessaging;
public void sendNotification(String token, String title, String body) throws FirebaseMessagingException {
Notification notification = Notification.builder()
.setTitle(title)
.setBody(body)
.build();
Message message = Message.builder()
.setToken(token)
.setNotification(notification)
.build();
firebaseMessaging.send(message);
}
}
8. IN-APP NOTIFICATION
8.1 Entity
@Entity
@Table(name = "notifications")
public class Notification {
@Id @GeneratedValue
private Long id;
@ManyToOne
private User user;
private String title;
private String message;
private String type;
private boolean read;
private LocalDateTime createdAt;
}
8.2 Service
@Service
@RequiredArgsConstructor
public class NotificationService {
private final NotificationRepository repository;
private final SimpMessagingTemplate websocket;
public Notification create(User user, String title, String message, String type) {
Notification notification = new Notification();
notification.setUser(user);
notification.setTitle(title);
notification.setMessage(message);
notification.setType(type);
notification.setRead(false);
notification.setCreatedAt(LocalDateTime.now());
Notification saved = repository.save(notification);
// Gửi qua WebSocket
websocket.convertAndSendToUser(
user.getId().toString(),
"/queue/notifications",
saved
);
return saved;
}
}
9. WEBHOOK
Gửi HTTP request khi có sự kiện.
@Service
@RequiredArgsConstructor
public class WebhookService {
private final RestTemplate restTemplate;
public void sendWebhook(String url, Object payload) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> request = new HttpEntity<>(payload, headers);
try {
restTemplate.postForEntity(url, request, String.class);
} catch (Exception e) {
log.error("Webhook failed: {}", url, e);
}
}
}
10. BÀI TẬP THỰC HÀNH
Bài 1: Welcome Email
Gửi email chào mừng khi user đăng ký.
Bài 2: Order Confirmation
Gửi email xác nhận đơn hàng với template.
Bài 3: Async Notification
Implement hệ thống notification async.
11. TÓM TẮT
| Khái niệm | Mô tả |
|---|---|
| JavaMailSender | Gửi email |
| Thymeleaf | Template |
| @Async | Bất đồng bộ |
| Twilio | SMS |
| FCM | Push notification |
| WebSocket | Real-time |
| Webhook | HTTP callback |
Bài tiếp theo: 6.10 Logging & Monitoring
🧭 Điều hướng bài học
- ⬅️ Bài trước: BÀI 6.8: FILE UPLOAD/DOWNLOAD
- ➡️ Bài tiếp theo: BÀI 6.10: LOGGING & MONITORING
- 📑 Toàn bộ lộ trình: Java Backend Zero to Hello
⭐ Hãy bookmark (clip) lại series để tiện theo dõi các bài học tiếp theo nhé!
All rights reserved