增加 spring websocket stomp 示例

This commit is contained in:
YunaiV
2019-11-21 09:23:49 +08:00
parent 43bbff6f31
commit 5229dd69c4
15 changed files with 466 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-websocket-25-03</artifactId>
<dependencies>
<!-- 实现对 WebSocket 相关依赖的引入,方便~ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 引入 Fastjson ,实现对 JSON 的序列化,因为后续我们会使用它解析消息 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,13 @@
package cn.iocoder.springboot.lab25.springwebsocket;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,51 @@
package cn.iocoder.springboot.lab25.springwebsocket.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker // 开启 Spring WebSocket 对 Stomp 的支持
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// registry.addEndpoint("/send_to_all")
// .setAllowedOrigins("*")
// .withSockJS();
registry.addEndpoint("/")
.setAllowedOrigins("*")
.withSockJS();
// RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
// registry.addEndpoint("/")
// .setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
// .setAllowedOrigins("*");
}
// @Override
// public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// registry.addHandler(this.webSocketHandler(), "/") // 配置处理器
// .addInterceptors(new DemoWebSocketShakeInterceptor()) // 配置拦截器
// .setAllowedOrigins("*"); // 解决跨域问题
// }
// @Bean
// public DemoWebSocketHandler webSocketHandler() {
// return new DemoWebSocketHandler();
// }
// @Bean
// public DemoWebSocketShakeInterceptor webSocketShakeInterceptor() {
// return new DemoWebSocketShakeInterceptor();
// }
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.springboot.lab25.springwebsocket.controller;
import cn.iocoder.springboot.lab25.springwebsocket.message.SendToAllRequest;
import cn.iocoder.springboot.lab25.springwebsocket.message.SendToUserRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class SendController {
private Logger logger = LoggerFactory.getLogger(getClass());
@MessageMapping("/send_to_all")
@SendTo(value = "/topic/send_to_all")
public SendToUserRequest sendToAll(SendToAllRequest message) {
logger.info("[sendToAll][SendToAllRequest({})]", message);
// // 创建转发的消息
// SendToUserRequest sendToUserRequest = new SendToUserRequest().setMsgId(message.getMsgId())
// .setContent(message.getContent());
// // 广播发送
// WebSocketUtil.broadcast(SendToUserRequest.TYPE, sendToUserRequest);
// 这里,假装直接成功
// return new SendResponse().setMsgId(message.getMsgId()).setCode(0);
return new SendToUserRequest().setMsgId(message.getMsgId())
.setContent(message.getContent());
}
// @SubscribeMapping("/topic/send_to_all")
// public void subSendToAll(SendToUserRequest message) {
// logger.info("[subSendToAll][SendToUserRequest({})]", message);
// }
}

View File

