天天看点

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中的一致 

SSM框架下使用websocket实现后端发送消息至前端
SSM框架下使用websocket实现后端发送消息至前端

以上内容仅供参考,如果以上内容有所不当或者不清楚的可以联系本人。技术在于沟通!

转载于:https://www.cnblogs.com/chenyuanbo/p/10060505.html