SpringMVC+WebSocket

1 根据我的另一篇博客创建一个web框架的maven工程

https://blog.csdn.net/u014377655/article/details/81332959

 

2 在工程中添加文件

结构如下图

 

3 配置spring-mvc.xml

 

4 jsp以及类内容

index.jsp

<!DOCTYPE html>

<html>

<body>

<h2>Hello World!</h2>

<body>

    <form action="websocket/login.do">

        username:<input type="text" name="userName"/>

        <input type="submit" value="login"/>

    </form>

</body>

</body>

</html>

ws.jsp

<!DOCTYPE html>

<html>

<head>

    <title>WebSocket测试页</title>



    <script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>

    <script type="text/javascript" src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js"></script>

    <script type="text/javascript">

        var websocket = null;

        if ('WebSocket' in window) {

            var host = window.location.host;

            var url = "ws://"+host+"/chat/websocket/socketServer.do";

            websocket = new WebSocket(url);

        }

        else if ('MozWebSocket' in window) {

            websocket = new MozWebSocket("ws://localhost:8080/chat/websocket/socketServer.do");

        }

        else {

            websocket = new SockJS("http://localhost:8080/chat/sockjs/socketServer.do");

        }

        websocket.onopen = onOpen;

        websocket.onmessage = onMessage;

        websocket.onerror = onError;

        websocket.onclose = onClose;



        function onOpen(openEvt) {

            alert("connection status: success");

        }



        function onMessage(evt) {

            //收到服务器消息,使用evt.data提取

            evt.stopPropagation()

            evt.preventDefault()

            writeToScreen(evt.data);

        }

        function onError() {

            //产生异常

            writeToScreen(evt.message)

        }

        function onClose() {

            alert("connection status: closed");

        }

        function closeWebSocket() {

            websocket.close();

        }

        //浏览器刷新前关闭websocket

        function fnUnloadHandler() {

            websocket.onclose();

        }

        function doSend() {

            if (websocket.readyState == websocket.OPEN) {

                var msg = document.getElementById("inputMsg").value;

                //后台将调用handleTextMessage方法接收该消息

                websocket.send(msg);

                alert("send success!");

            } else {

                alert("send failed!\nconnection is closed!");
            }
        }

        function writeToScreen(message) {

            var pre = document.createElement("p");

            pre.style.wordWrap = "break-word";

            pre.innerHTML += message;

            document.body.appendChild(pre);
        }



    </script>

</head>


<body onbeforeunload="fnUnloadHandler();">

<div>

    Input:<textarea rows="3" cols="30" id="inputMsg" name="inputMsg"></textarea>

    <button onclick="doSend();">send</button>

    <button onclick="closeWebSocket();">close</button>

</div>

</body>

</html>

 

SpringWebSocketConfig

