spring-boot自己對websocket提供了很好的支持,能夠直接原生支持sockjs和stomp協議。百度搜了一些中文文檔,雖然也能實現websocket,可是並無直接使用spring-boot直接支持的websocket的特性。web
在實踐中以爲stromp協議對於websocket開發的自由度影響比較大。這裏給你們展現一種自由度比較大的方案。spring
主要就是三個組件,config,interceptor和handlerwebsocket
@Configuration @EnableWebSocket public class MessageWebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(messageWebSocketHandler(), "/sockjs/message") .addInterceptors(new MessageWebSocketInterceptor()).withSockJS(); } @Bean public MessageWebSocketHandler messageWebSocketHandler() { return new MessageWebSocketHandler(); } }
config須要繼承WebSocketConfigurer
須要重寫registerWebSocketHandlers
方法,指明handler和interceptor。session
interceptor顧名思義爲攔截器咱們能夠在websocket創建之間和以後作一些事情。重載beforeHandshake
和afterHandshake
就OK。我在beforeHandshake
這裏還操做了attributes
。被修改的attributes
會被帶到後面websocket的session之中。socket
public class MessageWebSocketInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; String siteId = servletRequest.getServletRequest().getParameter("siteId"); String userId = servletRequest.getServletRequest().getParameter("userId"); if (siteId == null || userId == null) { return false; } attributes.put("siteId", siteId); attributes.put("userId", userId); } return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } }
handler裏面就能夠寫websocket的邏輯啦ide
public class MessageWebSocketHandler implements WebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) { } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) { } @Override public void handleTransportError(WebSocketSession session, Throwable exception) { } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) { } @Override public boolean supportsPartialMessages() { return false; } }
spring-boot單元測試能夠寫websocket-clientspring-boot
@RunWith(SpringRunner.class) @SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class WebsocketTest { private final Logger logger = LoggerFactory.getLogger(WebsocketTest.class); private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); final CountDownLatch latch = new CountDownLatch(1); final AtomicReference<Throwable> failure = new AtomicReference<>(); @LocalServerPort private int port; private SockJsClient sockJsClient; @Before public void setup() { List<Transport> transports = new ArrayList<>(); transports.add(new WebSocketTransport(new StandardWebSocketClient())); transports.add(new RestTemplateXhrTransport()); this.sockJsClient = new SockJsClient(transports); } @Test public void getGreeting() throws Exception { this.sockJsClient.doHandshake(new TestWebSocketHandler(failure), "ws://localhost:"+String.valueOf(port)+"/sockjs/message?siteId=webtrn&userId=lucy"); if (latch.await(60, TimeUnit.SECONDS)) { if (failure.get() != null) { throw new AssertionError("", failure.get()); } } else { fail("Greeting not received"); } } private class TestWebSocketHandler implements WebSocketHandler { private final AtomicReference<Throwable> failure; TestWebSocketHandler() { this.failure = null; } ; TestWebSocketHandler(AtomicReference<Throwable> failure) { this.failure = failure; } ; @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.info("client connection established"); session.sendMessage(new TextMessage("hello websocket server!")); } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { String payload = (String) message.getPayload(); logger.info("client handle message: " + payload); if (payload.equals("hello websocket client! webtrn lucy")) { latch.countDown(); } if (payload.equals("web socket notify")) { latch.countDown(); } } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { logger.info("client transport error"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { logger.info("client connection closed"); } @Override public boolean supportsPartialMessages() { return false; } } }
若是採用stomp協議的話能夠參考spring-boot的一個ws-guide。有問題仍是直接看spring文檔比較好。單元測試