Skip to content

Commit 4b56e79

Browse files
author
Xiong Neng
committed
更新websocket,非Stomp协议的原生WebSocket协议。
1 parent 03cb51f commit 4b56e79

File tree

8 files changed

+349
-18
lines changed

8 files changed

+349
-18
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.xncoding.jwt.commons;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.core.type.TypeReference;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
7+
import java.io.IOException;
8+
9+
/**
10+
* JacksonUtil
11+
*
12+
* @author XiongNeng
13+
* @version 1.0
14+
* @since 2018/3/4
15+
*/
16+
public class JacksonUtil {
17+
private static ObjectMapper mapper = new ObjectMapper();
18+
19+
public static String bean2Json(Object obj) {
20+
try {
21+
return mapper.writeValueAsString(obj);
22+
} catch (JsonProcessingException e) {
23+
e.printStackTrace();
24+
return "";
25+
}
26+
}
27+
28+
// public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
29+
// try {
30+
// return mapper.readValue(jsonStr, objClass);
31+
// } catch (IOException e) {
32+
// e.printStackTrace();
33+
// return null;
34+
// }
35+
// }
36+
37+
public static <T> T json2Bean(String jsonStr, TypeReference<T> typeReference) {
38+
try {
39+
return mapper.readValue(jsonStr, typeReference);
40+
} catch (IOException e) {
41+
e.printStackTrace();
42+
return null;
43+
}
44+
}
45+
}
Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
11
package com.xncoding.jwt.config;
22

3+
import com.xncoding.jwt.handler.SocketHandler;
4+
import com.xncoding.jwt.interceptor.WebSocketInterceptor;
35
import org.springframework.context.annotation.Configuration;
4-
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
5-
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
6-
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
7-
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
6+
import org.springframework.web.socket.config.annotation.EnableWebSocket;
7+
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
8+
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
89

