SpringMVC+WebSocket+H5 Notification实例

来源:互联网 发布:大数据概念股一览 编辑:程序博客网 时间:2024/06/03 16:47

传统的HTTP协议是被动的,单项的即服务器传递信息给客户端,每次发送信息都需要封装HTTP协议中的Headers等相关信息。实时性消息较高的应用场景瓶颈非常明显如聊天室,无法主动获取客户端发送的信息,每次传输数据都需要发送一个完整的HTTP请求,数据传输效率低。
WebSocket其实就是一套新的协议,可以实现Socket编程效果,初次连接的时候初始化一次,只要连接不关闭便可以实现客户端和服务器的实时数据传递。
WebSocket协议是基于HTTP即浏览器的一套新的编程接口,客户端与服务器的连接通过JavaScript编程,页面关闭后连接便失效了,刷新页面会先关闭当前的连接再建立新的连接。

开发工具:
SpringMVC4.0+(spring-websocket包,支持WebSocket编程)
Tomcat 7.0+ (支持WebSocket协议)

实例使用的是SpringMVC4.15+Tomcat7.0.76+JDK1.8

核心代码:
WebSocketInterceptor 拦截器,每次连接时触发。
WebSocketConfig 配置文件,WebSocket实例化。
SocketHandler 业务逻辑处理。

public class WebSocketInterceptor implements HandshakeInterceptor {    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {        ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;这里写代码片        String[] str = serverHttpRequest.getServletRequest().getParameterMap().get("id");        map.put("id", str[0]);        return true;    }    @Override    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {    }}ide    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {        ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;        String[] str = serverHttpRequest.getServletRequest().getParameterMap().get("id");        map.put("id", str[0]);        return true;    }    @Override    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {    }}@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        registry.addHandler(myHandler(), "/socketHandler").addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*");    }    //@Bean    public WebSocketHandler myHandler() {        return new SocketHandler();    }}@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        registry.addHandler(myHandler(), "/socketHandler").addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*");    }    //@Bean    public WebSocketHandler myHandler() {        return new SocketHandler();    }}@Servicepublic class SocketHandler extends TextWebSocketHandler {    //在线用户列表(适用于单用户多点)    private static final Map<Integer, List<WebSocketSession>> users;    static {        users = new HashMap<>();    }    @Override    public void afterConnectionEstablished(WebSocketSession session) throws Exception {        System.out.println("成功建立连接");        Integer userId = getClientId(session);        List<WebSocketSession> list = users.get(userId);        if (null == list){            list = new ArrayList<>();            list.add(session);            users.put(userId, list);        }         else            list.add(session);    }    /***     * 接收客户端信息     */    @Override    public void handleTextMessage(WebSocketSession session, TextMessage message) {        System.out.println(message.getPayload());    }    /**     * 发送信息给指定用户     * @param userloginid 用户标识     * @param message     * @return     */    public void sendMessageToUser(Integer userloginid, TextMessage message) {        if (users.get(userloginid) == null)             return;        List<WebSocketSession> list = users.get(userloginid);        for(int i=0;i<list.size();i++){            WebSocketSession session = list.get(i);            if (!session.isOpen())                 continue;            try {                session.sendMessage(message);            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 广播信息     * @param userloginid 用户标识     * @param message     * @return     */    public void sendMessageToAllUser(Integer userloginid,TextMessage message) {        Set<Integer> clientIds = users.keySet();        for (Integer clientId : clientIds) {            if(clientId != userloginid)                sendMessageToUser(clientId,message);        }    }    /**     * 广播信息     * @param message     * @return     */    public void sendMessageToAllUsers(TextMessage message) {        Set<Integer> clientIds = users.keySet();        for (Integer clientId : clientIds) {            sendMessageToUser(clientId,message);        }    }    /***     * 关闭连接     * @param id     * @param session     */    public void remove(int id,WebSocketSession session){        if (users.get(id) == null)             return;        List<WebSocketSession> list = users.get(id);        Optional<WebSocketSession> optional = list.stream().filter(m->m.equals(session)).findFirst();        if(optional.isPresent())            list.remove(optional.get());        if(null == list || list.size()==0)            users.remove(id);    }    /***     * 出错是执行,关闭浏览器界面会执行该方法,并自动关闭session     */    @Override    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {        if (session.isOpen()) {            session.close();        }        remove(getClientId(session),session);    }    /***     * 关闭session时执行     */    @Override    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {        if (session.isOpen()) {            session.close();        }        remove(getClientId(session),session);    }    @Override    public boolean supportsPartialMessages() {        return false;    }    /**     * 获取用户标识     * @param session     * @return     */    private Integer getClientId(WebSocketSession session) {        return Integer.parseInt(session.getAttributes().get("id").toString());    }}

HTML代码:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page isELIgnored="false"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>     <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">    <title>WebSocket</title> </head> <body>     <button>socket连接</button>       <script src="${pageContext.request.contextPath}/js/jquery-2.1.1.js"></script>    <script type="text/javascript">      $(function() {        $("button").click(function(){            if (typeof WebSocket == 'undefined')                 alert("浏览器不支持相关特性,请更换为谷歌,UC浏览器。")              else{                //WebSocket客户端建立,生命周期为当前页面。                var ws = new WebSocket("ws://localhost:8123/websocket/socketHandler?id=4")                ws.onopen = function () {                    console.log("onpen");                    ws.send("客户端发送消息");                }                //页面关闭便会触发                ws.onclose = function () {                    console.log("onclose");                }                ws.onmessage = function (msg) {                    console.log(msg.data);                    var message = msg.data.split(",");                    //浏览器支持Notification,并允许接收通知                    if($.notificationHandler.requestPermission())                    $.notificationHandler.showNotification('${pageContext.request.contextPath}/images/11.png',message[0],message[1]);                }               }        });      })    </script></body></html>

本实例中运用到了H5的Notification发送通知,相关代码已封装到JS文件里了,便不多叙述了。

下载地址:http://download.csdn.net/download/lishengko/9998130

原创粉丝点击