首先 先说明我的Tomcat版本是8.0的, 7.0无法运行。用的是Maven。
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
这3个是websocket所需要的。
jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML>
<html>
<head>
<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>
<!-- 最新的 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 = new WebSocket("ws://localhost:8080/movies/ws.do");
websocket.onopen = function(evnt) {
$("#tou").html("链接服务器成功!")
};
websocket.onmessage = function(evnt) {
$("#msg").html($("#msg").html() + "<br/>" + evnt.data);
};
websocket.onerror = function(evnt) {
$("#tou").html("发生错误,与服务器断开了链接!")
};
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>
<!-- /input-group -->
</div>
<!-- /.col-lg-6 -->
</div>
<!-- /.row -->
</body>
</html>
注意上面的 var websocket = new WebSocket("ws://localhost:8080/movies/ws.do");
ws://IP地址:端口号/项目名称/配置的方法名称
接着就是要写java类了(3个java类)
首先第一个要写个配置类 ,作用:(配置路径,配置拦截器,配置处理器)。
package cn.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
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;
/**
* Component注解告诉SpringMVC该类是一个SpringIOC容器下管理的类
* 其实@Controller, @Service, @Repository是@Component的细化
*/
@Component
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Autowired
MyWebSocketHander handler;
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
//添加websocket处理器,添加握手拦截器 拦截器先执行 然后到处理器
webSocketHandlerRegistry.addHandler(handler, "/ws.do").addInterceptors(new MyHandShakeInterceptor());
//添加websocket处理器,添加握手拦截器
// webSocketHandlerRegistry.addHandler(handler, "/ws/sockjs").addInterceptors(new MyHandShakeInterceptor()).withSockJS();
}
}
这里的ws.do是配置路径要跟jsp的方法名称一样。MyWebSocketHander是配置处理器类。MyHandShakeInterceptor是配置拦截器类。剩下的两个类就是这两个类。
接下来写MyHandShakeInterceptor拦截器类
package cn.controller;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import cn.domain.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* websocket握手拦截器
* 拦截握手前,握手后的两个切面
*/
@Component
public class MyHandShakeInterceptor implements HandshakeInterceptor {
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse,
WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
if (request instanceof ServletServerHttpRequest) {
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
String phonenumber=(String) servletRequest.getSession().getAttribute("phonenumber");
//这里给map赋值 相当于websockethandler的afterConnectionEstablished方法里的WebSocketSession
map.put("WEBSOCKET_PHONENUMBER", phonenumber);
System.out.println(phonenumber);
}
return true;
}
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
}
这里的phonenumber是我项目登录存入的session,你们可以看你们项目实际需要修改。
最后写MyWebSocketHander处理器类
package cn.controller;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.*;
import java.io.IOException;
import java.util.ArrayList;
@Component
public class MyWebSocketHander implements WebSocketHandler {
private static final Logger logger = Logger.getLogger(MyWebSocketHander.class);
private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();
// 初次链接成功执行
public void afterConnectionEstablished(WebSocketSession websocketsession) throws Exception {
logger.debug("链接成功......");
users.add(websocketsession);
//这里的websocketsession相当于HandShakeInterceptor的map
System.out.println(websocketsession.getAttributes().get("WEBSOCKET_PHONENUMBER"));
}
// 接受消息处理消息
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage)
throws Exception {
sendMessageToUsers(new TextMessage(webSocketMessage.getPayload() + "")); //获取内容。
}
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
if (webSocketSession.isOpen()) {
webSocketSession.close();
}
logger.debug("链接出错,关闭链接......");
users.remove(webSocketSession);
}
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
logger.debug("链接关闭......" + closeStatus.toString());
users.remove(webSocketSession);
}
public boolean supportsPartialMessages() {
return false;
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
for (WebSocketSession user : users) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
*/
public void sendMessageToUser(String userName, TextMessage message) {
for (WebSocketSession user : users) {
if (user.getAttributes().get("WEBSOCKET_PHONENUMBER").equals(userName)) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
}
注意一下 MyHandShakeInterceptor拦截器类的 map.put("WEBSOCKET_PHONENUMBER", phonenumber); 这个存入的数据
可以在MyWebSocketHander处理器类websocketsession.getAttributes().get("WEBSOCKET_PHONENUMBER")提取出来