赞
踩
目录
1.使用内置的AbstractWebSocketHandler
以 Spring Boot 2.1.0.RELEASE为例
该类是一个抽象类,包含于 org.springframework:spring-websocket 包中
这里引入:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-websocket</artifactId>
- <version>2.1.0.RELEASE</version>
- </dependency>
即可使用
使用时需要继承该类,根据需要重写相应方法即可
例如:
- import org.springframework.web.socket.CloseStatus;
- import org.springframework.web.socket.TextMessage;
- import org.springframework.web.socket.WebSocketMessage;
- import org.springframework.web.socket.WebSocketSession;
- import org.springframework.web.socket.handler.AbstractWebSocketHandler;
-
- public class MyWebSocketHandler extends AbstractWebSocketHandler {
- @Override
- public void afterConnectionEstablished(WebSocketSession session) throws Exception {
- System.out.println("Connection established");
- }
-
- @Override
- public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
- System.out.println("收到消息:"+message);
- Thread.sleep(2000L);
- session.sendMessage(new TextMessage("Hello World!"));
- }
-
- @Override
- public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
- System.out.println("Connection closed");
- }
- }

如果是Spring MVC可以在XML中配置端点映射(例如映射到/hello):
- <websocket:handlers>
- <websocket:mapping path="/hello" handler="socketHandler"/>
- </websocket:handlers>
- <bean class="MyWebSocketHandler" id="socketHandler"/>
也可以继承 AbstractWebSocketMessageBrokerConfigurer 并重写相应方法配置端点(还需要进行注入)
- @Override
- public void registerStompEndpoints(StompEndpointRegistry registry) {
- registry.addEndpoint("/hello").withSockJS();
- }
然后就可以和网页通信了
引入依赖:
- <dependency>
- <groupId>javax.websocket</groupId>
- <artifactId>javax.websocket-api</artifactId>
- <version>1.1</version>
- <scope>provided</scope>
- </dependency>
这里使用注解实现:
- import Users;
- import org.springframework.stereotype.Component;
- import javax.websocket.OnMessage;
- import javax.websocket.OnOpen;
- import javax.websocket.Session;
- import javax.websocket.server.PathParam;
- import javax.websocket.server.ServerEndpoint;
- import java.io.IOException;
-
- @ServerEndpoint(value = "/chatroom/{userName}")
- @Component
- public class WebsocketServer {
- private Session session;
- private static int count=0;
-
- @OnOpen
- public void onOpen(Session session, @PathParam("userName")String userName) throws IOException {
- this.session=session;
- //Users用来存放数据,user是该类的一个静态HashMap变量
- if(Users.user.get(userName)==null) {
- Users.user.put(userName, this);
- count++;
- }
- session.getBasicRemote().sendText("系统消息:当前在线人数:"+count);
- }
-
- @OnMessage
- public void onMessage(String msg) throws IOException {
- for(WebsocketServer server:Users.user.values()){
- server.session.getBasicRemote().sendText(msg);
- }
- }
- }

