Spring4.0 + 实现简单的聊天

来源:互联网 发布:淘宝直播刷人软件下载 编辑:程序博客网 时间:2024/05/18 03:18

  最近因为要在项目中加入在线聊天功能,所以想到了spring 自带的WebSocket,之前有听说,但是一直没有研究过,去网上一搜感觉乱七八糟,梳理了一整天,终于作出了一个简单的Demo。

1、环境

Spring MVC + Tomcate (本人使用 MyEclipse2014 开发)
Spring 版本使用4.0 以上 其他没有任何要求

2、配置

web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:websocket="http://www.springframework.org/schema/websocket"  这xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd" id="WebApp_ID" version="3.1"><display-name>spring_demo</display-name><welcome-file-list><welcome-file>index.html</welcome-file></welcome-file-list><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext*.xml</param-value></context-param><servlet><servlet-name>spring</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>detectAllHandlerExceptionResolvers</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup><async-supported>true</async-supported></servlet><servlet-mapping><servlet-name>spring</servlet-name><url-pattern>/</url-pattern></servlet-mapping><servlet-mapping><servlet-name>default</servlet-name><url-pattern>*.css</url-pattern></servlet-mapping><servlet-mapping><servlet-name>default</servlet-name><url-pattern>*.xls</url-pattern></servlet-mapping><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><filter><filter-name>HiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>HiddenHttpMethodFilter</filter-name><servlet-name>spring</servlet-name></filter-mapping><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

标红色的是需要加上去的,其他的都是一些web的基本配置,不做介绍。


3、Spring 对于webSocket的处理

1、WebSocket 配置

配置WebSocketConfig,相当于注册一个服务(下面代为是 创建一个请求路径为“/echo” 的服务)。
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;/** * WebSocket 配置 * @author yanbumo */@Configuration@EnableWebMvc@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer{@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {//registry.addHandler(new WebSocketHander(),"/echo").addInterceptors(new HandshakeInterceptor()); //支持websocket 的访问链接        //registry.addHandler(new WebSocketHander(),"/sockjs/echo").addInterceptors(new HandshakeInterceptor()).withSockJS(); //SockJS的访问链接registry.addHandler(new WebSocketHander(),"/echo").addInterceptors(new HandshakeInterceptor());}}

这里 涉及到两个类  WebSocketHander  和  HandshakeInterceptor 是下面要实现的连个类,一个用来连接Socket连接,一个用来处理消息。至于"/echo" 这个路径是 前端用来请求websocket 连接的路径,

<strong style="background-color: rgb(255, 255, 255);">websocket = new WebSocket("ws://127.0.0.1:8080/echo");</strong>

2、WebSocketHander 处理消息

import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.Set;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.TextWebSocketHandler;public class WebSocketHander extends TextWebSocketHandler{/** * 存放所有连接的用户 */    private static final Map<String,WebSocketSession> users = new HashMap<String, WebSocketSession>();    /**     * 初次链接成功执行     */    @Override    public void afterConnectionEstablished(WebSocketSession session) throws Exception {    System.out.println(session.getId() + " 上线");    sendMessageToUsers(new TextMessage(session.getId() + " 上线"));        users.put(session.getId(), session);    }    /**     * 接受消息处理消息     */    @Override    public void handleMessage(WebSocketSession from, WebSocketMessage<?> message) throws Exception {        String fromMsg = message.getPayload().toString();    if(fromMsg.contains(" To ")){    String targetId = fromMsg.split(" To ")[1].trim();    String msg = fromMsg.split(" To ")[0];    WebSocketSession target = users.get(targetId);    target.sendMessage(new TextMessage("来自" + from.getId() + ":" + msg.split(" To ")[0]));    from.sendMessage(new TextMessage("我:" + msg));    }else{    sendMessageToUsers(new TextMessage("来自" + from.getId() + ":" + fromMsg));    }    }    /**     * 错误处理     */    @Override    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {        if(webSocketSession.isOpen()){            webSocketSession.close();        }        users.remove(webSocketSession);    }    /**     * 关闭连接     */    @Override    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {    System.out.println(session.getId() + " 下线");    sendMessageToUsers(new TextMessage(session.getId() + " 下线"));        users.remove(session);    }    /**     * 支持文件传输     */    @Override    public boolean supportsPartialMessages() {        return false;    }       /**     * 给所有用户推送     */    public void sendMessageToUsers(TextMessage message) throws IOException {Set<String> ids = users.keySet();for (String id : ids) {WebSocketSession user = users.get(id);user.sendMessage(message);}    }        /**     * 给目标发送消息     */    public void setMsg(WebSocketSession session,String msg) throws IOException{    session.sendMessage(new TextMessage(msg));    }}

代码注释  比较详细,服务在接到请求后,交给Handle 处理。

3、HandshakeInterceptor 拦截器

import java.util.Map;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.web.socket.WebSocketHandler;/** * @author yanbumo */public class HandshakeInterceptor implements org.springframework.web.socket.server.HandshakeInterceptor {    //进入hander之前的拦截    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse,     WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {        return true;    }    @Override    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse,     WebSocketHandler webSocketHandler, Exception e) {    }}

拦截器创建后,服务端的处理基本上就完成了。下面是前端的处理。

4、前台页面

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <!-- <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script> -->    <!-- 新 Bootstrap 核心 CSS 文件 -->    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">    <!-- 可选的Bootstrap主题文件(一般不用引入) -->    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">    <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->    <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>    <!--<script type="text/javascript" src="js/jquery-1.7.2.js"></script>-->    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->    <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>    <title>webSocket测试</title>    <script type="text/javascript">        $(function(){            var websocket;            /* if ('WebSocket' in window) {                alert("WebSocket");                websocket = new WebSocket("ws://127.0.0.1:8080/echo");            } else if ('MozWebSocket' in window) {                alert("MozWebSocket");                websocket = new MozWebSocket("ws://echo");            } else {                alert("SockJS");                            } */            //websocket = new SockJS("http://127.0.0.1:8080/sockjs/echo");            websocket = new WebSocket("ws://127.0.0.1:8080/echo");            websocket.onopen = function (evnt) {                $("#tou").html("链接服务器成功!")            };            websocket.onmessage = function (evnt) {                $("#msg").html($("#msg").html() + "<br/>" + evnt.data);            };            websocket.onerror = function (evnt) {            };            websocket.onclose = function (evnt) {                $("#tou").html("与服务器断开了链接!")            }            $('#send').bind('click', function() {                send();            });            function send(){                if (websocket != null) {                    var message = document.getElementById('message').value;                    websocket.send(message);                } else {                    alert('未与服务器链接.');                }            }        });    </script></head><body><div class="page-header" id="tou">    webSocket及时聊天Demo程序</div><div class="well" id="msg"></div><div class="col-lg">    <div class="input-group">        <input type="text" class="form-control" placeholder="发送信息..." id="message">      <span class="input-group-btn">        <button class="btn btn-default" type="button" id="send" >发送</button>      </span>    </div></div></body></html>

WebSocket 对象的应用:分别是:创建,连接,关闭,接受消息,发送消息,出错处理

var websocket = new WebSocket("ws://127.0.0.1:8080/echo");websocket.onopen = function (evnt) { $("#tou").html("链接服务器成功!") };websocket.onmessage = function (evnt) { //接受消息处理 };websocket.onerror = function (evnt) { //出错处理 };websocket.onclose = function (evnt) { //关闭连接 }websocket.send(message); //发送消息





直接访问页面,就可以了。

4、结果演示




作者这里使用的是谷歌浏览器,没有在其他版本浏览器上测试。





0 0
原创粉丝点击