SpringBoot项目基于 WebSocket 技术实现聊天室功能
1.添加websocket依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
2.编写配置类WebSocketConfig
3.定义相关的实体类Message和ResultMessage
4.定义工具类MessageUtils用于封装消息
5.编写核心类ChatWebSocket
@ServerEndpoint("/chat/{userIp}") @Component public class ChatWebSocket { //用来存储每一个客户端对象对应的ChatEndpoint对泉 private static final Map<String, ChatWebSocket> onlineUsers = new ConcurrentHashMap<>(); private static final Logger log = LoggerFactory.getLogger(ChatWebSocket.class); private Session session; private static final String IMAGE_SAVE_PATH = "/path/save/images/"; /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(@PathParam("userIp") String userIp, Session session) { log.info("建立连接,用户ip为{}", userIp); this.session = session; //将当前对象存储到容器中 onlineUsers.put(userIp, this); //将当前在线用户的ip地址推送给所有的客户端 //1,获取消息 String message = MessageUtils.getMessage(true, null, getUserIps()); //2,调用方法进行系统消息的推达 broadcastAllUsers(message); } private void broadcastAllUsers(String message) { try { //要将该消息推送给所有的客户端 Set<String> ips = onlineUsers.keySet(); for (String ip : ips) { ChatWebSocket chatWebSocket = onlineUsers.get(ip); chatWebSocket.session.getBasicRemote().sendText(message); } } catch (Exception e) { e.printStackTrace(); } } private Set<String> getUserIps() { return onlineUsers.keySet(); } /** * 收到客户端消息后调用的方法 */ @OnMessage public void onMessage(@PathParam("userIp") String userIp, String message) { try { //将message转挽成Message对象 ObjectMapper mapper = new ObjectMapper(); Message mess = mapper.readValue(message, Message.class); String toUserIp = mess.getToUserIp(); if (mess.isImage()){ // 接收到的是图片消息 String base64Image = mess.getMessage(); byte[] imageBytes = Base64.decodeBase64(base64Image); // 保存为图片文件 LocalDateTime now = LocalDateTime.now(); String timestamp = now.toString().replace("-", "").replace(":", "").replace(".", ""); String randomUUID = UUID.randomUUID().toString().replace("-", ""); String uniqueFileName = timestamp + "_" + randomUUID +".jpg"; // 自定义保存的文件名 String filePath = IMAGE_SAVE_PATH + uniqueFileName; saveImageToFile(imageBytes, filePath); Message reply = new Message(); reply.setToUserIp(toUserIp); reply.setMessage(convertFileToBase64(uniqueFileName)); reply.setImage(true); // 发送消息 onlineUsers.get(toUserIp).session.getBasicRemote().sendText(mapper.writeValueAsString(reply)); }else { String data = mess.getMessage(); String resultMessage = MessageUtils.getMessage(false, userIp, data); onlineUsers.get(toUserIp).session.getBasicRemote().sendText(resultMessage); } } catch (Exception e) { e.printStackTrace(); } } // 保存字节数组为图片文件的方法 private void saveImageToFile(byte[] imageBytes, String fileName) throws IOException { File directory = new File(IMAGE_SAVE_PATH); if (!directory.exists()) { directory.mkdirs(); } String filePath = IMAGE_SAVE_PATH + fileName; try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath))) { bos.write(imageBytes); } } //将图片文件转换成 Base64 字符串 private String convertFileToBase64(String fileName) throws IOException { File file = new File(fileName); if (!file.exists()) { throw new FileNotFoundException("File not found: " + fileName); } try (FileInputStream fileInputStream = new FileInputStream(file)) { byte[] bytes = new byte[(int) file.length()]; fileInputStream.read(bytes); return Base64.encodeBase64String(bytes); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose(@PathParam("userIp") String userIp,Session session) { //从容器中删除指定的用户 onlineUsers.remove(userIp); //获取推送的消息 String message = MessageUtils.getMessage(true, null, getUserIps()); broadcastAllUsers(message); } /** * 发生错误时调用 */ @OnError public void onError(Session session, Throwable throwable) { try { session.close(); } catch (IOException e) { e.printStackTrace(); } throwable.printStackTrace(); } }