还需要注入ServerEndpointExporter:
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
- @Configuration
- public class WebSocketConfig {
- @Bean
- public ServerEndpointExporter confServerEndpointExporter(){
- return new ServerEndpointExporter();
- }
- }
这里有一个大坑,网上的很多案例里面,@ServerEndpoint标记的类,都没有使用@Component,我在测试的时候,总是报404错误,无法连接,加上该注解后问题解决
如果是编程式实现,只要继承 javax.websocket.Endpoint 类并实现/重写相关方法,剩下的和注解式相同
写了两个简单页面,就不用Controller进行映射了,直接把页面放到 resource/static 下
index.html:
- <html>
- <head>
- <meta charset="UTF-8">
- <title>登录</title>
- </head>
- <body>
- <form action="chat.html" method="get">
- 你的名字:<input type="text" name="userName"/>
- <input type="submit" value="提交"/>
- </form>
- </body>
- </html>
chat.html:
- <html>
- <head>
- <meta charset="UTF-8">
- <title>聊天</title>
- <script type="text/javascript" src="webjars/jquery/2.1.4/jquery.min.js"></script>
- <script type="application/javascript">
- var url=null;
- var sock=null;
- var userName=getQueryString("userName")
- //百度来的函数,用来截取参数
- function getQueryString(name) {
- var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
- var r = window.location.search.substr(1).match(reg);
- if (r != null) return unescape(r[2]); return null;
- }
- $(function(){
- if(!window.WebSocket){
- alert('你的浏览器不支持WebSocket');
- }else{
- url='ws://localhost:8080/chatroom/'+userName
- sock=new WebSocket(url)
- sock.onopen=function () {
- $("#content").append("<h1>欢迎"+userName+"来到聊天室</h1>");
- }
- sock.onmessage=function (e) {
- $("#content").append("<p>"+e.data+"</p>")
- }
- sock.onclose=function () {
- window.close();
- }
- }
- });
- function sendMessage() {
- var date=new Date()
- sock.send(userName+" "+date.toLocaleTimeString()+" 说<br/>"+$('.msg').val())
- $('.msg').val("")
- }
- </script>
- </head>
- <body>
- <div id="content"></div>
- <input type="text" class="msg"/><br/>
- <input type="button" value="发送" onclick="sendMessage()"/><br/>
- <input type="button" value="关闭websocket" onclick="sock.close()"/>
- </body>
- </html>

这样就能实现一个公共聊天室了:
如果想实现私聊也很简单,稍作修改就可以,我写了个简单实现:
修改后的chat.html:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>聊天</title>
- <script type="text/javascript" src="webjars/jquery/2.1.4/jquery.min.js"></script>
- <script type="application/javascript">
- var url=null;
- var sock=null;
- var userName=getQueryString("userName")
- function getQueryString(name) {
- var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
- var r = window.location.search.substr(1).match(reg);
- if (r != null) return unescape(r[2]); return null;
- }
- $(function(){
- if(!window.WebSocket){
- alert('你的浏览器不支持WebSocket');
- }else{
- url='ws://localhost:8080/chatroom/'+userName
- sock=new WebSocket(url)
- sock.onopen=function () {
- $("#content").append("<p>欢迎"+userName+"来到聊天室</p>");
- }
- sock.onmessage=function (e) {
- $("#content").append("<p>"+e.data+"</p>")
- }
- sock.onclose=function () {
- window.close();
- }
- }
- });
- function sendMessage() {
- var date=new Date()
- sock.send(userName+" "+date.toLocaleTimeString()+" 说<br/>"+$('.msg').val())
- $('.msg').val("")
- }
- function sendPrivateMessage() {
- var date=new Date()
- sock.send("<font color='red'>"+userName+date.toLocaleTimeString()+"对"+$('.privatechat').val()+"悄悄说<br/>"+$('.msg').val()+"</font>")
- $('.msg').val("")
- }
- </script>
- </head>
- <body>
-
- <div id="content"></div>
- <input type="text" class="msg"/><br/>
- <input type="button" value="发送" onclick="sendMessage()"/><br/>
- <input type="button" value="关闭websocket" onclick="sock.close()"/>
- 对他私聊:<input type="text" class="privatechat"/><br/>
- <input type="button" value="发送私聊" onclick="sendPrivateMessage()"/><br/>
- </body>
- </html>

主要就是增加了一个私密发送的方法
WebSocketServer类的onMessage方法略作修改即可:
- @OnMessage
- public void onMessage(String msg) throws IOException {
- if(msg.startsWith("<font")){
- String user2=msg.substring(msg.indexOf("对")+1,msg.indexOf("悄悄"));
- WebsocketServer server2=Users.user.get(user2);
- if(server2!=null){
- server2.session.getBasicRemote().sendText(msg);
- }
- session.getBasicRemote().sendText(msg);
- }else {
- for (WebsocketServer server : Users.user.values()) {
- server.session.getBasicRemote().sendText(msg);
- }
- }
- }
效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。