You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Android与Spring Boot(Kotlin),如何连接Spring STOMP WebSocket?

解决Android连接Spring Boot STOMP+SockJS WebSocket的可行方案

你的后端采用了Spring的STOMP协议+SockJS封装,所以Android端需要适配STOMP协议(而非原生WebSocket)。下面提供三种经过验证的实现方案,覆盖不同技术栈偏好:


方案1:Spring官方STOMP客户端(最适配)

依赖Spring官方的Android STOMP客户端,与后端兼容性最好。

1. 添加依赖

在app/build.gradle.kts中引入:

implementation("org.springframework.android:spring-android-stomp-client:2.0.0.M3")
implementation("org.springframework:spring-messaging:6.0.11")
implementation("com.squareup.okhttp3:okhttp:4.11.0")

2. 连接与收发代码

import org.springframework.messaging.simp.stomp.*
import okhttp3.OkHttpClient
import java.lang.Exception
import java.lang.reflect.Type

class StompClientManager {
    private var stompSession: StompSession? = null
    private val okHttpClient = OkHttpClient()

    fun connect() {
        // 注意:SockJS的WebSocket端点需在原路径后加/websocket
        val wsUrl = "ws://10.0.2.2:8080/gs-guide-websocket/websocket"
        val stompHeaders = StompHeaders().apply {
            add(StompHeaders.ACCEPT_VERSION, "1.1,1.2")
        }

        val sessionHandler = object : StompSessionHandlerAdapter() {
            override fun afterConnected(session: StompSession, headers: StompHeaders) {
                stompSession = session
                // 订阅后端推送的消息
                session.subscribe("/topic/greetings", object : StompFrameHandler {
                    override fun getPayloadType(headers: StompHeaders): Type = String::class.java
                    override fun handleFrame(headers: StompHeaders, payload: Any?) {
                        val receivedMsg = payload as String
                        // 切换到主线程更新UI
                    }
                })
            }

            override fun handleTransportError(session: StompSession, exception: Throwable) {
                exception.printStackTrace()
                // 可在此实现重连逻辑
            }
        }

        val stompClient = DefaultStompSession(sessionHandler, stompHeaders)
        try {
            stompClient.connect(wsUrl, okHttpClient)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun sendMessage(content: String) {
        stompSession?.send("/app/hello", content)
    }

    fun disconnect() {
        stompSession?.disconnect()
        stompSession = null
    }
}

方案2:Scarlet(RxJava/Kotlin协程友好)

基于OkHttp的轻量级WebSocket客户端,支持STOMP协议,适合响应式编程场景。

1. 添加依赖

implementation("com.github.tinder.scarlet:scarlet:0.2.4")
implementation("com.github.tinder.scarlet:scarlet-stomp:0.2.4")
implementation("com.github.tinder.scarlet:scarlet-message-adapter-gson:0.2.4")
implementation("com.squareup.okhttp3:okhttp:4.11.0")

2. 定义STOMP接口与客户端

// 定义STOMP交互接口
interface ChatService {
    @Receive(topic = "/topic/greetings")
    fun observeGreetings(): Flowable<String>

    @Send(destination = "/app/hello")
    fun sendMessage(message: String)

    @Receive
    fun observeConnectionEvents(): Flowable<WebSocket.Event>
}

// 客户端实现
import com.tinder.scarlet.Scarlet
import com.tinder.scarlet.lifecycle.android.AndroidLifecycle
import com.tinder.scarlet.messageadapter.gson.GsonMessageAdapter
import com.tinder.scarlet.retry.LinearBackoffStrategy
import com.tinder.scarlet.stomp.StompMessageAdapter
import com.tinder.scarlet.websocket.okhttp.OkHttpWebSocket
import okhttp3.OkHttpClient
import okhttp3.Request
import androidx.lifecycle.LifecycleOwner

class ScarletStompClient(private val lifecycleOwner: LifecycleOwner) {
    private lateinit var chatService: ChatService
    private val okHttpClient = OkHttpClient()

    fun connect() {
        val wsUrl = "ws://10.0.2.2:8080/gs-guide-websocket/websocket"
        val request = Request.Builder().url(wsUrl).build()

        val scarlet = Scarlet.Builder()
            .webSocketFactory(OkHttpWebSocket.Factory(okHttpClient, request))
            .lifecycle(AndroidLifecycle.ofApplicationForeground(lifecycleOwner))
            .backoffStrategy(LinearBackoffStrategy(1000))
            .addMessageAdapterFactory(GsonMessageAdapter.Factory())
            .addMessageAdapterFactory(StompMessageAdapter.Factory())
            .build()

        chatService = scarlet.create()

        // 监听消息
        chatService.observeGreetings()
            .subscribe({ msg -> /* 更新UI */ }, { it.printStackTrace() })

        // 监听连接状态
        chatService.observeConnectionEvents()
            .subscribe({ event ->
                when (event) {
                    is WebSocket.Event.OnConnectionOpened<*> -> {} // 连接成功
                    is WebSocket.Event.OnConnectionClosed -> {} // 连接关闭
                    is WebSocket.Event.OnConnectionFailed -> {} // 连接失败
                }
            }, { it.printStackTrace() })
    }

    fun sendMessage(content: String) {
        chatService.sendMessage(content)
    }
}

方案3:Ktor客户端(Kotlin协程原生支持)

Ktor官方提供STOMP插件,适合纯Kotlin协程项目。

1. 添加依赖

implementation("io.ktor:ktor-client-android:2.3.3")
implementation("io.ktor:ktor-client-websockets:2.3.3")
implementation("io.ktor:ktor-client-stomp:2.3.3")

2. 连接与收发代码

import io.ktor.client.HttpClient
import io.ktor.client.plugins.websocket.webSocketSession
import io.ktor.client.plugins.stomp.*
import io.ktor.http.URLBuilder
import io.ktor.http.path
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class KtorStompClient {
    private val client = HttpClient {
        install(WebSockets)
        install(Stomp)
    }

    fun connect() {
        GlobalScope.launch(Dispatchers.IO) {
            val wsUrl = URLBuilder().apply {
                protocol = io.ktor.http.URLProtocol.WS
                host = "10.0.2.2"
                port = 8080
                path("/gs-guide-websocket/websocket")
            }.build()

            val session = client.webSocketSession(wsUrl)
            val stompSession = session.stomp()

            // 订阅消息
            stompSession.subscribe("/topic/greetings") { frame ->
                val msg = frame.payload.decodeToString()
                launch(Dispatchers.Main) { /* 更新UI */ }
            }

            // 发送消息方法
            fun sendMessage(content: String) {
                launch(Dispatchers.IO) {
                    stompSession.send("/app/hello", content.encodeToByteArray())
                }
            }
        }
    }
}

通用注意事项

  1. 网络权限:在AndroidManifest.xml中添加:
    <uses-permission android:name="android.permission.INTERNET" />
    
  2. 本地测试IP:Android模拟器访问电脑本地服务时,需用10.0.2.2代替localhost/127.0.0.1
  3. 后端验证:先用Postman等工具测试后端WebSocket端点是否正常响应,排除后端问题

内容的提问来源于stack exchange,提问作者Maurice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 07:05:20