SSM模块系列:websocket(消息推送)

1 配置

  • pom.xml
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>4.3.6.RELEASE</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>4.3.6.RELEASE</version>
</dependency>
  • applicationContext.xml
<context:component-scan base-package="com.websocket"/>
  • ssmPureBackend-servlet.xml
<mvc:resources location="/resource/static" mapping="*.html"/>
<mvc:resources location="/resource/static/images" mapping="/resource/static/images/**"/>
<mvc:resources location="/resource/static/js" mapping="*.js"/>
  • web.xml
<async-supported>true</async-supported>

2 资源

2.1 插件

2.2 完整路径

├ssmPureBackend
    ├── src
    │   ├── main
    │   │   ├── java
    │   │   │   └── com
    │   │   │       └── websocket
    │   │   │           ├── MsgSocketHandle.java
    │   │   │           ├── WebSocketConfig.java
    │   │   │           └── WebSocketHandshakeInterceptor.java
    │   │   │       ├── controller
    │   │   │       │   ├── webchat
    │   │   │       │       ├── MsgController.java
    │   │   └── webapp
    │   │       ├── index.jsp
    │   │       ├── resource
    │   │       │   └── static
    │   │       │       └── js
    │   │       │           ├── jquery-3.2.1.js
    │   │       │           ├── jquery-3.2.1.min.js
    │   │       │           ├── jquery-3.4.1.js
    │   │       │           ├── jquery-3.4.1.min.js
    │   │       │           ├── jquery.js
    │   │       │           ├── sockjs.min.js
    │   │       └── WEB-INF
    │   │           ├── jsp
    │   │           │   └── websocket
    │   │           │       ├── chat.jsp
    │   │           │       └── login.jsp

3 源文件

3.1 websocket源文件

3.1.0 MsgSocketHandle.java

/**
 * @Description 
 * @Author Nobody
 * @Date 2019/10/18 14:19
 * @Version 1.0
 **/
package com.websocket;
 
import com.po.People;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
@Component
public class MsgSocketHandle implements WebSocketHandler {
    /**已经连接的用户*/
    private static final List<WebSocketSession> peoples;
    static {
        //保存当前连接用户
        peoples = new ArrayList<>();
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        //将用户信息添加到list中
        peoples.add(webSocketSession);
        System.out.println("=====================建立连接成功==========================");
        People people  = (People) webSocketSession.getAttributes().get("people");
        if(people != null){
            System.out.println("当前连接用户======"+people.getUserName());
        }
        System.out.println("webSocket连接数量====="+peoples.size());
    }
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        People people = (People) webSocketSession.getAttributes().get("people");
        System.out.println("收到用户:"+people.getUserName()+"的消息");
    }
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        if (webSocketSession.isOpen()){
            //关闭session
            try {
                webSocketSession.close();
            } catch (IOException e) {
            }
        }
        //移除用户
        peoples.remove(webSocketSession);
    }
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        peoples.remove(webSocketSession);
        People people = (People) webSocketSession.getAttributes().get("people");
        System.out.println(people.getUserName()+"断开连接");
    }
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
    public void sendMessageToUser(People people, TextMessage messageInfo){
        for (WebSocketSession session : peoples) {
            People sessionUser = (People) session.getAttributes().get("people");
            //根据用户名去判断用户接收消息的用户
            if(people.getUserName().equals(sessionUser.getUserName())){
                try {
                    if (session.isOpen()){
                        session.sendMessage(messageInfo);
                        System.out.println("发送消息给:"+people.getUserName()+"内容:"+messageInfo);
                    }
                    break;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void sendMsgToAllUsers(TextMessage messageInfo) throws Exception{
        for (WebSocketSession user : peoples) {
            user.sendMessage(messageInfo);
        }
    }
}

3.1.2 WebSocketConfig.java

/**
 * @Description 
 * @Author Nobody
 * @Date 2019/10/18 14:19
 * @Version 1.0
 **/
package com.websocket;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
 
/**
 * @Description 
 * @Author Nobody
 * @Date 2019/10/18 14:19
 * @Version 1.0
 **/
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        System.out.println("===========================注册websocket================");
        webSocketHandlerRegistry.addHandler(msgSocketHandle(),"/websocket")
                .addInterceptors(new WebSocketHandshakeInterceptor());
        webSocketHandlerRegistry.addHandler(msgSocketHandle(),
                "/sockjs/websocket").
                addInterceptors(new WebSocketHandshakeInterceptor())
                .withSockJS();
    }
    @Bean(name = "msgSocketHandle")
    public WebSocketHandler msgSocketHandle(){
        return new MsgSocketHandle();
    }
}

3.1.3 WebSocketHandshakeInterceptor.java

/**
 * @Description 
 * @Author Nobody
 * @Date 2019/10/18 14:19
 * @Version 1.0
 **/
package com.websocket;
 
import com.po.People;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
 
import javax.servlet.http.HttpSession;
import java.util.Map;
 
public class WebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        if (request instanceof ServletServerHttpRequest){
            ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletServerHttpRequest.getServletRequest().getSession(false);
            if(session != null){
                //从session中获取当前用户
                People people = (People) session.getAttribute("people");
                map.put("people",people);
            }
        }
        return true;
    }
    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
        super.afterHandshake(serverHttpRequest,serverHttpResponse,webSocketHandler,e);
    }
}

