Spring boot使用websocket实现在线聊天

maven依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.8.26</version>
		</dependency>

Java 类

WebSocket 配置

package com.zpjiang.chat;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    /**
     * 	注入ServerEndpointExporter,
     * 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
    
}

WebSocket 接口入径(ws://localhost:8087/socket/websocket/userId)

package com.zpjiang.chat;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}") // 接口路径  ws://localhost:8087/socket/websocket/userId;
public class WebSocket {

	// 与某个客户端的连接会话,需要通过它来给客户端发送数据
	private Session session;
	/**
	 * 用户ID
	 */
	private String userId;

	// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
	// 虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
	// 注:底下WebSocket是当前类名
	private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();
	// 用来存在线连接用户信息
	private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();

	/**
	 * 链接成功调用的方法
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam(value = "userId") String userId) {
		try {
			this.session = session;
			this.userId = userId;
			webSockets.add(this);
			sessionPool.put(userId, session);
			log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());
		} catch (Exception e) {
		}
	}

	/**
	 * 链接关闭调用的方法
	 */
	@OnClose
	public void onClose() {
		try {
			webSockets.remove(this);
			sessionPool.remove(this.userId);
			log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
		} catch (Exception e) {
		}
	}

	/**
	 * 收到客户端消息后调用的方法
	 *
	 * @param message
	 * @param session
	 */
	@OnMessage
	public void onMessage(String message) {
		log.info("【websocket消息】收到客户端消息:" + message);
		Message msg = JSONUtil.toBean(message, Message.class);
		sendOneMessage(msg.getToUID(), message);
	}

	/**
	 * 发送错误时的处理
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {

		log.error("用户错误,原因:" + error.getMessage());
		error.printStackTrace();
	}

	// 此为广播消息
	public void sendAllMessage(String message) {
		log.info("【websocket消息】广播消息:" + message);
		for (WebSocket webSocket : webSockets) {
			try {
				if (webSocket.session.isOpen()) {
					webSocket.session.getAsyncRemote().sendText(message);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	// 此为单点消息
	public void sendOneMessage(String userId, String message) {
		Session session = sessionPool.get(userId);
		if (session != null && session.isOpen()) {
			try {
				log.info("【websocket消息】 单点消息:" + message);
				session.getAsyncRemote().sendText(message);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	// 此为单点消息(多人)
	public void sendMoreMessage(String[] userIds, String message) {
		for (String userId : userIds) {
			Session session = sessionPool.get(userId);
			if (session != null && session.isOpen()) {
				try {
					log.info("【websocket消息】 单点消息:" + message);
					session.getAsyncRemote().sendText(message);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

	}

}

controller

package com.zpjiang.chat;

import javax.annotation.Resource;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

@RestController
public class WebsocketController {
	
	@Resource
	private WebSocket webSocket;
	
	@GetMapping("/page")
    public ModelAndView page() {
        return new ModelAndView("webSocket");
    }
	
	@RequestMapping("/push/{toUID}/{msg}")
    public ResponseEntity<String> pushToClient(@PathVariable("msg")String message, @PathVariable("toUID") String toUID) throws Exception {
		webSocket.sendOneMessage(toUID, message);
        return ResponseEntity.ok("Send Success!");
    }
}

消息bean

package com.zpjiang.chat;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

@Data
@Getter
@Setter
public class Message {

	private String toUID;
	private String Msg;
}

main方法类

package com.zpjiang.chat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class ChatApplication {

	 public static void main(String[] args) {
	        SpringApplication.run(ChatApplication.class, args);
	    }
}

配置文件

server:
  port: 8087
  servlet:
    context-path: /socket

spring:
  application:
    name: websocket

视图文件 /src/main/resources/templates/webSocket.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebSocket消息通知</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
	var socket;

	//打开WebSocket
	function openSocket() {
		if (typeof (WebSocket) === "undefined") {
			console.log("您的浏览器不支持WebSocket");
		} else {
			console.log("您的浏览器支持WebSocket");
			//实现化WebSocket对象,指定要连接的服务器地址与端口,建立连接.
			//ws://localhost:8087/socket/websocket/userId
			var socketUrl = "http://localhost:8087/socket/websocket/"
					+ $("#uid").val();
			//将https与http协议替换为ws协议
			socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
			console.log(socketUrl);
			if (socket != null) {
				socket.close();
				socket = null;
			}
			socket = new WebSocket(socketUrl);
			//打开事件
			socket.onopen = function() {
				console.log("WebSocket已打开");
				//socket.send("这是来自客户端的消息" + location.href + new Date());
			};
			//获得消息事件
			socket.onmessage = function(msg) {
				console.log(msg.data);
				//发现消息进入,开始处理前端触发逻辑
			};
			//关闭事件
			socket.onclose = function() {
				console.log("WebSocket已关闭");
			};
			//发生了错误事件
			socket.onerror = function() {
				console.log("WebSocket发生了错误");
			}
		}
	}

	var socket1;
	//打开WebSocket
	function openSocket1() {
		if (typeof (WebSocket) === "undefined") {
			console.log("您的浏览器不支持WebSocket");
		} else {
			console.log("您的浏览器支持WebSocket");
			//实现化WebSocket对象,指定要连接的服务器地址与端口,建立连接.
			//ws://localhost:8087/socket/websocket/userId
			var socketUrl = "http://localhost:8087/socket/websocket/"
					+ $("#toUID").val();
			//将https与http协议替换为ws协议
			socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
			console.log(socketUrl);
			if (socket1 != null) {
				socket1.close();
				socket1 = null;
			}
			socket1 = new WebSocket(socketUrl);
			//打开事件
			socket1.onopen = function() {
				console.log("WebSocket已打开");
				//socket.send("这是来自客户端的消息" + location.href + new Date());
			};
			//获得消息事件
			socket1.onmessage = function(msg) {
				console.log("socket1收到消息:");
				console.log(msg.data);
				//发现消息进入,开始处理前端触发逻辑
			};
			//关闭事件
			socket1.onclose = function() {
				console.log("WebSocket已关闭");
			};
			//发生了错误事件
			socket1.onerror = function() {
				console.log("WebSocket发生了错误");
			}
		}
	}

	//发送消息
	function sendMessage() {
		if (typeof (WebSocket) === "undefined") {
			console.log("您的浏览器不支持WebSocket");
		} else {
			console.log("您的浏览器支持WebSocket");
			console.log('{"toUID":"' + $("#toUID").val() + '","Msg":"'
					+ $("#msg").val() + '"}');
			socket.send('{"toUID":"' + $("#toUID").val() + '","Msg":"'
					+ $("#msg").val() + '"}');
		}
	}
	function sendMessage1() {
		if (typeof (WebSocket) === "undefined") {
			console.log("您的浏览器不支持WebSocket");
		} else {
			console.log("您的浏览器支持WebSocket");
			console.log('{"toUID":"' + $("#uid").val() + '","Msg":"'
					+ $("#msg").val() + '"}');
			socket1.send('{"toUID":"' + $("#uid").val() + '","Msg":"'
					+ $("#msg").val() + '"}');
		}
	}
</script>
<body>
	<p>【uid】:
	<div>
		<input id="uid" name="uid" type="text" value="1">
	</div>
	<p>【toUID】:
	<div>
		<input id="toUID" name="toUID" type="text" value="2">
	</div>
	<p>【Msg】:
	<div>
		<input id="msg" name="msg" type="text" value="hello WebSocket2">
	</div>
	<p>【第一步操作:】:
	<div>
		<button onclick="openSocket()">开启socket</button>
		<button onclick="openSocket1()">开启socket2</button>
	</div>
	<p>【第二步操作:】:
	<div>
		<button onclick="sendMessage()">发送消息</button>
		<button onclick="sendMessage1()">发送消息2</button>
	</div>
</body>

</html>

  • 11
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
A:要实现基于Spring BootWebSocket聊天功能,可以按以下步骤进行。 1. 集成WebSocket依赖。在Spring Boot项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建WebSocket配置类。在Spring Boot项目中,创建一个WebSocket配置类,用于配置WebSocket相关的参数和处理器等。具体代码如下: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new ChatWebSocketHandler(), "/chat").setAllowedOrigins("*"); } } ``` 上面的代码创建了一个名为“/chat”的WebSocket处理器,同时允许所有来源的连接。 3. 创建WebSocket处理器。在Spring Boot项目中,创建一个WebSocket处理器,用于处理WebSocket连接和消息等。具体代码如下: ```java public class ChatWebSocketHandler extends TextWebSocketHandler { private List<WebSocketSession> sessions = new ArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(message); } } } ``` 上面的代码创建了一个名为ChatWebSocketHandler的WebSocket处理器,它可以接收和发送文本消息。handleTextMessage方法对于接收到的消息进行处理,然后将它发送给所有连接的客户端。 4. 创建聊天页面。在Web应用程序中,创建一个聊天页面,允许用户在页面上输入和发送消息。具体代码如下: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>聊天室</title> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> </head> <body> <input id="username" type="text" placeholder="请输入用户名"><br> <textarea id="message" placeholder="请输入消息"></textarea><br> <button id="sendBtn">发送</button> <script> var ws; $("#sendBtn").click(function () { if (!ws) { alert("WebSocket未连接"); return; } var username = $("#username").val(); var message = $("#message").val(); if (!username) { alert("请输入用户名"); return; } if (!message) { alert("请输入消息"); return; } var data = { username: username, message: message }; ws.send(JSON.stringify(data)); $("#message").val(""); }); $(function () { ws = new WebSocket("ws://" + location.host + "/chat"); ws.onopen = function () { console.log("WebSocket已连接"); }; ws.onclose = function () { console.log("WebSocket已关闭"); ws = null; }; ws.onmessage = function (event) { console.log(event.data); }; }); </script> </body> </html> ``` 上面的HTML代码创建了一个简单的聊天页面,包含一个用户名输入框、一个消息输入框和一个发送按钮。通过WebSocket连接服务器并发送消息。 5. 测试聊天功能。启动Spring Boot应用程序,然后使用多个浏览器窗口或标签页打开聊天页面,在页面上输入和发送消息,验证聊天功能是否正常工作。 至此,完成了Spring BootWebSocket实现聊天功能的整个过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张知文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值