此demo在google浏览器下测试通过
- 首先websocket 的支持要分两部分
- 框架的支持 针对 spring框架
- 代码的支持 含有3部分代码
- nginx的配置文件也需要改造
pom.xml调整
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
package com.dozenx.web.module.websocket;
import java.io.IOException;
import java.util.ArrayList;
import com.dozenx.web.core.Constants;
import com.dozenx.web.core.auth.session.SessionUser;
import org.apache.log4j.Logger;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class ChatMessageHandler extends TextWebSocketHandler {
private static final ArrayList<WebSocketSession> users;// 这个会出现性能问题,最好用Map来存储,key用userid
private static Logger logger = Logger.getLogger(ChatMessageHandler.class);
static {
users = new ArrayList<WebSocketSession>();
}
/**
* 连接成功时候,会触发UI上onopen方法
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("connect to the websocket success......");
users.add(session);
// 这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户
// TextMessage returnMessage = new TextMessage("你将收到的离线");
// session.sendMessage(returnMessage);
}
/**
* 在UI在用js调用websocket.send()时候,会调用该方法
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
SessionUser from = (SessionUser)(session.getAttributes().get(Constants.SESSION_USER));
String to ="大家";
;
sendMessageToUsers(new TextMessage(from.getUserName()+"对 "+to+" 说:"+new String (message.asBytes())));
//super.handleTextMessage(session, message);
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
*/
public void sendMessageToUser(/*WebSocketSession session ,*/String userName, TextMessage message) {
for (WebSocketSession user : users) {
if (user.getAttributes().get(Constants.SESSION_USER).equals(userName)) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
for (WebSocketSession user : users) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
logger.debug("websocket connection closed......");
users.remove(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("websocket connection closed......");
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
package com.dozenx.web.module.websocket;
import org.springframework.context.annotation.Bean;
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 org.springframework.web.socket.handler.TextWebSocketHandler;
/**
* @Author: dozen.zhang
* @Description:
* @Date: Created in 9:47 2018/10/30
* @Modified By:
*/
@EnableWebMvc
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatMessageHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor());
registry.addHandler(chatMessageHandler2(),"/webSocketServer2").addInterceptors(new WebSocketHandshakeInterceptor());
registry.addHandler(chatMessageHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()).withSockJS();
}
@Bean
public TextWebSocketHandler chatMessageHandler(){
return new ChatMessageHandler();
}
@Bean
public TextWebSocketHandler chatMessageHandler2(){
return new ChatMessageHandler2();
}
}
package com.dozenx.web.module.websocket;
import com.dozenx.util.StringUtil;
import com.dozenx.web.core.Constants;
import com.dozenx.web.core.auth.session.SessionUser;
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.support.HttpSessionHandshakeInterceptor;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @Author: dozen.zhang
* @Description:
* @Date: Created in 9:48 2018/10/30
* @Modified By:
*/
public class WebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("Before Handshake");
String userName ="";
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest)request;
HttpSession session = servletRequest.getServletRequest().getSession(true);
if (session !=null) { //使用userName区分WebSocketHandler,以便定向发送消息
SessionUser sessionUser =
(SessionUser) session.getAttribute(Constants.SESSION_USER);//这部分可以自己改造 用你自己的session对象 直接是一个用户名字符串也可以的 ^_^
if(sessionUser == null) {
return false;
}
attributes.put(Constants.SESSION_USER, sessionUser);//标识用户已经登录
}else{
return false;
}
}
//使用userName区分WebSocketHandler,以便定向发送消息(使用shiro获取session,或是使用上面的方式)
// String userName = (String) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER);
// if (userName == null) {
// userName = "default-system";
// }
attributes.put(Constants.SESSION_USER, StringUtil.getRandomString(5));
boolean flag = super.beforeHandshake(request, response, wsHandler, attributes);
return flag;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("After Handshake");
super.afterHandshake(request, response, wsHandler, ex);
}
}
<!DOCTYPE html>
<html>
<head>
<title>Web Socket Client</title>
</head>
<body style="padding:10px;">
<h1>Web Socket Chating Room</h1>
<div style="margin:5px 0px;">
Address:
<div><input id="address" type="text" value="/home/webSocketServer" style="width:400px;"/></div>
</div>
<div style="margin:5px 0px;">
Name:
<div><input id="name" type="text" value="Byron" style="width:400px;"/></div>
</div>
<div>
<button id="connect" onclick="connect();">connect server</button>
<button id="disconnect" onclick="quit();">disconnect</button>
<button id="clear" onclick="clearMsg();">clear</button>
<button id="team" onclick="team();">配对</button>
</div>
<h5 style="margin:4px 0px;">Message:</h5>
<div id="message" style="border:solid 1px #333; padding:4px; width:400px; overflow:auto;
background-color:#404040; height:300px; margin-bottom:8px; font-size:14px;">
</div>
<input id="text" type="text" onkeypress="enter(event);" style="width:340px"/>
<button id="send" onclick="send();">send</button>
<script type="text/javascript">
var name=document.getElementById('name').value;
var msgContainer=document.getElementById('message');
var text=document.getElementById('text');
var ws;
function connect () {
var address="ws://" + document.location.host+document.getElementById('address').value;
ws=new WebSocket(address);
ws.onopen=function(e){
var msg=document.createElement('div');
msg.style.color='#0f0';
msg.innerHTML="Server > connection open.";
msgContainer.appendChild(msg);
ws.send('{<'+document.getElementById('name').value+'>}');
};
ws.onmessage=function(e){
var msg=document.createElement('div');
msg.style.color='#fff';
msg.innerHTML=e.data;
msgContainer.appendChild(msg);
};
ws.onerror=function(e){
var msg=document.createElement('div');
msg.style.color='#0f0';
msg.innerHTML='Server > '+e.data;
msgContainer.appendChild(msg);
};
ws.onclose=function(e){
var msg=document.createElement('div');
msg.style.color='#0f0';
msg.innerHTML="Server > connection closed by server.";
msgContainer.appendChild(msg);
};
text.focus();
}
function quit(){
if(ws){
ws.close();
var msg=document.createElement('div');
msg.style.color='#0f0';
msg.innerHTML='Server > connection closed.';
msgContainer.appendChild(msg);
ws=null;
}
}
function send(){
ws.send(text.value);
setTimeout(function(){
msgContainer.scrollTop=msgContainer.getBoundingClientRect().height;
},100);
text.value='';
text.focus();
}
function clearMsg(){
msgContainer.innerHTML="";
}
function enter(event){
if(event.keyCode==13){
send();
}
}
</script>
</body>
</html>
http {
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
# websocket
upstream websocket {
server 127.0.0.1:8081;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name localhost;
#access_log logs/host.access.log main;
location / {
location /home/webSocketServer {
proxy_pass http://websocket;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}