WebSocket实现前后端消息推送

来源:互联网 发布:极客湾淘宝店 编辑:程序博客网 时间:2024/05/18 20:09

环境

jdk8 tomcat7 谷歌浏览器和火狐浏览器(浏览器得支持websocket)
本文用webSocket建立一个简单的聊天室,直接上代码。。。
websocket 用到jar包:

<dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-websocket</artifactId>          <version>${spring-framework.version}</version>      </dependency>      <dependency>          <groupId>org.springframework</groupId>          <artifactId>spring-messaging</artifactId>          <version>${spring-framework.version}</version>      </dependency> 

先准备一个普通的maven工程 springMVC框架

后台代码:

主要是建立拦截器拦截webSocket请求并交于handler进行处理。
webSocket配置如下:
1.MySocketConfig:注册拦截器+handler

import org.springframework.beans.factory.annotation.Autowired;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 com.zzm.test.websocket.socket.WebSocketInterceptor;@Configuration@EnableWebMvc@EnableWebSocketpublic class MySocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{    @Autowired    private MySocketHandle mySocketHandle;//自己的handler    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        //注册处理拦截器,拦截url为socketServer的请求        registry.addHandler(mySocketHandle, "/socketChatroom.do").addInterceptors(new WebSocketInterceptor());//拦截的请求,(注意首先得被servlet拦截到,即要注意web-inf0中的配置)    }}

拦截器:拦截请求将httpSession用户保存到WebSocketSession里,用于区别webSocketSession是哪个用户的

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.HandshakeInterceptor;public class MySocketInterceptor implements HandshakeInterceptor{    /**     * 握手后报存用户信息到webSocketSession     */    @Override    public boolean beforeHandshake(ServerHttpRequest request,            ServerHttpResponse response, WebSocketHandler wsHandler,            Map<String, Object> attributes) throws Exception {        if(request instanceof ServerHttpRequest){              ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;              HttpSession session = servletRequest.getServletRequest().getSession();              if(session!=null){                  attributes.put("user", session.getAttribute("user"));              }            }        return true;    }    @Override    public void afterHandshake(ServerHttpRequest request,            ServerHttpResponse response, WebSocketHandler wsHandler,            Exception exception) {    }}

handler处理类:定义各连接状态的处理,保存连接上的用户,及自定义发送方法

import java.util.Map;import java.util.Map.Entry;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.WebSocketMessage;import org.springframework.web.socket.WebSocketSession;@Servicepublic class MySocketHandle implements WebSocketHandler{    private Logger logger = LoggerFactory.getLogger(MySocketHandle.class);    private Map<String,WebSocketSession> users = new ConcurrentHashMap<String,WebSocketSession>();    @Override    public void afterConnectionEstablished(WebSocketSession session)            throws Exception {        logger.info("建立socket连接");        String userName = session.getAttributes().get("user").toString();        if(null!=userName&&!"".equals(userName)){            users.put(userName, session);            session.sendMessage(new TextMessage("system:"+userName+"连接成功。。。"));        }    }    @Override    public void handleMessage(WebSocketSession session,            WebSocketMessage<?> message) throws Exception {    }    @Override    public void handleTransportError(WebSocketSession session,            Throwable exception) throws Exception {        if(session.isOpen()){            session.close();        }        logger.error("连接出现错误",exception);        users.remove(session.getAttributes().get("user").toString());    }    @Override    public void afterConnectionClosed(WebSocketSession session,            CloseStatus closeStatus) throws Exception {        logger.info("连接关闭");        users.remove(session.getAttributes().get("user").toString());    }    @Override    public boolean supportsPartialMessages() {        return false;    }    public void sendMessageToUsers(String sender,TextMessage message){        Set<Map.Entry<String, WebSocketSession>> entrySet = users.entrySet();        for(Map.Entry<String, WebSocketSession> entry : entrySet){            String userName = "";            try{            userName = entry.getKey();            if(userName==null||userName.equals(sender)){                continue;            }            WebSocketSession session = entry.getValue();            session.sendMessage(message);            }catch(Exception e){                logger.error("发送信息给"+userName+"失败",e);            }        }    }    public void sendMessageToUser(String userName,TextMessage message){        try{            WebSocketSession session = users.get(userName);            session.sendMessage(message);        }catch(Exception e){            logger.error("发送消息给"+userName+"失败",e);        }    }}

controller类:

import javax.servlet.http.HttpSession;import org.slf4j.Logger;import org.slf4j.LoggerFactory;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 com.zzm.test.websocket.controller.SocketController;import com.zzm.test.websocket.service.MySocketHandle;@Controller@RequestMapping("socketPushController")public class SocketPushController {     private static final Logger logger = LoggerFactory.getLogger(SocketController.class);      @Autowired      private MySocketHandle mySocketHandler;      @RequestMapping("login")      public String login(HttpSession session,String name){        logger.info(name+"登录了");        session.setAttribute("user", name);        return "../socketPush/chatroom";      }      @RequestMapping("sendMessage")      @ResponseBody      public String sendMessage(HttpSession session,String message){          String name = (String) session.getAttribute("user");          mySocketHandler.sendMessageToUsers( name,new TextMessage(name+" : "+message));          return "success";      }}

前端页面:

登录:用户用姓名登录

<%@ 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 + "/";%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>登录</title><script type="text/javascript"></script></head><body>    <form action="http://localhost:8080/AllStudy/socketPushController/login.do" method="post">        <span>姓名:</span><input type="text" name="name"><br/>        <input type="submit" value="登录">    </form></body></html>

发送页面:可以发送和接收信息。

<%@ 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 + "/";%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script type="text/javascript" src="../js/jquery-1.7.2.min.js"></script><script type="text/javascript"></script><script type="text/javascript">$(function(){    //建立socket连接    var sock;    if ('WebSocket' in window) {//判断当前浏览器是否支持webSocket        sock = new WebSocket("ws://localhost:8080/AllStudy/socketChatroom.do");//建立连接    }    sock.onopen = function (e) {//成功建立连接        console.log(e);    };    sock.onmessage = function (e) {//接收到消息        console.log(e)        $("#messages").append("<p><font color='red'>"+e.data+"</font>")    };    sock.onerror = function (e) {//连接发生错误        console.log(e);    };    sock.onclose = function (e) {//连接关闭        console.log(e);    };    ////监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。    window.onbeforeunload = function(){          websocket.close();      };});function mysend(){    var message = $("#message").val();    $("#messages").append("<p><font color='blue'>"+"我:"+message+"</font>");    $.post('http://localhost:8080/AllStudy/socketPushController/sendMessage.do',{message:message},function(){        $("message").val("");    },'text');}</script></head><body>    <div id="messages">    </div>    <div><input type="text" id="message" ><button onclick="mysend()">发送</button></div></body></html>

结果图:
这里写图片描述

这里写图片描述

这里写图片描述