public class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements

        WebSocketConfigurer {

    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

        registry.addHandler(webSocketHandler(),"/websocket/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor());

        registry.addHandler(webSocketHandler(), "/sockjs/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();

    }

    @Bean

    public TextWebSocketHandler webSocketHandler(){

        return new SpringWebSocketHandler();
    }
}

SpringWebSocketHandler

public class SpringWebSocketHandler extends TextWebSocketHandler {



    //在线用户列表

    private static final Map<String, WebSocketSession> users;

    static {
        users = new HashMap<>();
    }
    public SpringWebSocketHandler() { }


    /**

     * 建立连接后触发的回调

     * 记录用户的连接标识,便于后面发信息,

     * 这里我是记录将id记录在Map集合中。

     * 一个Map中不能包含相同的key,每个key只能映射一个value,根据先后put的顺序覆盖

     * @param session

     * @throws Exception

     */

    @Override

    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        System.out.println("成功建立连接");

        String userName = getClientId(session);
        if (userName != null) {
            System.out.println("用户"+userName+"登录!");
            users.put(userName, session);
            session.sendMessage(new TextMessage("server:成功建立socket连接"));
            System.out.println("当前在线用户"+users.size()+": "+users);

        }

        //userName为空时,不存储该用户,不与该用户交互

    }
    /**

     * 断开连接后触发的回调

     * 连接已关闭,移除在Map集合中的记录。

     * @param session

     * @param closeStatus

     * @throws Exception

     */

    @Override

    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

        String userName = getClientId(session);

        System.out.println("\n用户"+userName+"已退出: " + closeStatus);

        users.remove(userName);

        System.out.println("剩余在线用户"+users.size()+": "+users);

    }

    /**

     * 收到消息时触发的回调

     * 对H5 Websocket的send方法进行处理

     * @param session

     * @param message

     */

    @Override

    public void handleTextMessage(WebSocketSession session, TextMessage message) {

        //显示客户端发送过来的消息内容

        System.out.println("client:"+message.getPayload());
        WebSocketMessage message1 = new TextMessage("server:"+message);

        try {
            session.sendMessage(message1);
        } catch (IOException e) {

            e.printStackTrace();
        }
    }


    /**

     * 传输消息出错时触发的回调

     * 连接出错处理,主要是关闭出错会话的连接,和删除在Map集合中的记录

     * @param session

     * @param exception

     * @throws Exception

     */

    @Override

    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

        if (session.isOpen()) {

            session.close();

        }
        System.out.println("连接出错");
        users.remove(getClientId(session));

    }

    /**

     * 是否处理分片消息

     * @return

     */

    public boolean supportsPartialMessages() {
        return false;
    }


    /**

     * 发送信息给指定用户

     * 传入用户标识和消息体

     * @param clientId

     * @param message

     * @return

     */

    public boolean sendMessageToUser(String clientId, TextMessage message) {

        if (users.get(clientId) == null) return false;

        WebSocketSession session = users.get(clientId);

        System.out.println("sendMessage:" + session);

        if (!session.isOpen()) return false;

        try {

            session.sendMessage(message);

        } catch (IOException e) {

            e.printStackTrace();

            return false;

        }

        return true;

    }


    /**

     * 广播信息

     * 只需要传入消息体

     * @param message

     * @return

     */

    public boolean sendMessageToAllUsers(TextMessage message) {

        boolean allSendSuccess = true;

        Set<String> clientIds = users.keySet();

        WebSocketSession session = null;

        for (String clientId : clientIds) {

            try {

                session = users.get(clientId);

                if (session.isOpen()) {

                    session.sendMessage(message);

                }

            } catch (IOException e) {

                e.printStackTrace();

                allSendSuccess = false;

            }

        }
        return  allSendSuccess;
    }



    /**

     * 获取用户标识

     * @param session

     * @return

     */

    private String getClientId(WebSocketSession session) {

        try {

            String clientId = (String)session.getAttributes().get(Const.CLIENT_NAME);

            return clientId;

        } catch (Exception e) {

            return null;
        }

    }

}

SpringWebSocketHandlerInterceptor

public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
   @Override

    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,

                                   WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception 

        System.out.println("Before Handshake");

        if (request instanceof ServletServerHttpRequest) {

            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;

            HttpSession session = servletRequest.getServletRequest().getSession(false);

            if (session != null) {

                //使用userName区分WebSocketHandler,以便定向发送消息

                String userName = (String) session.getAttribute("userName");

                if (userName==null) {

                    userName="default-system";

                }

                attributes.put("userName",userName);

            }else{

                System.out.println("beforeHandshake 没有获取到 session");

            }

        }

        return super.beforeHandshake(request, response, wsHandler, attributes);

    }

    @Override

    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,

                               WebSocketHandler wsHandler, Exception ex) {

        System.out.println("After Handshake");

        super.afterHandshake(request, response, wsHandler, ex);
    }
}
 

controller

@Controller

public class WebsocketController {
@Bean

public SpringWebSocketHandler infoHandler() {

    return new SpringWebSocketHandler();

}

@RequestMapping("/websocket/login")

public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {

    String userName = request.getParameter("userName");

    System.out.println(userName+"登录");



    HttpSession session = request.getSession(false);

    session.setAttribute(Const.CLIENT_NAME, userName);

    ModelAndView mv = new ModelAndView();
    mv.setViewName("ws");

    return mv;

}}

5 测试

输入用户名,点击login

跳转至

 

发送消息测试

参考博文

spring配置websocket并实现群发/单独发送消息

https://blog.csdn.net/u014520745/article/details/62046396

Spring WebSocket实现消息推送

https://www.cnblogs.com/3dianpomian/p/5902084.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

waf13916

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值