更新websocket,非Stomp协议的原生WebSocket协议。
This commit is contained in:
parent
03cb51fd4a
commit
4b56e79eac
@ -0,0 +1,45 @@
|
|||||||
|
package com.xncoding.jwt.commons;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JacksonUtil
|
||||||
|
*
|
||||||
|
* @author XiongNeng
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2018/3/4
|
||||||
|
*/
|
||||||
|
public class JacksonUtil {
|
||||||
|
private static ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public static String bean2Json(Object obj) {
|
||||||
|
try {
|
||||||
|
return mapper.writeValueAsString(obj);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
|
||||||
|
// try {
|
||||||
|
// return mapper.readValue(jsonStr, objClass);
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static <T> T json2Bean(String jsonStr, TypeReference<T> typeReference) {
|
||||||
|
try {
|
||||||
|
return mapper.readValue(jsonStr, typeReference);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +1,25 @@
|
|||||||
package com.xncoding.jwt.config;
|
package com.xncoding.jwt.config;
|
||||||
|
|
||||||
|
import com.xncoding.jwt.handler.SocketHandler;
|
||||||
|
import com.xncoding.jwt.interceptor.WebSocketInterceptor;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||||
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
|
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSocketConfig
|
* WebSocketConfig
|
||||||
*
|
*
|
||||||
* @author XiongNeng
|
* @author XiongNeng
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
* @since 2018/2/28
|
* @since 2018/3/22
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSocketMessageBroker
|
@EnableWebSocket
|
||||||
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
|
public class WebSocketConfig implements WebSocketConfigurer {
|
||||||
|
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||||
@Override
|
registry.addHandler(new SocketHandler(), "/app")
|
||||||
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
|
.addInterceptors(new WebSocketInterceptor())
|
||||||
stompEndpointRegistry.addEndpoint("/simple")
|
.setAllowedOrigins("*");
|
||||||
.setAllowedOrigins("*") //解决跨域问题
|
|
||||||
.withSockJS();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
|
||||||
registry.enableSimpleBroker("/topic");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.xncoding.jwt.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||||
|
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
|
||||||
|
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||||
|
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STOMP协议的WebStocket
|
||||||
|
*
|
||||||
|
* @author XiongNeng
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2018/2/28
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSocketMessageBroker
|
||||||
|
public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
|
||||||
|
stompEndpointRegistry.addEndpoint("/simple")
|
||||||
|
.setAllowedOrigins("*") //解决跨域问题
|
||||||
|
.withSockJS();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||||
|
registry.enableSimpleBroker("/topic");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
package com.xncoding.jwt.handler;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.xncoding.jwt.commons.JacksonUtil;
|
||||||
|
import com.xncoding.jwt.model.WsParam;
|
||||||
|
import com.xncoding.jwt.model.WsResponse;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SocketHandler
|
||||||
|
*
|
||||||
|
* @author XiongNeng
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2018/3/22
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SocketHandler extends TextWebSocketHandler {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||||
|
logger.info("handleTextMessage start");
|
||||||
|
// 将消息进行转化,因为是消息是json数据,可能里面包含了发送给某个人的信息,所以需要用json相关的工具类处理之后再封装成TextMessage,
|
||||||
|
// 我这儿并没有做处理,消息的封装格式一般有{from:xxxx,to:xxxxx,msg:xxxxx},来自哪里,发送给谁,什么消息等等
|
||||||
|
String msg = message.getPayload();
|
||||||
|
logger.info("msg = " + msg);
|
||||||
|
WsParam wsParam = JacksonUtil.json2Bean(msg, new TypeReference<WsParam>(){});
|
||||||
|
if ("list".equals(wsParam.getMethod())) {
|
||||||
|
logger.info("call list method...");
|
||||||
|
WsResponse response = new WsResponse();
|
||||||
|
response.setResult("hello list");
|
||||||
|
sendMessageToUser(session, new TextMessage(JacksonUtil.bean2Json(response)));
|
||||||
|
}
|
||||||
|
logger.info("handleTextMessage end");
|
||||||
|
// 给所有用户群发消息
|
||||||
|
//sendMessagesToUsers(msg);
|
||||||
|
// 给指定用户群发消息
|
||||||
|
//sendMessageToUser(userId, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
||||||
|
logger.info("Connected ... " + session.getId());
|
||||||
|
sessions.add(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
|
||||||
|
if (session.isOpen()) {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
sessions.remove(session);
|
||||||
|
logger.info(String.format("Session %s closed because of %s", session.getId(), status.getReason()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
|
||||||
|
logger.error("error occured at sender " + session, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给所有的用户发送消息
|
||||||
|
*/
|
||||||
|
public void sendMessagesToUsers(TextMessage message) {
|
||||||
|
for (WebSocketSession user : sessions) {
|
||||||
|
try {
|
||||||
|
// isOpen()在线就发送
|
||||||
|
if (user.isOpen()) {
|
||||||
|
user.sendMessage(message);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息给指定的用户
|
||||||
|
*/
|
||||||
|
private void sendMessageToUser(WebSocketSession user, TextMessage message) {
|
||||||
|
try {
|
||||||
|
// 在线就发送
|
||||||
|
if (user.isOpen()) {
|
||||||
|
user.sendMessage(message);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("发送消息给指定的用户出错", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.xncoding.jwt.interceptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
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.HandshakeInterceptor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebSocketInterceptor
|
||||||
|
*
|
||||||
|
* @author XiongNeng
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2018/3/22
|
||||||
|
*/
|
||||||
|
public class WebSocketInterceptor implements HandshakeInterceptor {
|
||||||
|
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
@Override
|
||||||
|
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse arg1,
|
||||||
|
WebSocketHandler arg2, Map<String, Object> arg3) throws Exception {
|
||||||
|
// 将ServerHttpRequest转换成request请求相关的类,用来获取request域中的用户信息
|
||||||
|
if (request instanceof ServletServerHttpRequest) {
|
||||||
|
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
|
||||||
|
HttpServletRequest httpRequest = servletRequest.getServletRequest();
|
||||||
|
}
|
||||||
|
logger.info("beforeHandshake完成");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterHandshake(ServerHttpRequest arg0, ServerHttpResponse arg1, WebSocketHandler arg2, Exception arg3) {
|
||||||
|
logger.info("afterHandshake完成");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.xncoding.jwt.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WsParam
|
||||||
|
*
|
||||||
|
* @author XiongNeng
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2018/3/22
|
||||||
|
*/
|
||||||
|
public class WsParam {
|
||||||
|
private String method;
|
||||||
|
private Object param;
|
||||||
|
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethod(String method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getParam() {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParam(Object param) {
|
||||||
|
this.param = param;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.xncoding.jwt.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WsResponse
|
||||||
|
*
|
||||||
|
* @author XiongNeng
|
||||||
|
* @version 1.0
|
||||||
|
* @since 2018/3/22
|
||||||
|
*/
|
||||||
|
public class WsResponse {
|
||||||
|
private Object result;
|
||||||
|
|
||||||
|
public Object getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(Object result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>广播式WebSocket</title>
|
||||||
|
<script src="js/sockjs.min.js"></script>
|
||||||
|
<script src="js/stomp.js"></script>
|
||||||
|
<script src="js/jquery-3.1.1.js"></script>
|
||||||
|
</head>
|
||||||
|
<body onload="disconnect()">
|
||||||
|
<noscript><h2 style="color: #e80b0a;">Sorry,浏览器不支持WebSocket</h2></noscript>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<button id="connect" onclick="connect();">连接</button>
|
||||||
|
<button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="conversationDiv">
|
||||||
|
<label>输入你的名字</label><input type="text" id="name"/>
|
||||||
|
<button id="sendName" onclick="sendName();">发送</button>
|
||||||
|
<p id="response"></p>
|
||||||
|
<p id="callback"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var ws;
|
||||||
|
function connect() {
|
||||||
|
ws = new WebSocket('ws://localhost:8092/app');
|
||||||
|
ws.onmessage = function(data){
|
||||||
|
console.log("msg = " + JSON.stringify(data.data));
|
||||||
|
showResponse(data.data);
|
||||||
|
};
|
||||||
|
setConnected(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function disconnect() {
|
||||||
|
if (ws != null) {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
setConnected(false);
|
||||||
|
console.log("Disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendName() {
|
||||||
|
var data = {
|
||||||
|
"method": "list",
|
||||||
|
"param": $("#name").val()
|
||||||
|
};
|
||||||
|
ws.send(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResponse(message) {
|
||||||
|
$("#response").html(message);
|
||||||
|
}
|
||||||
|
function showCallback(message) {
|
||||||
|
$("#callback").html(message);
|
||||||
|
}
|
||||||
|
function setConnected(connected) {
|
||||||
|
document.getElementById("connect").disabled = connected;
|
||||||
|
document.getElementById("disconnect").disabled = !connected;
|
||||||
|
document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden';
|
||||||
|
$("#response").html();
|
||||||
|
$("#callback").html();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user