3.2 控制器

  • MsgController.java
/**
 * @Description 
 * @Author Nobody
 * @Date 2019/10/18 14:19
 * @Version 1.0
 **/
package com.controller.webchat;
 
import com.po.People;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.socket.TextMessage;
import javax.servlet.http.HttpServletRequest;

// import com.websocket.fullversion.MsgSocketHandle;
import com.websocket.MsgSocketHandle;
 
@RequestMapping("/websocket")
@Controller
public class MsgController {
    @Autowired
    private MsgSocketHandle msgSocketHandle;
    @RequestMapping("/index")
    public String login(){
        return "websocket/login";
    }

    @RequestMapping("/login")
    public String login(People people, HttpServletRequest request){
        System.out.format("name:"+people.getUserName());
        request.getSession().setAttribute("people",people);
        return "websocket/chat";
    }
    @ResponseBody
    @RequestMapping(value = "/sendMsg",produces = "application/json; charset=utf-8")
    public String sendMsgToUser(String content,String toUserName){
        People people = new People();
        people.setUserName(toUserName);
        TextMessage textMessage = new TextMessage(content);
        msgSocketHandle.sendMessageToUser(people,textMessage);
        return "发送成功";
    }
    @ResponseBody
    @RequestMapping(value = "/sendMsg2",produces = "application/json; charset=utf-8")
    public String sendMsgToAll(String content) throws Exception {
        TextMessage textMessage = new TextMessage(content);
        msgSocketHandle.sendMsgToAllUsers(textMessage);
        return "发送成功";
    }
}

3.3 前端展示

3.3.1 login.jsp

<%--
  该页面用于登录,将用户存于session
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
  <head>
    <title>测试websocket</title>
    <base href="<%=basePath%>">
  </head>
  <body>
  <form:form action="websocket/login">
    <input type="text" name="userName" value="admin"/>
    <input type="text" name="passWord" value="admin"/>
    <input type="submit" value="测试websocket"/>
  </form:form>
  </body>
</html>

3.3.2 chat.jsp

<%--
  该页面用于消息推送
--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
    <title>测试requestbody</title>
</head>
<script type="text/javascript" src="<%=path%>/resource/static/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="<%=path%>/resource/static/js/sockjs.min.js"></script>
<body>
当前登录用户:${pageContext.session.getAttribute("people").userName}<br>
<input type="text" id="text">
<button id="btn1" value="发送给所有人">发送给所有人</button>
<button id="btn2" value="发送给特定用户">发送给特定用户</button>
<div id="msg"></div>

</body>
</html>
<script>
    console.log("path:"+"<%=path%>");
    $(function() {
        var websocket;
        // 首先判断是否 支持 WebSocket
        if('WebSocket' in window) {
            websocket = new WebSocket("ws://localhost:8080/ssmPureBackend/websocket");
        } else if('MozWebSocket' in window) {
            websocket = new MozWebSocket("ws://localhost:8080/ssmPureBackend/websocket");
        } else {
            websocket = new SockJS("http://localhost:8080/ssmPureBackend/sockjs/websocket");
        }
        // 打开时
        websocket.onopen = function(evnt) {
            console.log("  websocket.onopen  ");
        };
        // 处理消息时
        websocket.onmessage = function(evnt) {
            alert("你有一条新消息");
            $("#msg").html(evnt.data);
        };
        websocket.onerror = function(evnt) {
            console.log("  websocket.onerror  ");
        };
        websocket.onclose = function(evnt) {
            console.log("  websocket.onclose  ");
        };
        // 点击了发送消息按钮的响应事件
        $("#btn2").bind("click",function () {
            var url = "${pageContext.request.contextPath}/websocket/sendMsg";
            var content =  $("#text").val();
            var toUserName = "admin"
            $.ajax({
                data: "content=" + content + "&toUserName=" + toUserName,
                type: "get",
                dataType: 'text',
                async: false,
                contentType: "application/x-www-form-urlencoded;charset=UTF-8",
                encoding: "UTF-8",
                url: url,
                success: function (data) {
                    alert(data.toString());
                },
                error: function (msg) {
                    alert(msg);
                },
            });
        })
        $("#btn1").bind("click",function () {
            var url = "${pageContext.request.contextPath}/websocket/sendMsg2";
            var content =  $("#text").val();
            $.ajax({
                data: "content=" + content ,
                type: "get",
                dataType: 'text',
                async: false,
                contentType: "application/x-www-form-urlencoded;charset=UTF-8",
                encoding: "UTF-8",
                url: url,
                success: function (data) {
                    alert(data.toString());
                },
                error: function (msg) {
                    alert(msg);
                },
            });
        })
    });
</script>

4 访问

  • 登录
http://localhost:8080/ssmPureBackend/websocket/index
  • 对话
http://localhost:8080/ssmPureBackend/websocket/login
  • Firefox控制台
    在这里插入图片描述
图 Firefox控制台信息

【参考文献】
[1]https://blog.csdn.net/qq_35615462/article/details/82595071
[2]https://www.jb51.net/article/137433.htm

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值