消息推送之Websocket

来源:互联网 发布:腾鹰软件 编辑:程序博客网 时间:2024/05/29 02:25

WebSocket是html5新增加的特性之一,可以实现客户端和服务器彼此之间相互通信,也可以实现跨域通信,目前大部分主流浏览器都支持,iE浏览器需要10版本以上。


需求:公司项目有一个报警模块,当后台接收到报警消息之后,需要及时的推送到浏览器上,显示给用户。


一:导入WebSocket的maven依赖:


                <dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.0</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>4.1.4.RELEASE</version></dependency>



二:建立WebSocket入口

创建一个类实现WebSocketConfigurer接口并继承WebMvcConfigurerAdapter,这个方法中可以配置websocket入口,指定允许访问的域、handler、和拦截器.


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.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import org.springframework.web.socket.handler.TextWebSocketHandler;@Configuration@EnableWebMvc@EnableWebSocketpublic class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {//注册websocket通道,指定handler和拦截器        registry.addHandler(webSocketHandler(),"/websocket/socketServer").addInterceptors(new SpringWebSocketHandlerInterceptor());        registry.addHandler(webSocketHandler(), "/sockjs/socketServer").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();}   @Bean   public TextWebSocketHandler webSocketHandler(){                //核心处理handler类       return new SpringWebSocketHandler();   }}


三:编写拦截器

import java.util.Map;import javax.servlet.http.HttpSession;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;public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor{@Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,            Map<String, Object> attributes) throws Exception {        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("WEBSOCKET_USERNAME",userName);            }        */        }        return true;            }        public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,            Exception ex) {        super.afterHandshake(request, response, wsHandler, ex);    }}


四:编写handler


import java.io.IOException;import java.util.ArrayList;import org.apache.log4j.Logger;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.TextWebSocketHandler;public class SpringWebSocketHandler extends TextWebSocketHandler{    private static final ArrayList<WebSocketSession> users;    private static Logger logger = Logger.getLogger(SpringWebSocketHandler.class);        static {        users = new ArrayList<WebSocketSession>();    }        /**     * 连接成功时候,会触发页面上onopen方法     */    public void afterConnectionEstablished(WebSocketSession session) throws Exception {        users.add(session);        //这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户        TextMessage returnMessage = new TextMessage("推送测试");        // session.sendMessage(returnMessage);        //sendMessageToUsers(new TextMessage("hahhaa"));     }        /**     * 关闭连接时触发     */    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {        logger.debug("websocket connection closed......");        String username= (String) session.getAttributes().get("WEBSOCKET_USERNAME");        System.out.println("用户"+username+"已退出!");        users.remove(session);        System.out.println("剩余在线用户"+users.size());    }    /**     * js调用websocket.send时候,会调用该方法     */    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {        super.handleTextMessage(session, message);    }    /**     * 发生错误时触发     */    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {    if(session.isOpen()){        session.close();        }        logger.debug("websocket connection closed......");        users.remove(session);    }    public boolean supportsPartialMessages() {        return false;    }        /**     * 使用这个方法像客户端某个在线用户发送消息     *     * @param userName     * @param message     */    public void sendMessageToUser(String userName, TextMessage message) {        for (WebSocketSession user : users) {            if (user.getAttributes().get("WEBSOCKET_USERNAME").equals(userName)) {                try {                    if (user.isOpen()) {                        user.sendMessage(message);                    }                } catch (IOException e) {                    e.printStackTrace();                }                break;            }        }    }        /**     * 使用这个方法像客户端所有在线用户发送消息     *     * @param message     */    public void sendMessageToUsers(TextMessage message) {        for (WebSocketSession user : users) {            try {                if (user.isOpen()) {                    user.sendMessage(message);                }            } catch (IOException e) {                e.printStackTrace();            }        }    }}



五:客户端代码


<!--导入js文件--><script type="text/javascript"src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js"></script><script type="text/javascript">function wsPath() {var pathName = window.document.location.pathname;var host = window.location.host;var projectName = pathName.substring(0,pathName.substr(1).indexOf('/') + 1);return (host + projectName);}wsPath = wsPath();var websocket = null;if ('WebSocket' in window) {websocket = new WebSocket("ws://" + wsPath + "/websocket/socketServer");} else if ('MozWebSocket' in window) {websocket = new MozWebSocket("ws://" + wsPath+ "/项目名称/websocket/socketServer");} else {websocket = new SockJS("http://" + wsPath+ "/项目名称/sockjs/socketServer");}websocket.onmessage = onMessage;websocket.onope = onOpen;websocket.onerror = onError;websocket.onclose = onClose;function onOpen() {}function onMessage(evt) {//这里evt就是推送给过来的消息}function onError() {websocket.close();}function onClose() {}window.close = function() {websocket.onclose();}</script>


六:测试


import org.springframework.context.annotation.Bean;import org.springframework.web.socket.TextMessage;public class Test {@Bean// 这个注解会从Spring容器拿出Beanpublic static SpringWebSocketHandler infoHandler() {return new SpringWebSocketHandler();}public static void main(String[] args) {infoHandler().sendMessageToUsers(new TextMessage("哈哈,测试小哥"));}}

结束!!!!!

原创粉丝点击