首先 先說明我的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" target="_blank" rel="external nofollow" >
<!-- 可選的Bootstrap主題檔案(一般不用引入) -->
<link rel="stylesheet"
href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css" target="_blank" rel="external nofollow" >
<!-- 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")提取出來