Springboot集成WebSocket通信全部代码,即扣即用。

websocket通信主要来自两个类以及一个测试的html页面。
MyHandler 和 WebSocketH5Config,下面全部代码
MyHandler类全部代码:
package com.union.common.config;
 
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
 
 
@Service
public class MyHandler implements WebSocketHandler {
	
    //在线用户列表
    private static final Map<String, WebSocketSession> webSocketUsers;

    static {
        webSocketUsers = new HashMap<>();
    }
    //新增socket
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    	 String ID = session.getUri().toString().split("uid=")[1];
         if (ID != null) {
             webSocketUsers.put(ID, session);
             session.sendMessage(new TextMessage("成功建立socket连接"));

         }
    }
 
    //接收socket信息
    @Override
	public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
    	try{
	    	JSONObject jsonobject = JSONObject.parseObject((String) webSocketMessage.getPayload());
            String message = (String) jsonobject.get("message");
            if (message == null) {
                message = "服务器收到了,hello!";
            }
            sendMessageToUser(jsonobject.get("id")+"",message);
    	 }catch(Exception e){
      	   e.printStackTrace();
         }
	}
 
    /**
     * 发送信息给指定用户
     * @param clientId
     * @param message
     * @return
     */
    public boolean sendMessageToUser(String clientId, String message) {
        if(webSocketUsers.get(clientId) == null){
            return false;
        }
        WebSocketSession session = webSocketUsers.get(clientId);
        if(!session.isOpen()) {
            return false;
        }
        try {
            session.sendMessage(new TextMessage(message));
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
 
    /**
     * 广播信息
     * @param message
     * @return
     */
    public boolean sendMessageToAllUsers(String message) {
        boolean allSendSuccess = true;
        Set<String> clientIds = webSocketUsers.keySet();
        WebSocketSession session = null;
        for (String clientId : clientIds) {
            try {
                session = webSocketUsers.get(clientId);
                if (session.isOpen()) {
                    session.sendMessage(new TextMessage(message));
                }
            } catch (IOException e) {
                e.printStackTrace();
                allSendSuccess = false;
            }
        }
 
        return  allSendSuccess;
    }

    /**
     * 关闭连接
     * @param clientId
     * @return
     */
    public void afterConnectionClosed(String clientId) {
        try {
            if(webSocketUsers.get(clientId) != null){
                WebSocketSession session = webSocketUsers.get(clientId);
                afterConnectionClosed(session,CloseStatus.NORMAL);
            }
            webSocketUsers.remove(clientId);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
 
 
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        String uid = session.getUri().toString().split("uid=")[1];
        webSocketUsers.remove(uid);
        if (session.isOpen()) {
            session.close();
        }
    }
 
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String uid = session.getUri().toString().split("uid=")[1];
        webSocketUsers.remove(uid);
        session.close(status);
    }
 
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}

  

WebSocketH5Config 类全部代码:

package com.union.common.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;


//实现接口来配置Websocket请求的路径和拦截器。
@Configuration
@EnableWebSocket
public class WebSocketH5Config implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        //handler是webSocket的核心,配置入口
        registry.addHandler(new MyHandler(), "/myHandler/{uid}").setAllowedOrigins("*");
    }
}

  

 

测试用的html页面:

 

<!DOCTYPE html>
<html>
<head>
    <title>socket.html</title>
    <meta name="content-type" content="text/html" charset="UTF-8">
</head>
<body>

Welcome<br/>
登录的uid:<input id="uid" type="text"/><br/>
<button onclick="connectWebSocket()">connectWebSocket</button><br/>
发送出去的信息:<input id="text" type="text"/><br/>
发送送给谁的uid:<input id="sendToUid" type="text"/><br/>
<button onclick="send()">Send</button><br/>
收到的信息:<input id="getMessage" type="text"/><br/>
<button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>
<script type="text/javascript">
    var websocket = null;
    //强制关闭浏览器  调用websocket.close(),进行正常关闭
    window.onunload = function () {
        //关闭连接
        closeWebSocket();
    }

    //建立WebSocket连接
    function connectWebSocket() {
        var userID = document.getElementById("uid");
        console.log(userID);
        console.log("开始...");

        //建立webSocket连接
        websocket = new WebSocket("ws://localhost:8080/myHandler/uid=" + userID.value);

        //打开webSokcet连接时,回调该函数
        websocket.onopen = function () {
            console.log("onpen");
        }

        //关闭webSocket连接时,回调该函数
        websocket.onclose = function () {
            //关闭连接
            console.log("onclose");
        }

        //接收信息
        websocket.onmessage = function (msg) {
            var getMessage = document.getElementById("getMessage");
            getMessage.value = msg.data;
            console.log(msg.data);
        }
    }

    //发送消息
    function send() {
        var sendToUid = document.getElementById("sendToUid");
        var messageText = document.getElementById("text");
        var postValue = {};
        postValue.id = sendToUid.value;
        postValue.message = messageText.value;
        websocket.send(JSON.stringify(postValue));
    }

    //关闭连接
    function closeWebSocket() {
        if (websocket != null) {
            websocket.close();
        }
    }

</script>
</html>

  

 

 

 

因为websocket使用的是ws协议。所以我在nginx上做了一个请求转发,这样服务器就可以使用:

 

在nginx.conf文件里面的http部分加入如下代码。

map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

  

在server{}部分加了如下代码。放在最前面,就可以在ws部分使用域名访问了:

ws和wss就像http和https一样的

wss://api.****.com/union-front/myHandler/uid=

 

  location ~* /union-front/myHandler {
        proxy_pass http://127.0.0.1:8080;
        proxy_redirect    off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Origin "";
        }

  

 当使用websocket的时候,再使用定时任务,则会报错,在Application启动类上加上如下代码即可解决这个问题

@Bean
    public TaskScheduler taskScheduler() {
        //使用 websockt注解的时候,使用@EnableScheduling注解启动的时候一直报错,增加这个bean 则报错解决。
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        return taskScheduler;
    }

  

posted @ 2019-04-30 14:32  忘尘丶  阅读(994)  评论(0编辑  收藏  举报