From 4b56e79eac4430a87a2829c594a340ab2f55bc94 Mon Sep 17 00:00:00 2001 From: Xiong Neng Date: Thu, 22 Mar 2018 09:10:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0websocket=EF=BC=8C=E9=9D=9ESt?= =?UTF-8?q?omp=E5=8D=8F=E8=AE=AE=E7=9A=84=E5=8E=9F=E7=94=9FWebSocket?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/xncoding/jwt/commons/JacksonUtil.java | 45 ++++++++ .../xncoding/jwt/config/WebSocketConfig.java | 30 ++--- .../jwt/config/WebSocketStompConfig.java | 31 +++++ .../xncoding/jwt/handler/SocketHandler.java | 106 ++++++++++++++++++ .../jwt/interceptor/WebSocketInterceptor.java | 40 +++++++ .../java/com/xncoding/jwt/model/WsParam.java | 29 +++++ .../com/xncoding/jwt/model/WsResponse.java | 20 ++++ .../jwt/socket/client/html/index1.html | 66 +++++++++++ 8 files changed, 349 insertions(+), 18 deletions(-) create mode 100644 springboot-websocket/src/main/java/com/xncoding/jwt/commons/JacksonUtil.java create mode 100644 springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketStompConfig.java create mode 100644 springboot-websocket/src/main/java/com/xncoding/jwt/handler/SocketHandler.java create mode 100644 springboot-websocket/src/main/java/com/xncoding/jwt/interceptor/WebSocketInterceptor.java create mode 100644 springboot-websocket/src/main/java/com/xncoding/jwt/model/WsParam.java create mode 100644 springboot-websocket/src/main/java/com/xncoding/jwt/model/WsResponse.java create mode 100644 springboot-websocket/src/test/java/com/xncoding/jwt/socket/client/html/index1.html diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/commons/JacksonUtil.java b/springboot-websocket/src/main/java/com/xncoding/jwt/commons/JacksonUtil.java new file mode 100644 index 0000000..f672d9a --- /dev/null +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/commons/JacksonUtil.java @@ -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 json2Bean(String jsonStr, Class objClass) { +// try { +// return mapper.readValue(jsonStr, objClass); +// } catch (IOException e) { +// e.printStackTrace(); +// return null; +// } +// } + + public static T json2Bean(String jsonStr, TypeReference typeReference) { + try { + return mapper.readValue(jsonStr, typeReference); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketConfig.java b/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketConfig.java index bee5421..3d1681a 100644 --- a/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketConfig.java +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketConfig.java @@ -1,31 +1,25 @@ 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.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; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; /** * WebSocketConfig * * @author XiongNeng * @version 1.0 - * @since 2018/2/28 + * @since 2018/3/22 */ @Configuration -@EnableWebSocketMessageBroker -public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { - - @Override - public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) { - stompEndpointRegistry.addEndpoint("/simple") - .setAllowedOrigins("*") //解决跨域问题 - .withSockJS(); - } - - @Override - public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.enableSimpleBroker("/topic"); +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(new SocketHandler(), "/app") + .addInterceptors(new WebSocketInterceptor()) + .setAllowedOrigins("*"); } } diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketStompConfig.java b/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketStompConfig.java new file mode 100644 index 0000000..259b1eb --- /dev/null +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/config/WebSocketStompConfig.java @@ -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"); + } +} diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/handler/SocketHandler.java b/springboot-websocket/src/main/java/com/xncoding/jwt/handler/SocketHandler.java new file mode 100644 index 0000000..b5ccef5 --- /dev/null +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/handler/SocketHandler.java @@ -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 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(){}); + 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); + } + } +} diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/interceptor/WebSocketInterceptor.java b/springboot-websocket/src/main/java/com/xncoding/jwt/interceptor/WebSocketInterceptor.java new file mode 100644 index 0000000..59e9f1e --- /dev/null +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/interceptor/WebSocketInterceptor.java @@ -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 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完成"); + } +} diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/model/WsParam.java b/springboot-websocket/src/main/java/com/xncoding/jwt/model/WsParam.java new file mode 100644 index 0000000..2b1e098 --- /dev/null +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/model/WsParam.java @@ -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; + } +} diff --git a/springboot-websocket/src/main/java/com/xncoding/jwt/model/WsResponse.java b/springboot-websocket/src/main/java/com/xncoding/jwt/model/WsResponse.java new file mode 100644 index 0000000..42d8cc1 --- /dev/null +++ b/springboot-websocket/src/main/java/com/xncoding/jwt/model/WsResponse.java @@ -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; + } +} diff --git a/springboot-websocket/src/test/java/com/xncoding/jwt/socket/client/html/index1.html b/springboot-websocket/src/test/java/com/xncoding/jwt/socket/client/html/index1.html new file mode 100644 index 0000000..d33752a --- /dev/null +++ b/springboot-websocket/src/test/java/com/xncoding/jwt/socket/client/html/index1.html @@ -0,0 +1,66 @@ + + + + 广播式WebSocket + + + + + + +
+
+ + +
+ +
+ + +

+

+
+
+ + + \ No newline at end of file