910
/**
1011
* WebSocketConfig
1112
*
1213
* @author XiongNeng
1314
* @version 1.0
14-
* @since 2018/2/28
15+
* @since 2018/3/22
1516
*/
1617
@Configuration
17-
@EnableWebSocketMessageBroker
18-
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
19-
20-
@Override
21-
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
22-
stompEndpointRegistry.addEndpoint("/simple")
23-
.setAllowedOrigins("*") //解决跨域问题
24-
.withSockJS();
25-
}
26-
27-
@Override
28-
public void configureMessageBroker(MessageBrokerRegistry registry) {
29-
registry.enableSimpleBroker("/topic");
18+
@EnableWebSocket
19+
public class WebSocketConfig implements WebSocketConfigurer {
20+
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
21+
registry.addHandler(new SocketHandler(), "/app")
22+
.addInterceptors(new WebSocketInterceptor())
23+
.setAllowedOrigins("*");
3024
}
3125
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.xncoding.jwt.config;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
5+
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
6+
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
7+
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
8+
9+
/**
10+
* STOMP协议的WebStocket
11+
*
12+
* @author XiongNeng
13+
* @version 1.0
14+
* @since 2018/2/28
15+
*/
16+
@Configuration
17+
@EnableWebSocketMessageBroker
18+
public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {
19+
20+
@Override
21+
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
22+
stompEndpointRegistry.addEndpoint("/simple")
23+
.setAllowedOrigins("*") //解决跨域问题
24+
.withSockJS();
25+
}
26+
27+
@Override
28+
public void configureMessageBroker(MessageBrokerRegistry registry) {
29+
registry.enableSimpleBroker("/topic");
30+
}
31+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package com.xncoding.jwt.handler;
2+
3+
import com.fasterxml.jackson.core.type.TypeReference;
4+
import com.xncoding.jwt.commons.JacksonUtil;
5+
import com.xncoding.jwt.model.WsParam;
6+
import com.xncoding.jwt.model.WsResponse;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import org.springframework.stereotype.Component;
10+
import org.springframework.web.socket.CloseStatus;
11+
import org.springframework.web.socket.TextMessage;
12+
import org.springframework.web.socket.WebSocketSession;
13+
import org.springframework.web.socket.handler.TextWebSocketHandler;
14+
15+
import java.io.IOException;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.concurrent.CopyOnWriteArrayList;
19+
20+
/**
21+
* SocketHandler
22+
*
23+
* @author XiongNeng
24+
* @version 1.0
25+
* @since 2018/3/22
26+
*/
27+
@Component
28+
public class SocketHandler extends TextWebSocketHandler {
29+
30+
private Logger logger = LoggerFactory.getLogger(this.getClass());
31+
32+
List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
33+
34+
@Override
35+
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
36+
logger.info("handleTextMessage start");
37+
// 将消息进行转化,因为是消息是json数据,可能里面包含了发送给某个人的信息,所以需要用json相关的工具类处理之后再封装成TextMessage,
38+
// 我这儿并没有做处理,消息的封装格式一般有{from:xxxx,to:xxxxx,msg:xxxxx},来自哪里,发送给谁,什么消息等等
39+
String msg = message.getPayload();
40+
logger.info("msg = " + msg);
41+
WsParam wsParam = JacksonUtil.json2Bean(msg, new TypeReference<WsParam>(){});
42+
if ("list".equals(wsParam.getMethod())) {
43+
logger.info("call list method...");
44+
WsResponse response = new WsResponse();
45+
response.setResult("hello list");
46+
sendMessageToUser(session, new TextMessage(JacksonUtil.bean2Json(response)));
47+
}
48+
logger.info("handleTextMessage end");
49+
// 给所有用户群发消息
50+
//sendMessagesToUsers(msg);
51+
// 给指定用户群发消息
52+
//sendMessageToUser(userId, msg);
53+
}
54+
55+
56+
57+
@Override
58+
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
59+
logger.info("Connected ... " + session.getId());
60+
sessions.add(session);
61+
}
62+
63+
@Override
64+
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
65+
if (session.isOpen()) {
66+
session.close();
67+
}
68+
sessions.remove(session);
69+
logger.info(String.format("Session %s closed because of %s", session.getId(), status.getReason()));
70+
}
71+
72+
@Override
73+
public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
74+
logger.error("error occured at sender " + session, throwable);
75+
}
76+
77+
/**
78+
* 给所有的用户发送消息
79+
*/
80+
public void sendMessagesToUsers(TextMessage message) {
81+
for (WebSocketSession user : sessions) {
82+
try {
83+
// isOpen()在线就发送
84+
if (user.isOpen()) {
85+
user.sendMessage(message);
86+
}
87+
} catch (IOException e) {
88+
e.printStackTrace();
89+
}
90+
}
91+
}
92+
93+
/**
94+
* 发送消息给指定的用户
95+
*/
96+
private void sendMessageToUser(WebSocketSession user, TextMessage message) {
97+
try {
98+
// 在线就发送
99+
if (user.isOpen()) {
100+
user.sendMessage(message);
101+
}
102+
} catch (IOException e) {
103+
logger.error("发送消息给指定的用户出错", e);
104+
}
105+
}
106+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.xncoding.jwt.interceptor;
2+
3+
import javax.servlet.http.HttpServletRequest;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.springframework.http.server.ServerHttpRequest;
8+
import org.springframework.http.server.ServerHttpResponse;
9+
import org.springframework.http.server.ServletServerHttpRequest;
10+
import org.springframework.web.socket.WebSocketHandler;
11+
import org.springframework.web.socket.server.HandshakeInterceptor;
12+
13+
import java.util.Map;
14+
15+
/**
16+
* WebSocketInterceptor
17+
*
18+
* @author XiongNeng
19+
* @version 1.0
20+
* @since 2018/3/22
21+
*/
22+
public class WebSocketInterceptor implements HandshakeInterceptor {
23+
private Logger logger = LoggerFactory.getLogger(this.getClass());
24+
@Override
25+
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse arg1,
26+
WebSocketHandler arg2, Map<String, Object> arg3) throws Exception {
27+
// 将ServerHttpRequest转换成request请求相关的类,用来获取request域中的用户信息
28+
if (request instanceof ServletServerHttpRequest) {
29+
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
30+
HttpServletRequest httpRequest = servletRequest.getServletRequest();
31+
}
32+
logger.info("beforeHandshake完成");
33+
return true;
34+
}
35+
36+
@Override
37+
public void afterHandshake(ServerHttpRequest arg0, ServerHttpResponse arg1, WebSocketHandler arg2, Exception arg3) {
38+
logger.info("afterHandshake完成");
39+
}
40+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.xncoding.jwt.model;
2+
3+
/**
4+
* WsParam
5+
*
6+
* @author XiongNeng
7+
* @version 1.0
8+
* @since 2018/3/22
9+
*/
10+
public class WsParam {
11+
private String method;
12+
private Object param;
13+
14+
public String getMethod() {
15+
return method;
16+
}
17+
18+
public void setMethod(String method) {
19+
this.method = method;
20+
}
21+
22+
public Object getParam() {
23+
return param;
24+
}
25+
26+
public void setParam(Object param) {
27+
this.param = param;
28+
}
29+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.xncoding.jwt.model;
2+
3+
/**
4+
* WsResponse
5+
*
6+
* @author XiongNeng
7+
* @version 1.0
8+
* @since 2018/3/22
9+
*/
10+
public class WsResponse {
11+
private Object result;
12+
13+
public Object getResult() {
14+
return result;
15+
}
16+
17+
public void setResult(Object result) {
18+
this.result = result;
19+
}
20+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<html>
2+
<head>
3+
<meta charset="UTF-8"/>
4+
<title>广播式WebSocket</title>
5+
<script src="js/sockjs.min.js"></script>
6+
<script src="js/stomp.js"></script>
7+
<script src="js/jquery-3.1.1.js"></script>
8+
</head>
9+
<body onload="disconnect()">
10+
<noscript><h2 style="color: #e80b0a;">Sorry,浏览器不支持WebSocket</h2></noscript>
11+
<div>
12+
<div>
13+
<button id="connect" onclick="connect();">连接</button>
14+
<button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
15+
</div>
16+
17+
<div id="conversationDiv">
18+
<label>输入你的名字</label><input type="text" id="name"/>
19+
<button id="sendName" onclick="sendName();">发送</button>
20+
<p id="response"></p>
21+
<p id="callback"></p>
22+
</div>
23+
</div>
24+
<script type="text/javascript">
25+
var ws;
26+
function connect() {
27+
ws = new WebSocket('ws://localhost:8092/app');
28+
ws.onmessage = function(data){
29+
console.log("msg = " + JSON.stringify(data.data));
30+
showResponse(data.data);
31+
};
32+
setConnected(true);
33+
}
34+
35+
function disconnect() {
36+
if (ws != null) {
37+
ws.close();
38+
}
39+
setConnected(false);
40+
console.log("Disconnected");
41+
}
42+
43+
function sendName() {
44+
var data = {
45+
"method": "list",
46+
"param": $("#name").val()
47+
};
48+
ws.send(JSON.stringify(data));
49+
}
50+
51+
function showResponse(message) {
52+
$("#response").html(message);
53+
}
54+
function showCallback(message) {
55+
$("#callback").html(message);
56+
}
57+
function setConnected(connected) {
58+
document.getElementById("connect").disabled = connected;
59+
document.getElementById("disconnect").disabled = !connected;
60+
document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden';
61+
$("#response").html();
62+
$("#callback").html();
63+
}
64+
</script>
65+
</body>
66+
</html>

0 commit comments

Comments
 (0)