Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gk
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
micro_app
gk
Commits
10f3fd13
Commit
10f3fd13
authored
Oct 20, 2025
by
daniel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(websocket): websocket接口调整
parent
beb3de1a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
201 additions
and
386 deletions
+201
-386
SchedulerConfig.java
...in/java/com/dlbridge/jadp/config/web/SchedulerConfig.java
+19
-0
WebSocketConfig.java
...in/java/com/dlbridge/jadp/config/web/WebSocketConfig.java
+21
-30
TicketWebSocketHandler.java
...a/com/dlbridge/jadp/websocket/TicketWebSocketHandler.java
+53
-0
WebSocketController.java
...java/com/dlbridge/jadp/websocket/WebSocketController.java
+0
-74
WebSocketEventListener.java
...a/com/dlbridge/jadp/websocket/WebSocketEventListener.java
+0
-65
WebSocketMessage.java
...in/java/com/dlbridge/jadp/websocket/WebSocketMessage.java
+53
-14
WebSocketSessionService.java
.../com/dlbridge/jadp/websocket/WebSocketSessionService.java
+31
-184
WebSocketSessionWrapper.java
.../com/dlbridge/jadp/websocket/WebSocketSessionWrapper.java
+24
-0
WebSocketTestController.java
.../com/dlbridge/jadp/websocket/WebSocketTestController.java
+0
-19
No files found.
src/main/java/com/dlbridge/jadp/config/web/SchedulerConfig.java
0 → 100644
View file @
10f3fd13
package
com
.
dlbridge
.
jadp
.
config
.
web
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
;
@Configuration
@EnableScheduling
public
class
SchedulerConfig
{
@Bean
public
ThreadPoolTaskScheduler
taskScheduler
()
{
ThreadPoolTaskScheduler
scheduler
=
new
ThreadPoolTaskScheduler
();
scheduler
.
setPoolSize
(
2
);
scheduler
.
setThreadNamePrefix
(
"scheduled-task-"
);
return
scheduler
;
}
}
src/main/java/com/dlbridge/jadp/config/web/WebSocketConfig.java
View file @
10f3fd13
package
com
.
dlbridge
.
jadp
.
config
.
web
;
import
com.dlbridge.jadp.websocket.TicketWebSocketHandler
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.messaging.simp.config.MessageBrokerRegistry
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
;
import
org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
;
import
org.springframework.web.socket.config.annotation.StompEndpointRegistry
;
import
org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
;
import
org.springframework.web.socket.config.annotation.*
;
@Configuration
@EnableWebSocket
MessageBroker
public
class
WebSocketConfig
implements
WebSocket
MessageBroker
Configurer
{
@EnableWebSocket
public
class
WebSocketConfig
implements
WebSocketConfigurer
{
@Override
public
void
configureMessageBroker
(
MessageBrokerRegistry
config
)
{
// 创建一个调度器,用于心跳定时任务
ThreadPoolTaskScheduler
taskScheduler
=
new
ThreadPoolTaskScheduler
();
taskScheduler
.
setPoolSize
(
1
);
taskScheduler
.
setThreadNamePrefix
(
"wss-heartbeat-thread-"
);
taskScheduler
.
initialize
();
// 启用简单消息代理,并配置心跳
config
.
enableSimpleBroker
(
"/topic"
,
"/queue"
)
.
setHeartbeatValue
(
new
long
[]{
10000
,
10000
})
// 服务端和客户端心跳间隔(毫秒)
.
setTaskScheduler
(
taskScheduler
);
// 设置应用程序目的地前缀
config
.
setApplicationDestinationPrefixes
(
"/app"
);
// 设置用户目的地前缀(点对点消息)
config
.
setUserDestinationPrefix
(
"/user"
);
private
final
TicketWebSocketHandler
handler
;
public
WebSocketConfig
(
TicketWebSocketHandler
handler
)
{
this
.
handler
=
handler
;
}
@Override
public
void
registerStompEndpoints
(
StompEndpointRegistry
registry
)
{
// 注册 STOMP 端点,指定使用 SockJS
registry
.
addEndpoint
(
"/ws"
).
setAllowedOrigins
(
"*"
)
// 允许所有来源,生产环境应指定具体域名
.
withSockJS
()
.
setHeartbeatTime
(
10000
);
public
void
registerWebSocketHandlers
(
WebSocketHandlerRegistry
registry
)
{
registry
.
addHandler
(
handler
,
"/ws/ticket"
)
.
setAllowedOrigins
(
"*"
);
// 原生 WebSocket, 不使用 SockJS
}
// 同时支持原生 WebSocket
registry
.
addEndpoint
(
"/ws"
)
.
setAllowedOrigins
(
"*"
);
// ✅ 这里就是声明 ThreadPoolTaskScheduler Bean
@Bean
public
ThreadPoolTaskScheduler
messageBrokerTaskScheduler
()
{
ThreadPoolTaskScheduler
scheduler
=
new
ThreadPoolTaskScheduler
();
scheduler
.
setPoolSize
(
1
);
scheduler
.
setThreadNamePrefix
(
"wss-heartbeat-thread-"
);
return
scheduler
;
}
}
}
\ No newline at end of file
src/main/java/com/dlbridge/jadp/websocket/TicketWebSocketHandler.java
0 → 100644
View file @
10f3fd13
package
com
.
dlbridge
.
jadp
.
websocket
;
import
cn.hutool.json.JSONObject
;
import
cn.hutool.json.JSONUtil
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.socket.*
;
import
org.springframework.web.socket.handler.TextWebSocketHandler
;
import
java.util.Map
;
@Component
public
class
TicketWebSocketHandler
extends
TextWebSocketHandler
{
private
final
WebSocketSessionService
sessionService
;
public
TicketWebSocketHandler
(
WebSocketSessionService
sessionService
)
{
this
.
sessionService
=
sessionService
;
}
@Override
public
void
afterConnectionEstablished
(
WebSocketSession
session
)
{
System
.
out
.
println
(
"新连接: "
+
session
.
getId
());
}
@Override
protected
void
handleTextMessage
(
WebSocketSession
session
,
TextMessage
message
)
throws
Exception
{
JSONObject
msg
=
JSONUtil
.
parseObj
(
message
.
getPayload
());
String
action
=
msg
.
getStr
(
"action"
);
String
ticketNo
=
msg
.
getStr
(
"ticketNo"
);
WebSocketSessionWrapper
wrapper
=
new
WebSocketSessionWrapper
(
session
);
switch
(
action
)
{
case
"subscribe"
:
sessionService
.
registerUserSession
(
ticketNo
,
ticketNo
,
session
.
getId
(),
wrapper
);
wrapper
.
sendMessage
(
WebSocketMessage
.
info
(
ticketNo
,
"订阅成功"
).
toJson
());
break
;
case
"unsubscribe"
:
sessionService
.
removeTicketSession
(
session
.
getId
(),
ticketNo
);
wrapper
.
sendMessage
(
WebSocketMessage
.
info
(
ticketNo
,
"取消订阅成功"
).
toJson
());
break
;
case
"heartbeat"
:
// 可记录心跳时间
break
;
}
}
@Override
public
void
afterConnectionClosed
(
WebSocketSession
session
,
CloseStatus
status
)
{
sessionService
.
removeUserSession
(
session
.
getId
());
System
.
out
.
println
(
"连接关闭: "
+
session
.
getId
());
}
}
\ No newline at end of file
src/main/java/com/dlbridge/jadp/websocket/WebSocketController.java
deleted
100644 → 0
View file @
beb3de1a
package
com
.
dlbridge
.
jadp
.
websocket
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.messaging.handler.annotation.MessageMapping
;
import
org.springframework.messaging.handler.annotation.Payload
;
import
org.springframework.messaging.simp.SimpMessageHeaderAccessor
;
import
org.springframework.messaging.simp.annotation.SubscribeMapping
;
import
org.springframework.stereotype.Controller
;
import
java.util.Map
;
@Slf4j
@Controller
@RequiredArgsConstructor
public
class
WebSocketController
{
private
final
WebSocketSessionService
sessionService
;
/**
* 处理客户端发送的心跳消息
*/
@MessageMapping
(
"/heartbeat"
)
public
void
handleHeartbeat
(
@Payload
Map
<
String
,
Object
>
message
)
{
String
sessionId
=
(
String
)
message
.
get
(
"sessionId"
);
String
userId
=
(
String
)
message
.
get
(
"userId"
);
log
.
info
(
"收到心跳消息 - 会话ID: {}, 用户ID: {}"
,
sessionId
,
userId
);
}
/**
* 处理客户端订阅特定票号
*/
@MessageMapping
(
"/ticket/subscribe"
)
public
void
handleTicketSubscribe
(
@Payload
Map
<
String
,
Object
>
message
,
SimpMessageHeaderAccessor
headerAccessor
)
{
// String sessionId = (String) message.get("sessionId");
String
sessionId
=
headerAccessor
.
getSessionId
();
String
userId
=
(
String
)
message
.
get
(
"userId"
);
String
ticketNo
=
(
String
)
message
.
get
(
"ticketNo"
);
log
.
info
(
"客户端订阅票号 - 会话ID: {}, 用户ID: {}, 票号: {}"
,
sessionId
,
userId
,
ticketNo
);
if
(
userId
!=
null
&&
ticketNo
!=
null
)
{
sessionService
.
registerUserSession
(
userId
,
ticketNo
,
sessionId
);
// 发送订阅成功确认
WebSocketMessage
response
=
WebSocketMessage
.
info
(
ticketNo
,
"票号订阅成功,开始接收核销通知"
);
sessionService
.
sendToUser
(
userId
,
response
);
}
}
/**
* 处理客户端取消订阅票号
*/
@MessageMapping
(
"/ticket/unsubscribe"
)
public
void
handleTicketUnsubscribe
(
@Payload
Map
<
String
,
Object
>
message
)
{
String
sessionId
=
(
String
)
message
.
get
(
"sessionId"
);
String
ticketNo
=
(
String
)
message
.
get
(
"ticketNo"
);
log
.
info
(
"客户端取消订阅票号 - 会话ID: {}, 票号: {}"
,
sessionId
,
ticketNo
);
sessionService
.
removeTicketSession
(
sessionId
,
ticketNo
);
}
/**
* 处理获取会话状态请求
*/
@SubscribeMapping
(
"/user/queue/status"
)
public
Map
<
String
,
Object
>
handleStatusRequest
()
{
return
sessionService
.
getSessionStats
();
}
}
\ No newline at end of file
src/main/java/com/dlbridge/jadp/websocket/WebSocketEventListener.java
deleted
100644 → 0
View file @
beb3de1a
package
com
.
dlbridge
.
jadp
.
websocket
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.context.event.EventListener
;
import
org.springframework.messaging.simp.stomp.StompHeaderAccessor
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.socket.messaging.SessionConnectEvent
;
import
org.springframework.web.socket.messaging.SessionDisconnectEvent
;
import
org.springframework.web.socket.messaging.SessionSubscribeEvent
;
@Slf4j
@Component
@RequiredArgsConstructor
public
class
WebSocketEventListener
{
private
final
WebSocketSessionService
sessionService
;
/**
* 处理 WebSocket 连接建立事件
*/
@EventListener
public
void
handleWebSocketConnectListener
(
SessionConnectEvent
event
)
{
StompHeaderAccessor
headerAccessor
=
StompHeaderAccessor
.
wrap
(
event
.
getMessage
());
String
sessionId
=
headerAccessor
.
getSessionId
();
String
userId
=
headerAccessor
.
getFirstNativeHeader
(
"userId"
);
log
.
info
(
"WebSocket 连接建立 - 会话ID: {}, 用户ID: {}"
,
sessionId
,
userId
);
}
/**
* 处理 WebSocket 订阅事件
*/
@EventListener
public
void
handleWebSocketSubscribeListener
(
SessionSubscribeEvent
event
)
{
StompHeaderAccessor
headerAccessor
=
StompHeaderAccessor
.
wrap
(
event
.
getMessage
());
String
sessionId
=
headerAccessor
.
getSessionId
();
String
destination
=
headerAccessor
.
getDestination
();
String
userId
=
headerAccessor
.
getFirstNativeHeader
(
"userId"
);
String
ticketNo
=
headerAccessor
.
getFirstNativeHeader
(
"ticketNo"
);
log
.
info
(
"WebSocket 订阅 - 会话ID: {}, 目的地: {}, 用户ID: {}, 票号: {}"
,
sessionId
,
destination
,
userId
,
ticketNo
);
if
(
userId
!=
null
&&
ticketNo
!=
null
)
{
sessionService
.
registerUserSession
(
userId
,
ticketNo
,
sessionId
);
}
}
/**
* 处理 WebSocket 连接断开事件
*/
@EventListener
public
void
handleWebSocketDisconnectListener
(
SessionDisconnectEvent
event
)
{
StompHeaderAccessor
headerAccessor
=
StompHeaderAccessor
.
wrap
(
event
.
getMessage
());
String
sessionId
=
headerAccessor
.
getSessionId
();
log
.
info
(
"WebSocket 连接断开 - 会话ID: {}"
,
sessionId
);
sessionService
.
removeUserSession
(
sessionId
);
}
}
src/main/java/com/dlbridge/jadp/websocket/WebSocketMessage.java
View file @
10f3fd13
package
com
.
dlbridge
.
jadp
.
websocket
;
import
lombok.AllArgsConstructor
;
import
cn.hutool.json.JSONObject
;
import
cn.hutool.json.JSONUtil
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.time.LocalDateTime
;
import
lombok.AllArgsConstructor
;
@Data
@NoArgsConstructor
@AllArgsConstructor
public
class
WebSocketMessage
{
private
String
type
;
// 消息类型:VERIFICATION_SUCCESS, ERROR, etc.
private
String
ticketNo
;
// 票号
private
String
message
;
// 消息内容
private
LocalDateTime
timestamp
;
// 时间戳
private
Object
data
;
// 附加数据
private
String
type
;
// 消息类型 success / error / info
private
String
ticketNo
;
// 票号
private
String
message
;
// 消息内容
private
Object
data
;
// 附加数据
// 定义一个内部的枚举类型,用于表示消息类型,包括成功、错误和信息三种类型,里面存放对应的字符串值
public
enum
MessageType
{
SUCCESS
(
"success"
),
ERROR
(
"error"
),
INFO
(
"info"
);
private
final
String
value
;
MessageType
(
String
value
)
{
this
.
value
=
value
;
}
public
String
getValue
()
{
return
value
;
}
}
// 构建消息静态方法
public
static
WebSocketMessage
success
(
String
ticketNo
,
String
message
)
{
return
new
WebSocketMessage
(
"VERIFICATION_SUCCESS"
,
ticketNo
,
message
,
LocalDateTime
.
now
(),
null
);
return
new
WebSocketMessage
(
MessageType
.
SUCCESS
.
getValue
(),
ticketNo
,
message
,
null
);
}
public
static
WebSocketMessage
success
(
String
ticketNo
,
String
message
,
Object
data
)
{
return
new
WebSocketMessage
(
MessageType
.
SUCCESS
.
getValue
(),
ticketNo
,
message
,
data
);
}
public
static
WebSocketMessage
error
(
String
ticketNo
,
String
message
)
{
return
new
WebSocketMessage
(
"ERROR"
,
ticketNo
,
message
,
LocalDateTime
.
now
(),
null
);
return
new
WebSocketMessage
(
MessageType
.
ERROR
.
getValue
(),
ticketNo
,
message
,
null
);
}
public
static
WebSocketMessage
error
(
String
ticketNo
,
String
message
,
Object
data
)
{
return
new
WebSocketMessage
(
MessageType
.
ERROR
.
getValue
(),
ticketNo
,
message
,
data
);
}
public
static
WebSocketMessage
info
(
String
ticketNo
,
String
message
)
{
return
new
WebSocketMessage
(
"INFO"
,
ticketNo
,
message
,
LocalDateTime
.
now
(),
null
);
return
new
WebSocketMessage
(
MessageType
.
INFO
.
getValue
(),
ticketNo
,
message
,
null
);
}
public
static
WebSocketMessage
info
(
String
ticketNo
,
String
message
,
Object
data
)
{
return
new
WebSocketMessage
(
MessageType
.
INFO
.
getValue
(),
ticketNo
,
message
,
data
);
}
// 转 JSON 字符串
public
String
toJson
()
{
JSONObject
obj
=
JSONUtil
.
createObj
()
.
set
(
"type"
,
type
)
.
set
(
"ticketNo"
,
ticketNo
)
.
set
(
"message"
,
message
);
if
(
data
!=
null
)
{
obj
.
set
(
"data"
,
data
);
}
return
obj
.
toString
();
}
}
}
\ No newline at end of file
src/main/java/com/dlbridge/jadp/websocket/WebSocketSessionService.java
View file @
10f3fd13
This diff is collapsed.
Click to expand it.
src/main/java/com/dlbridge/jadp/websocket/WebSocketSessionWrapper.java
0 → 100644
View file @
10f3fd13
package
com
.
dlbridge
.
jadp
.
websocket
;
import
org.springframework.web.socket.TextMessage
;
import
org.springframework.web.socket.WebSocketSession
;
public
class
WebSocketSessionWrapper
{
private
final
WebSocketSession
session
;
public
WebSocketSessionWrapper
(
WebSocketSession
session
)
{
this
.
session
=
session
;
}
public
void
sendMessage
(
String
payload
)
{
try
{
if
(
session
.
isOpen
())
session
.
sendMessage
(
new
TextMessage
(
payload
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
public
String
getId
()
{
return
session
.
getId
();
}
}
\ No newline at end of file
src/main/java/com/dlbridge/jadp/websocket/WebSocketTestController.java
View file @
10f3fd13
...
...
@@ -15,22 +15,6 @@ public class WebSocketTestController {
public
WebSocketTestController
(
WebSocketSessionService
sessionService
)
{
this
.
sessionService
=
sessionService
;
}
/**
* 测试接口:向指定用户发送票号核销消息
*/
@PostMapping
(
"/sendToUser"
)
public
Result
<
String
>
sendToUser
(
@RequestBody
Map
<
String
,
String
>
body
)
{
String
userId
=
body
.
get
(
"userId"
);
String
ticketNo
=
body
.
get
(
"ticketNo"
);
if
(
userId
==
null
||
ticketNo
==
null
)
return
Result
.
fail
(
"缺少 userId 或 ticketNo"
);
WebSocketMessage
response
=
WebSocketMessage
.
info
(
ticketNo
,
"这是一个测试消息,票号:"
+
ticketNo
);
sessionService
.
sendToUser
(
userId
,
response
);
// sessionService.sendVerificationSuccess(ticketNo,message);
return
Result
.
success
();
}
/**
* 测试接口:向指定用户发送票号核销消息
*/
...
...
@@ -39,9 +23,6 @@ public class WebSocketTestController {
String
message
=
body
.
get
(
"message"
);
String
ticketNo
=
body
.
get
(
"ticketNo"
);
if
(
message
==
null
||
ticketNo
==
null
)
return
Result
.
fail
(
"缺少 message 或 ticketNo"
);
// WebSocketMessage response = WebSocketMessage.info(ticketNo,
// "这是一个测试消息,票号:" + ticketNo);
// sessionService.sendToUser(userId, response);
sessionService
.
sendVerificationSuccess
(
ticketNo
,
message
);
return
Result
.
success
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment