1. 程式人生 > >SSM框架下使用websocket實現後端傳送訊息至前端

SSM框架下使用websocket實現後端傳送訊息至前端

本篇文章本人是根據實際專案需求進行書寫的第一版,裡面有些內容對大家或許沒有用,但是核心程式碼本人已對其做了紅色標註。文章講解我將從maven座標、HTML頁面、js檔案及後端程式碼一起書寫。

一、maven座標

<!-- WebSocket配置開始-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>${spring.version}</version>
</dependency>
<!-- WebSocket配置結束-->

二、HTML頁面

<!--訊息框開始&ndash;-->
 <!-- 彈窗&ndash;&gt-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link rel="stylesheet" type="text/css" href="${basePath}/static/css/home/index.css">
    <script src="${basePath}/static/js/common/jquery-1.8.3.min.js"
></script> <script src="${basePath}/static/js/home/index.js"></script> <script src="${basePath}/static/css/layui/layui.js"></script> <title>後臺管理系統</title> </head> <body> <input type="hidden" value="${userId}" id="userId"> <input type
="hidden" value="${cnName}" id="cnName"> <div class="tanchuang"> <div class="tanchuangClose"><span class="tanchuangCloseBtn">關閉</span></div> <h6>訊息提示:</h6> <div id="messages"></div> </div> <!--訊息框結束&ndash;--> <script src="${basePath}/static/js/home/index.js"></script> <script src="/static/js/webSocket.js"></script> </body> </html>

 

三、js檔案(websocket.js)

var websocket;
// var host = document.location.host;
var userId = $("#userId").val(); // 獲得當前登入人員的userName
var cnName=$("#cnName").val();
// alert(username)
//判斷當前瀏覽器是否支援WebSocket
if ('WebSocket' in window) {
    // alert("瀏覽器支援Websocket")
    if(websocket ==null){
//以下用的是ip路徑,那麼在本地啟動專案時也需要使用ip地址進行訪問 websocket
= new WebSocket("ws://192.168.200.102:8080/webSocket/"+userId+"/"+cnName); } } else { alert('當前瀏覽器 Not support websocket') } //連線發生錯誤的回撥方法 websocket.onerror = function() { // setMessageInnerHTML("WebSocket連線發生錯誤"); }; //連線成功建立的回撥方法 websocket.onopen = function() { // alert("WebSocket連線成功") // setMessageInnerHTML("WebSocket連線成功"); } //接收到訊息的回撥方法 websocket.onmessage = function(event) { // alert("接收到訊息的回撥方法") $('.tanchuang').css('display','block') // alert("這是後臺推送的訊息:"+event.data); $("#messages").append(event.data + '<br/>') ; // websocket.close(); // alert("webSocket已關閉!") } //連線關閉的回撥方法 websocket.onclose = function() { // setMessageInnerHTML("WebSocket連線關閉"); } //監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連線,防止連線還沒斷開就關閉視窗,server端會拋異常。 /*window.onbeforeunload = function() { closeWebSocket(); }*/ //關閉WebSocket連線 function closeWebSocket() { websocket.close(); } //將訊息顯示在網頁上 function setMessageInnerHTML(innerHTML) { document.getElementById('messages').innerHTML += innerHTML + '<br/>'; }

 

四、websocket連線控制器

package com.yjlc.platform.utils.webSocket;

import com.alibaba.fastjson.JSON;
import com.yjlc.platform.User;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * --------------------------------------------------------------
 * CopyRights(c)2018,YJLC
 * All Rights Reserved
 * <p>
 * FileName: WebSockets.java
 * Description:(該處未使用配置類)使用配置類後才可以在該類中進行service的註解注入
 * Author: cyb
 * CreateDate: 2018-11-28
 * --------------------------------------------------------------
 */
@ServerEndpoint("/webSocket/{userId}/{cnName}")
public class WebSockets {
    private static int onlineCount = 0;
    public static Map<User, WebSockets> clients = new ConcurrentHashMap<User, WebSockets>();
    private Session session;
    private Long userId;//使用者id
    private String cnName;//使用者真實名稱
    private User user;//使用者實體
    public static List<User> list = new ArrayList<>();   //線上列表,記錄使用者名稱稱

    /**
     *@description: 連線websocket
     *@author:cyb
     *@date: 2018-12-03 19:12
    *@param: userId 使用者id
    *@param: cnName 使用者真實名稱
    *@param: session
     *@return: void
     */
    @OnOpen
    public void onOpen(@PathParam("userId") Long userId,@PathParam("cnName") String cnName, Session session) throws IOException {
        this.userId = userId;
        this.session = session;
        this.cnName=cnName;
        System.out.println("cnName:"+cnName+"userId"+userId);
        user= new User();
        user.setUserId(userId);
        user.setCnName(cnName);
        list.add(user);
        addOnlineCount();//新增線上人數
        clients.put(user, this);
       /* String message = getMessage("["+cnName+"]進入聊天室,當前線上人數為"+getOnlineCount()+"位", "notice",  list);
        broadcast(message);//呼叫廣播
        System.out.println("已連線");*/
    }
    /**
     * 廣播訊息
     * @param message
     */
    public void broadcast(String message){
        for (WebSockets item : clients.values()) {
            String cnName = item.cnName;
            //
            String msg = message.replace("{userName}",cnName);
            item.session.getAsyncRemote().sendText(msg);
        }
    }
    /**
     * 組裝返回給前臺的訊息
     * @param message   互動資訊
     * @param type      資訊型別
     * @param list      線上列表
     * @return
     */
    public String getMessage(String message, String type, List list){
        com.alibaba.fastjson.JSONObject member = new com.alibaba.fastjson.JSONObject();
        member.put("message", message);
        member.put("type", type);
        member.put("list", list);
        return member.toString();
    }
    /**
     * 對特定使用者傳送訊息
     * @param message
     * @param session
     */
    public void singleSend(String message, Session session){
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     *@description: 關閉連線
     *@author:cyb
     *@date: 2018-12-03 14:33
    *@param:
     *@return: void
     */
    @OnClose
    public void onClose() throws IOException {
        System.out.println("關閉當前使用者連線:"+user.getCnName());
        clients.remove(user);
        list.remove(user);        //從線上列表移除這個使用者
        subOnlineCount();
    }
    /**
     *@description:前臺傳送過來的訊息
     *@author:cyb
     *@date: 2018-12-03 14:33
    *@param: _message
     *@return: void
     */
    @OnMessage
    public void onMessage(String _message) throws IOException {
        com.alibaba.fastjson.JSONObject chat = JSON.parseObject(_message);
        com.alibaba.fastjson.JSONObject message = JSON.parseObject(chat.get("message").toString());
        if(message.get("to") == null || message.get("to").equals("")){
            //如果to為空,則廣播;如果不為空,則對指定的使用者傳送訊息
            broadcast(_message);
        }else{
            String [] userlist = message.get("to").toString().split(",");
            sendMessageTo(_message,message.get("from").toString());
//            singleSend(_message, (Session) routetab.get(message.get("from"))); //傳送給自己
        }
    }
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
    /**
     *@description:訊息傳送給指定人員
     *@author:cyb
     *@date: 2018-12-03 14:35
    *@param: message
    *@param: To
     *@return: void
     */
    public void sendMessageTo(String message, String To) throws IOException {
        for (WebSockets item : clients.values()) {
            if (item.userId.equals(To) )
                item.session.getAsyncRemote().sendText(message);
        }
    }
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
        WebSockets.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
        WebSockets.onlineCount--;
    }
    public static synchronized Map<User, WebSockets> getClients() {
        return clients;
    }
}

 

五、websocket輔助類

package com.yjlc.platform.utils.webSocket;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

/**
 * --------------------------------------------------------------
 * CopyRights(c)2018,YJLC
 * All Rights Reserved
 * <p>
 * FileName: HttpSessionConfigurator.java
 * Description:配置類  將http中的session傳入websocket中
 * Author: cyb
 * CreateDate: 2018-11-26
 * --------------------------------------------------------------
 */
public class HttpSessionConfigurator extends ServerEndpointConfig.Configurator {

    @Override
    public void modifyHandshake(ServerEndpointConfig sec,
                                HandshakeRequest request, HandshakeResponse response) {
        // 獲取當前Http連線的session
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        // 將http session資訊注入websocket session
        sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
    }
}

 

六、後端程式碼

/**
     *@description:傳送資訊
     *@author:cyb
     *@date: 2018-11-19 10:03
    *@param: id
     *@return: java.util.Map<java.lang.String,java.lang.Object>
     */
    @RequestMapping("sndmsg")
    @ResponseBody
    public Map<String,Object> sndmsg(Long id){
        Map<String,Object> map = new HashMap<>();
        AdminUser user=(AdminUser) SecurityUtils.getSubject().getSession().getAttribute("users");
       try{
//           int k=0;
           int k=   service.sndmsg(id,user);
           if(k==200){
               map.put("code",200);
               return map;
           }else {
               map.put("code",0);
               return map;
           }
       }catch (Exception e){
           e.printStackTrace();
           map.put("code",500);
           return map;
       }
    }

七、service層實現類

//該類下標紅的未重點,其餘的程式碼大家可以跳過
public
int sndmsg(Long id,AdminUser adminUser) { //獲取該條資訊模板 SettingTemplateDTO templateDTO = templateDao.getSystemTemplateInfo(id); List<NotificationSendLog> logList = new ArrayList<>(); String content = templateDTO.getContent();//模板內容 Boolean result = false; int w=0;//操作結果 int count =0;//傳送總條數 int sucNum=0;//傳送成功條數 //查詢所有使用者列表 List<SecurityUser> userList =templateDao.getUserList(); if(templateDTO.getSendMode().equals("1")){//簡訊傳送 }else if(templateDTO.getSendMode().equals("3")){//站內傳送(桌面訊息提示) if(templateDTO.getSendPeople().equals("1")){//個人使用者 }else if(templateDTO.getSendPeople().equals("2")){//企業使用者 WebSockets webSocket = new WebSockets(); List<User> onLineList =WebSockets.list;//獲取線上人人員id List<SecurityUser> userList1 = templateDao.getUserList(); List<NotificationUserLog> userLogList = new ArrayList<>(); for(SecurityUser list:userList1){ NotificationUserLog userLog = new NotificationUserLog(); //呼叫裝配發送日誌實體 NotificationSendLog sendLog =setSendLog(templateDTO,adminUser,list); userLog.setUserId(list.getId()); userLog.setMsgId(templateDTO.getId()); userLog.setMsgStatus(false); for(int i =0;i<onLineList.size();i++){ Long userId =onLineList.get(i).getUserId(); if(list.getId()==userId){ userLog.setMsgStatus(true); sendLog.setStatus(true);//傳送成功 sucNum+=1; count+=1; } } userLogList.add(userLog); count= onLineList.size(); sucNum =onLineList.size(); logList.add(sendLog); } //插入傳送系統通知與使用者的關聯關係 int ww = templateDao.insertUserSendLog(userLogList); webSocket.broadcast(templateDTO.getContent());//呼叫廣播() //插入系統日誌 String category="系統訊息"; //呼叫生成傳送日誌方法 NotificationLog notificationLog =assembleLog(adminUser,category,count,sucNum,templateDTO); int h = settingDao.insertLog(notificationLog); //插入傳送日誌 w =templateDao.insertSendLog(logList); } } //修改傳送狀態 templateDTO.setSendStatus(true); int z = templateDao.updateSystemTemplate(templateDTO); if(w>0){ return 200; } return 0;

注意點:專案在瀏覽器中訪問時,切記路徑要和websocket.js中的一致 

以上內容僅供參考,如果以上內容有所不當或者不清楚的可以聯絡本人。技術在於溝通!