写在最前:在项目中发现前端在连接后端服务器websocket时,使用127.0.0.1IP访问一切正常,到生产环境指定IP后突然报错:
报错1:
Uncaught Error: Incompatibile SockJS! Main site uses: “1.6.1”, the
iframe: “1.0.0”.
报错2:
GET http://192.168.1.22:8088/ws/751/pl2birne/jsonp?c=_jp.aaxo0yy
net::ERR_ABORTED 404 (Not Found)
使用的boot版本:
org.springframework.boot
spring-boot-starter-websocket
2.2.4.RELEASE
使用的websocket配置:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig
implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 启用简单的消息代理,前缀为/topic的消息会发送到消息代理
config.enableSimpleBroker("/topic");
// 应用程序以/app为前缀的消息会路由到@MessageMapping注解的方法
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册STOMP端点,客户端将使用它连接到WebSocket服务器
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
}
使用的前端连接socket代码:
import {
Client
} from '@stomp/stompjs'
import SockJS from 'sockjs-client'
const createWebSocketClient = () =>
{
let client = null
const subscriptions = new Map()
const wsBaseUrl = window.SITE_CONFIG.baseUrl
const wsEndpoint = '/ws'
let messageListeners = []
const connect = () =>
{
return new Promise((resolve, reject) =>
{
if (client && client.connected) {
resolve()
return
}
client = new Client({
webSocketFactory: () =>
new SockJS(`${wsBaseUrl
}${wsEndpoint
}`),
debug: (str) => console.debug('[WebSocket]', str),
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
onConnect: () =>
{
console.log('[WebSocket] Connected successfully')
notifyListeners('connected')
resolve()
},
onStompError: (frame) =>
{
console.error('[WebSocket] Connection error:', frame.headers.message)
notifyListeners('error', frame.headers.message)
reject(new Error(frame.headers.message || 'Connection failed'))
},
onDisconnect: () =>
{
console.log('[WebSocket] Disconnected')
notifyListeners('disconnected')
},
onWebSocketError: (error) =>
{
console.error('[WebSocket] WebSocket error:', error)
notifyListeners('error', error.message)
},
onWebSocketClose: (event) =>
{
console.log('[WebSocket] WebSocket closed:', event)
notifyListeners('closed', event)
}
})
client.activate()
})
}
const subscribe = (destination, callback) =>
{
if (!client || !client.connected) {
console.error('[WebSocket] Cannot subscribe - not connected')
return null
}
const subscription = client.subscribe(destination, (message) =>
{
console.log(`[WebSocket] Received message on ${destination
}:`, message.body)
callback(message.body)
notifyListeners('message', {
destination,
body: message.body
})
})
subscriptions.set(destination, subscription)
return subscription
}
const disconnect = () =>
{
if (client) {
subscriptions.forEach(sub => sub.unsubscribe())
subscriptions.clear()
client.deactivate()
console.log('[WebSocket] Disconnected')
}
}
const addMessageListener = (callback) =>
{
messageListeners.push(callback)
return () =>
{
messageListeners = messageListeners.filter(listener => listener !== callback)
}
}
const notifyListeners = (event, data) =>
{
messageListeners.forEach(listener =>
listener(event, data))
}
return {
connect,
subscribe,
disconnect,
addMessageListener,
subscribeUsersChanged: (callback) =>
subscribe('/topic/xxx-topic', callback)
}
}
// 导出单例实例
export const webSocketClient = createWebSocketClient()
sockjs-client版本为:^1.6.1
好,如果使用以上配置时线下调试用127.0.0.1完全没问题,放到线上不是跨域就是请求/ws接口404,甚至偶尔又能请求成功,想到/ws前缀后端全放行无权限问题但就是死活报错,结果查阅大量资料后都说把setAllowedOrigins换成setAllowedOriginPatterns方法,但目前项目用的springboot版本2.2.4还没有此方法,无奈升级springboot版本到2.4.9使用setAllowedOriginPatterns方法后一下就好了。。。无语大坑,记录一下!