@@ -0,0 +1,24 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 用户认证请求
*/
public class AuthRequest implements Message {
public static final String TYPE = "AUTH_REQUEST";
/**
* 认证 Token
*/
private String accessToken;
public String getAccessToken() {
return accessToken;
}
public AuthRequest setAccessToken(String accessToken) {
this.accessToken = accessToken;
return this;
}
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 用户认证响应
*/
public class AuthResponse implements Message {
public static final String TYPE = "AUTH_RESPONSE";
/**
* 响应状态码
*/
private Integer code;
/**
* 响应提示
*/
private String message;
public Integer getCode() {
return code;
}
public AuthResponse setCode(Integer code) {
this.code = code;
return this;
}
public String getMessage() {
return message;
}
public AuthResponse setMessage(String message) {
this.message = message;
return this;
}
}

View File

@@ -0,0 +1,7 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 基础消息体
*/
public interface Message {
}

View File

@@ -0,0 +1,50 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 发送消息响应结果的 Message
*/
public class SendResponse implements Message {
public static final String TYPE = "SEND_RESPONSE";
/**
* 消息编号
*/
private String msgId;
/**
* 响应状态码
*/
private Integer code;
/**
* 响应提示
*/
private String message;
public String getMsgId() {
return msgId;
}
public SendResponse setMsgId(String msgId) {
this.msgId = msgId;
return this;
}
public Integer getCode() {
return code;
}
public SendResponse setCode(Integer code) {
this.code = code;
return this;
}
public String getMessage() {
return message;
}
public SendResponse setMessage(String message) {
this.message = message;
return this;
}
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 发送给所有人的群聊消息的 Message
*/
public class SendToAllRequest implements Message {
public static final String TYPE = "SEND_TO_ALL_REQUEST";
/**
* 消息编号
*/
private String msgId;
/**
* 内容
*/
private String content;
public String getContent() {
return content;
}
public SendToAllRequest setContent(String content) {
this.content = content;
return this;
}
public String getMsgId() {
return msgId;
}
public SendToAllRequest setMsgId(String msgId) {
this.msgId = msgId;
return this;
}
}

View File

@@ -0,0 +1,49 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 发送给指定人的私聊消息的 Message
*/
public class SendToOneRequest implements Message {
public static final String TYPE = "SEND_TO_ONE_REQUEST";
/**
* 发送给的用户
*/
private String toUser;
/**
* 消息编号
*/
private String msgId;
/**
* 内容
*/
private String content;
public String getToUser() {
return toUser;
}
public SendToOneRequest setToUser(String toUser) {
this.toUser = toUser;
return this;
}
public String getMsgId() {
return msgId;
}
public SendToOneRequest setMsgId(String msgId) {
this.msgId = msgId;
return this;
}
public String getContent() {
return content;
}
public SendToOneRequest setContent(String content) {
this.content = content;
return this;
}
}

View File

@@ -0,0 +1,37 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 发送消息给一个用户的 Message
*/
public class SendToUserRequest implements Message {
public static final String TYPE = "SEND_TO_USER_REQUEST";
/**
* 消息编号
*/
private String msgId;
/**
* 内容
*/
private String content;
public String getMsgId() {
return msgId;
}
public SendToUserRequest setMsgId(String msgId) {
this.msgId = msgId;
return this;
}
public String getContent() {
return content;
}
public SendToUserRequest setContent(String content) {
this.content = content;
return this;
}
}

View File

@@ -0,0 +1,24 @@
package cn.iocoder.springboot.lab25.springwebsocket.message;
/**
* 用户加入群聊的通知 Message
*/
public class UserJoinNoticeRequest implements Message {
public static final String TYPE = "USER_JOIN_NOTICE_REQUEST";
/**
* 昵称
*/
private String nickname;
public String getNickname() {
return nickname;
}
public UserJoinNoticeRequest setNickname(String nickname) {
this.nickname = nickname;
return this;
}
}

View File

@@ -0,0 +1,68 @@
package cn.iocoder.springboot.lab25.springwebsocket;
import cn.iocoder.springboot.lab25.springwebsocket.message.SendToAllRequest;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandler;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.UUID;
public class Main {
public static void main(String[] args) {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport( new StandardWebSocketClient()) );
WebSocketClient transport = new SockJsClient(transports); // TODO 芋艿,参考 https://codeday.me/bug/20190115/521240.html 文章
// WebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(transport);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
StompSessionHandler sessionHandler = new StompSessionHandler() {
@Override
public void afterConnected(StompSession stompSession, StompHeaders stompHeaders) {
// stompSession.subscribe("/topic/send_to_all", this);
stompSession.send("/app/send_to_all", new SendToAllRequest().setMsgId(UUID.randomUUID().toString())
.setContent("测试消息"));
}
@Override
public void handleException(StompSession stompSession, StompCommand stompCommand, StompHeaders stompHeaders, byte[] bytes, Throwable throwable) {
System.out.println();
}
@Override
public void handleTransportError(StompSession stompSession, Throwable throwable) {
System.out.println();
}
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return null;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
System.out.println();
}
};
stompClient.connect("ws://127.0.0.1:8080/", sessionHandler);
new Scanner(System.in).nextLine(); // Don't close immediately.
}
}

View File

@@ -14,6 +14,7 @@
<modules>
<module>lab-websocket-25-01</module>
<module>lab-websocket-25-02</module>
<module>lab-websocket-25-03</module>
</modules>