Spring4.0 + 实现简单的聊天

  最近因为要在项目中加入在线聊天功能,所以想到了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.xsd
	http://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
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer{

	@Override
	public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值