Tạo ứng dụng Chat với Spring Boot và Websocket
Trong bài viết này, chúng ta sẽ hướng dẫn chi tiết về cách tạo một ứng dụng Chat đơn giản với Spring Boot và Websocket.
Trong thế giới công nghệ hiện đại, ứng dụng Chat trở thành một phần không thể thiếu trong cuộc sống hàng ngày của chúng ta. Với sự phát triển của Spring Boot và Websocket, việc tạo ra một ứng dụng Chat đơn giản không còn là điều quá khó khăn.
1. Giới thiệu
Giới thiệu chung về Spring Boot và Websocket
Bạn có thể tham khảo các khái niện về Spring Boot trong bài viết này nhé!!!
Vậy Websocket là gì?
Bài viết này được đăng tại [free tuts .net]
Websocket là một giao thức truyền tải dữ liệu hai chiều giữa máy chủ và trình duyệt web, cho phép thiết lập một kết nối liên tục và định kỳ giữa chúng. Với Websocket, thông tin có thể được truyền tải theo thời gian thực và có thể được truyền tải nhanh chóng và hiệu quả hơn so với các phương thức truyền tải dữ liệu truyền thống khác như HTTP.
Về cơ bản, Websocket là một cách để thiết lập một kết nối liên tục giữa máy chủ và trình duyệt web, cho phép chúng trao đổi dữ liệu với nhau. Khi kết nối được thiết lập, các thông điệp có thể được gửi và nhận theo thời gian thực và không cần phải thiết lập lại kết nối. Điều này giúp giảm thiểu độ trễ và tăng tốc độ truyền tải dữ liệu trong các ứng dụng đòi hỏi tính năng thời gian thực như Chat, Game, và Video conference.
Mục đích và phạm vi của bài viết
Mục đích của bài viết này là hướng dẫn người đọc cách tạo một ứng dụng Chat đơn giản sử dụng Spring Boot và Websocket. Bài viết sẽ cung cấp cho người đọc một hướng dẫn chi tiết về cách triển khai ứng dụng này, từ khởi tạo dự án đến triển khai ứng dụng.
Phạm vi của bài viết sẽ tập trung vào việc triển khai một ứng dụng Chat đơn giản sử dụng Spring Boot và Websocket. Bài viết sẽ giải thích chi tiết các khái niệm và công nghệ được sử dụng trong ứng dụng, cùng với các bước cụ thể để triển khai ứng dụng. Tuy nhiên, bài viết sẽ không đi sâu vào các khái niệm và tính năng phức tạp của Spring Boot và Websocket, và sẽ tập trung vào việc hướng dẫn người đọc triển khai một ứng dụng Chat đơn giản.
2. Các bước để tạo ứng dụng Chat đơn giản với Spring Boot và Websocket
Chuẩn bị môi trường phát triển
Yêu cầu cấu hình và công cụ cần thiết:
Trước khi bắt đầu, chúng ta cần phải chuẩn bị môi trường phát triển để có thể triển khai ứng dụng Chat đơn giản với Spring Boot và Websocket.
Cụ thể, chúng ta cần có:
-
JDK (Java Development Kit) 11 hoặc mới hơn: JDK là một bộ công cụ phát triển Java được sử dụng để biên dịch và thực thi các chương trình Java. Chúng ta có thể tải và cài đặt JDK từ trang web của Oracle hoặc OpenJDK.
-
Maven: Maven là một công cụ quản lý dự án phổ biến được sử dụng để quản lý các thư viện phụ thuộc và xây dựng các ứng dụng Java. Chúng ta có thể tải và cài đặt Maven từ trang web của Apache Maven.
-
Trình biên dịch code Java: Chúng ta có thể sử dụng một trình biên dịch code Java như Eclipse hoặc IntelliJ IDEA để phát triển ứng dụng.
Cài đặt và cấu hình Spring Boot:
Sau khi đã cài đặt môi trường phát triển, chúng ta cần phải cài đặt và cấu hình Spring Boot. Các bước cài đặt và cấu hình Spring Boot như sau:
Bước 1: Tạo project Spring Boot
Để bắt đầu, chúng ta cần tạo một project Spring Boot mới bằng cách sử dụng Spring Initializr. Chúng ta có thể truy cập Spring Initializr từ trang web của Spring Boot hoặc sử dụng các trình quản lý dự án như Eclipse hoặc IntelliJ IDEA để tạo project Spring Boot.
Bước 2: Thêm các thư viện Spring Boot WebSocket
Sau khi đã tạo project Spring Boot, chúng ta cần thêm các thư viện cần thiết để triển khai WebSocket. Chúng ta có thể thêm các thư viện này vào file pom.xml của project:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies>
Bước 3: Cấu hình WebSocket trong ứng dụng
Tiếp theo, chúng ta cần cấu hình WebSocket trong ứng dụng. Chúng ta có thể cấu hình WebSocket bằng cách tạo một class WebSocketConfig trong package config của project:
@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(chatWebSocketHandler(), "/chat"); } @Bean public WebSocketHandler chatWebSocketHandler() { return new ChatWebSocketHandler();
Tạo project Spring Boot:
Và sau đây sẽ là các bước tạo một project Spring boot bằng Spring Initializr
Bước 1: Truy cập trang https://start.spring.io/ để mở Spring Initializr.
Bước 2: Chọn các thông số cho project của bạn, bao gồm:
- Group: Group ID của project, ví dụ com.example.
- Artifact: Tên của project, ví dụ chat-app.
- Dependencies: Các dependency cần thiết cho project của bạn. Trong trường hợp này, bạn cần chọn Web và WebSocket.
Bước 3: Sau khi chọn các thông số cần thiết, nhấn nút Generate để tạo project của bạn.
Bước 4: Sau khi tạo xong, tải project về máy tính của bạn dưới dạng file zip.
Bước 5: Giải nén file zip và mở project bằng trình biên dịch của bạn, chẳng hạn như IntelliJ IDEA hay Eclipse.
Bước 6: Bây giờ bạn đã có một project Spring Boot với WebSocket được tích hợp sẵn. Bạn có thể tiếp tục triển khai mã nguồn để tạo một ứng dụng Chat đơn giản.
Tạo Model cho ứng dụng
Định nghĩa Model:
- Định nghĩa các lớp User (người dùng) và Message (tin nhắn) với các thuộc tính tương ứng.
- Các thuộc tính cho lớp User có thể bao gồm id, username, password, avatar, ... Các thuộc tính cho lớp Message có thể bao gồm id, sender (người gửi), content (nội dung tin nhắn), timestamp (thời gian gửi), ...
Tạo các class để đại diện cho người dùng và tin nhắn
Sau đây là đoạn code ví dụ cho các lớp User và Message:
// Class User public class User { private Long id; private String username; private String password; private String avatar; // constructor, getter và setter } // Class Message public class Message { private Long id; private User sender; private String content; private LocalDateTime timestamp; // constructor, getter và setter }
Ở đây, lớp User có các thuộc tính id (mã người dùng), username (tên đăng nhập), password (mật khẩu), và avatar (ảnh đại diện). Lớp Message có các thuộc tính id (mã tin nhắn), sender (người gửi tin nhắn), content (nội dung tin nhắn), và timestamp (thời gian gửi tin nhắn).
Xây dựng Repository
Để sử dụng các lớp này trong ứng dụng, cần tạo các repository để lưu trữ và truy vấn dữ liệu.
Ví dụ, ta có thể sử dụng JPA và Hibernate để lưu trữ dữ liệu trong cơ sở dữ liệu:
// Repository User @Repository public interface UserRepository extends JpaRepository<User, Long> { User findByUsername(String username); } // Repository Message @Repository public interface MessageRepository extends JpaRepository<Message, Long> { List<Message> findByOrderByTimestampAsc(); }
Ở đây, UserRepository có phương thức findByUsername() để tìm kiếm người dùng theo tên đăng nhập, còn MessageRepository có phương thức findByOrderByTimestampAsc() để lấy danh sách tin nhắn đã được sắp xếp theo thời gian gửi tăng dần.
Xây dựng giao diện người dùng
Tạo trang đăng nhập
Tạo trang đăng nhập (login page) với form nhập thông tin tài khoản người dùng (username và password).
Ví dụ về template HTML cho trang đăng nhập:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Chat App - Login</title> <link rel="stylesheet" href="/css/login.css"> </head> <body> <div class="login-container"> <div class="login-box"> <h1>Chat App</h1> <form id="login-form"> <div class="form-group"> <label for="username">Username:</label> <input type="text" id="username" name="username" placeholder="Enter your username"> </div> <div class="form-group"> <label for="password">Password:</label> <input type="password" id="password" name="password" placeholder="Enter your password"> </div> <button type="submit">Login</button> </form> </div> </div> <script src="/js/jquery.min.js"></script> <script src="/js/login.js"></script> </body> </html>
Tạo trang chat
Tạo trang chat (chat page) để hiển thị danh sách tin nhắn và cho phép người dùng gửi tin nhắn mới. Giao diện có thể sử dụng HTML, CSS và JavaScript để tạo ra các thành phần UI cần thiết.
Ví dụ về template HTML cho trang chat:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Chat Application</title> <link rel="stylesheet" href="/css/style.css"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-4"> <h3>Welcome, <span id="username"></span>!</h3> <div class="online-users"> <h4>Online Users:</h4> <ul id="online-users-list"></ul> </div> </div> <div class="col-md-8"> <div class="chat-box"> <ul id ="chat-box-list"></ul> <form id="chat-form"> <input type="text" id="message-input" placeholder="Type your message..."> <button type="submit">Send</button> </form> </div> </div> </div> </div> <script src="/js/jquery.min.js"></script> <script src="/js/stomp.min.js"></script> <script src="/js/chat.js"></script> </body> </html>
Và đoạn code JavaScript để kết nối với server và gửi nhận tin nhắn:
$(document).ready(function() { var stompClient = null; var username = null; function connect() { var socket = new SockJS('/websocket'); stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/public', function(chatMessage) { var message = JSON.parse(chatMessage.body); displayMessage(message); }); stompClient.subscribe('/topic/userlist', function(onlineUsers) { var users = JSON.parse(onlineUsers.body); displayOnlineUsers(users); }); sendUserJoinMessage(); }); } function sendUserJoinMessage() { var chatMessage = { senderId: $('#sender-id').val(), senderName: $('#sender-name').val(), content: '', type: 'JOIN' }; stompClient.send('/app/chat.addUser', {}, JSON.stringify(chatMessage)); username = $('#sender-name').val(); $('#username').text(username); } function displayMessage(message) { var chatBoxList = $('#chat-box-list'); var messageClass = 'chat-box-list-item'; if (message.senderName === username) { messageClass += ' chat-box-list-item-mine'; } var messageHtml = '<li class="' + messageClass + '">'; messageHtml += '<div class="chat-box-list-item-sender">' + message.senderName + '</div>'; messageHtml += '<div class="chat-box-list-item-content">' + message.content + '</div>'; messageHtml += '</li>'; chatBoxList.append(messageHtml); chatBoxList.scrollTop(chatBoxList.prop('scrollHeight')); } function displayOnlineUsers(users) { var onlineUsersList = $('#online-users-list'); onlineUsersList.empty(); users.forEach(function(user) { var userHtml = '<li>' + user.name + '</li>'; onlineUsersList.append(userHtml); }); } $('#chat-form').on('submit', function(e) { e.preventDefault(); var messageInput = $('#message-input'); var chatMessage = { senderId: $('#sender-id').val(), senderName: $('#sender-name').val(), content: messageInput.val(), type: 'CHAT' }; stompClient.send('/app/chat.sendMessage', {}, JSON.stringify(chatMessage)); messageInput.val(''); }); connect(); });
Tạo các controller
Tạo controller cho trang đăng nhập
Tạo một UserController để xử lý các yêu cầu liên quan đến đăng nhập, đăng ký và đăng xuất của người dùng. Điều này có thể được thực hiện bằng cách sử dụng các phương thức POST và GET để lấy thông tin người dùng và thực hiện các hoạt động liên quan đến đăng nhập.
Sau khi đã định nghĩa các lớp và repository, ta có thể xây dựng các controller để xử lý các yêu cầu từ người dùng.
Ví dụ, ta có thể tạo UserController để xử lý yêu cầu đăng nhập và đăng ký:
// UserController @Controller public class UserController { @Autowired private UserRepository userRepository; @PostMapping("/login") public String login(@RequestParam("username") String username, @RequestParam("password") String password, HttpSession session) { User user = userRepository.findByUsername(username); if (user != null && user.getPassword().equals(password)) { session.setAttribute("user", user); return "redirect:/chat"; } else { return "redirect:/login"; } } @PostMapping("/register") public String register(@ModelAttribute("user") User user) { userRepository.save(user); return "redirect:/login"; } @GetMapping("/logout") public String logout(HttpSession session) { session.invalidate(); return "redirect:/login"; } }
Ở đây, phương thức login() sẽ kiểm tra xem người dùng có tồn tại trong cơ sở dữ liệu và có nhập đúng mật khẩu không, nếu đúng thì lưu thông tin người dùng vào session và chuyển hướng sang trang chat, còn nếu sai thì chuyển hướng lại trang đăng nhập. Phương thức register() sẽ lưu thông tin người dùng mới vào cơ sở dữ liệu, còn phương thức logout() sẽ xóa thông tin người dùng khỏi session và chuyển hướng lại trang đăng nhập.
Tạo controller cho trang chat
Tạo một ChatController để xử lý các yêu cầu liên quan đến trao đổi tin nhắn giữa người dùng. Điều này có thể được thực hiện bằng cách sử dụng Websocket để thiết lập kết nối giữa người dùng và máy chủ, và gửi tin nhắn qua kết nối này.
// ChatController @Controller public class ChatController { @Autowired private UserRepository userRepository; @Autowired private MessageRepository messageRepository; @GetMapping("/chat") public String chat(Model model, HttpSession session) { User user = (User) session.getAttribute("user"); if (user == null) { return "redirect:/login"; } List<Message> messages = messageRepository.findByOrderByTimestampAsc(); model.addAttribute("user", user); model.addAttribute("messages", messages); return "chat"; } @MessageMapping("/chat.sendMessage") @SendTo("/topic/public") public ChatMessage sendMessage(@Payload ChatMessage chatMessage) { User sender = userRepository.getOne(chatMessage.getSenderId()); Message message = new Message(); message.setSender(sender); message.setContent(chatMessage.getContent()); message.setTimestamp(LocalDateTime.now()); messageRepository.save(message); return chatMessage; } @MessageMapping("/chat.addUser") @SendTo("/topic/public") public ChatMessage addUser(@Payload ChatMessage chatMessage, SimpMessageHeaderAccessor headerAccessor) { User user = userRepository.getOne(chatMessage.getSenderId()); headerAccessor.getSessionAttributes().put("user", user); return chatMessage; } }
Ở đây, phương thức chat() sẽ kiểm tra xem người dùng đã đăng nhập chưa và lấy danh sách tin nhắn từ cơ sở dữ liệu để hiển thị lên trang chat. Phương thức sendMessage() và addUser() sẽ được gọi khi người dùng gửi tin nhắn hoặc tham gia vào phòng chat, và sẽ lưu tin nhắn mới vào cơ sở dữ liệu và gửi lại tin nhắn đó cho tất cả các người dùng khác trong phòng chat.
Đó là các bước để tạo ứng dụng Chat đơn giản với Spring Boot và Websocket. Bạn có thể tự do tùy chỉnh các class và template để phù hợp với nhu cầu của mình nhé!!
3. Xây dựng Websocket
Để xây dựng Websocket cho ứng dụng chat, bạn có thể làm theo các bước sau:
Định nghĩa Websocket endpoint
Bạn cần tạo một class endpoint để định nghĩa các phương thức để xử lý kết nối Websocket và các tin nhắn.
Ví dụ:
import org.springframework.stereotype.Component; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Component @EnableWebSocket public class ChatWebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new ChatWebSocketHandler(), "/chat").setAllowedOrigins("*"); } }
Xây dựng logic xử lý tin nhắn trong Websocket
Bạn cần tạo một class để xử lý tin nhắn và kết nối của các client.
Ví dụ:
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.AbstractWebSocketHandler; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ChatWebSocketHandler extends AbstractWebSocketHandler { private Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.put(session.getId(), session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session.getId()); } @Override public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions.values()) { s.sendMessage(message); } } }
Trong ví dụ này, chúng ta sử dụng một ConcurrentHashMap để lưu trữ các WebSocketSession của các client kết nối tới. Khi có tin nhắn mới, chúng ta sử dụng vòng lặp để gửi tin nhắn đến tất cả các session của client kết nối tới.
Kết nối Websocket với ứng dụng
Bạn cần bổ sung một số cấu hình cho ứng dụng để kết nối với Websocket.
Ví dụ:
@Configuration public class ChatAppConfig { @Bean public WebSocketHandler chatWebSocketHandler() { return new ChatWebSocketHandler(); } @Bean public HandlerMapping webSocketHandlerMapping() { Map<String, WebSocketHandler> map = new HashMap<>(); map.put("/chat", chatWebSocketHandler()); SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); mapping.setOrder(Ordered.HIGHEST_PRECEDENCE); mapping.setUrlMap(map); return mapping; } @Bean public WebSocketHandlerAdapter handlerAdapter() { return new WebSocketHandlerAdapter(); } }
Trong ví dụ này, chúng ta sử dụng các Bean để đăng ký ChatWebSocketHandler, HandlerMapping và WebSocketHandlerAdapter. HandlerMapping giúp định tuyến WebSocket đến ChatWebSocketHandler, trong khi WebSocketHandlerAdapter giúp kết nối Websocket với ứng dụng.
4. Các câu hỏi thường gặp
Tại sao nên sử dụng Spring Boot và WebSocket để phát triển ứng dụng Chat?
Sử dụng Spring Boot và WebSocket để phát triển ứng dụng Chat có nhiều lợi ích, bao gồm:
- Dễ dàng triển khai và sử dụng.
- Hiệu suất cao, giúp giảm thiểu độ trễ và lưu lượng mạng.
- Hỗ trợ các tính năng bảo mật như xác thực người dùng và mã hóa dữ liệu.
- Được cộng đồng lớn hỗ trợ và phát triển.
WebSocket có thể sử dụng được trên các trình duyệt nào?
WebSocket được hỗ trợ trên hầu hết các trình duyệt hiện đại như Chrome, Firefox, Safari và Edge.
Tôi cần phải cài đặt gì để sử dụng WebSocket trên Spring Boot?
Bạn không cần phải cài đặt thêm bất kỳ thư viện nào để sử dụng WebSocket trên Spring Boot, bởi vì nó được tích hợp sẵn trong Spring Framework. Bạn chỉ cần định nghĩa WebSocket endpoint và xây dựng các phương thức xử lý tin nhắn cho nó.
5. Kết bài viết
Cảm ơn bạn đã theo dõi và đọc hết nội dung này. Hy vọng bài viết đã giúp bạn hiểu rõ hơn về cách phát triển ứng dụng Chat đơn giản với Spring Boot và WebSocket. Nếu bạn có bất kỳ câu hỏi hoặc ý kiến đóng góp nào, xin hãy để lại trong phần bình luận bên dưới. Cảm ơn bạn rất nhiều và chúc bạn thành công trong việc phát triển ứng dụng của mình!