如何在Spring Websocket中为@Header值创建自定义转换器/反序列化器
解决方案
方法一:注册自定义转换器(推荐)
- 第一步:实现字符串到Context的转换器,假设你Header中传的context是JSON序列化字符串,示例代码如下:
import org.springframework.core.convert.converter.Converter import com.fasterxml.jackson.databind.ObjectMapper import com.barbarus.gameserver.websocket.Context class StringToContextConverter(private val objectMapper: ObjectMapper) : Converter<String, Context> { override fun convert(source: String): Context { return objectMapper.readValue(source, Context::class.java) } }
注意:如果你的Context是Kotlin数据类,需要引入jackson-datatype-kotlin依赖并给ObjectMapper注册Kotlin模块,避免反序列化无参构造报错
对应的ObjectMapper配置示例:
import com.fasterxml.jackson.module.kotlin.KotlinModule import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class JacksonConfig { @Bean fun objectMapper(): ObjectMapper { return ObjectMapper() .registerModule(KotlinModule()) } }
- 第二步:将转换器注册到WebSocket Messaging的参数解析器中,在你已有的
@EnableWebSocketMessageBroker配置类中添加如下配置:
import org.springframework.core.convert.support.DefaultConversionService import org.springframework.messaging.handler.annotation.support.HeaderMethodArgumentResolver import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer @Configuration @EnableWebSocketMessageBroker class WebSocketConfig( private val stringToContextConverter: StringToContextConverter ) : WebSocketMessageBrokerConfigurer { override fun addArgumentResolvers(resolvers: MutableList<HandlerMethodArgumentResolver>) { val conversionService = DefaultConversionService() conversionService.addConverter(stringToContextConverter) resolvers.add(HeaderMethodArgumentResolver(conversionService, null)) } // 保留你原有WebSocket的其他配置,比如端点注册、消息代理配置等 }
配置完成后重启服务即可正常通过@Header context: Context直接注入转换后的对象。
方法二:临时手动转换(快速验证用)
如果不想额外配置转换器,可以先将Header以字符串形式接收,再手动反序列化:
@MessageMapping("/gather/{resource}") fun emitGatherEvent( @DestinationVariable resource: String, @Header context: String, private val objectMapper: ObjectMapper ) { val contextObj = objectMapper.readValue(context, Context::class.java) LOG.debug("gather endpoint called for client ${contextObj.clientId} and character ${contextObj.characterId} with resource '$resource'") eventDispatcher.dispatchEvent(Gather(resource), contextObj.characterId) }
内容的提问来源于stack exchange,提问作者xetra11
相关产品推荐
相关产品推荐

