基于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()) } } } } }
通用注意事项
- 网络权限:在
AndroidManifest.xml中添加:<uses-permission android:name="android.permission.INTERNET" /> - 本地测试IP:Android模拟器访问电脑本地服务时,需用
10.0.2.2代替localhost/127.0.0.1 - 后端验证:先用Postman等工具测试后端WebSocket端点是否正常响应,排除后端问题
内容的提问来源于stack exchange,提问作者Maurice
相关产品推荐
相关产品推荐

