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

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

  • 相关阅读:
    less css用法思维导图
    javascript模块化编程规范
    行高:line-height图文解析
    CSS细节
    Emmet
    常见的浏览器兼容问题
    一条在没有水的环境下坚持了四年生存下来的鱼
    纪念:一高那些年
    水墨青花
    float浮动
  • 原文地址:https://www.cnblogs.com/chenyuanbo/p/10060505.html
Copyright © 2020-2023  润新知