Spring :如何将 SimpMessagingTemplate bean 公开到根上下文



我正在开发一个以Spring为主要框架的Java webapp(Spring core,Spring mvc,Spring security,Spring data,Spring websocket被特别使用)。

像这样在 Spring 上下文中声明message-broker为上下文提供了一个SimpMessagingTemplate bean:

<websocket:message-broker>
    <websocket:stomp-endpoint path="/stomp">
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic,/queue"/>
</websocket:message-broker>

我必须将此标签放在dispatcher-servlet.xml(而不是applicationContext.xml),否则客户端在尝试连接到 websocket 时(在初始页面加载时)将收到 404。

但是,由于提供SimpMessagingTemplate Bean(用于将消息发送到连接的客户端)的标记在根上下文中不可用,因此当服务(由根上下文扫描)发送 websocket 消息时,SimpMessagingTemplate Bean 无法自动连接(经典NoSuchBeanDefinitionException)。

以前,<websocket:message-broker> 标签在applicationContext.xml中,dispatcher-servlet.xml正在导入applicationContext.xml并且一切正常 - 但是当我最近使用SessionRegistry修改任意用户会话时,我惊讶地发现这是错误的。

事实上,由于DispatcherServlet显式导入了已经隐式继承的根上下文,因此SessionRegistry bean 被创建了两次,导致了意想不到的行为(SO 上有几个帖子描述了这个常见的错误,通常用户希望获得所有主体的列表,但由于 bean 复制SessionRegistry而获得空列表并了解这一点)。

所以为了解决这个问题,我删除了

<import resource="applicationContext.xml"/>

从调度程序-servlet.xml,但从那时起:

  • 要么我将<websocket:messagebroker>...</>标签放在调度程序-servlet 中.xml,在这种情况下,与 websocket 的连接成功,但服务无法自动连线SimpMessagingTemplate
  • 或者我把<websocket:messagebroker>...</>标签放在applicationContext.xml,在这种情况下,客户端无法连接到websocket。
  • (或者我回到以前的版本,DispatcherServlet导入ApplicationContext,这打破了SessionRegistry - 不)

这个可能相当普遍的问题的解决方案是什么?DispatcherServlet可以从根上下文访问 bean,但反之则不然,那么我应该如何解决这个问题呢?

我找到了一个肮脏的解决方案。我不喜欢它,但鉴于 SO 缺乏答案(另请参阅:Dispatcher-servlet 无法映射到 websocket 请求),以及现任和前任同事,我不得不继续该项目并实施一个肮脏的修复。

脏修复是Autowire控制器和调度类中的SimpMessagingTemplate(全部由声明websocket tagdispatcher-servlet扫描),并将SimpMessagingTemplate作为参数传递给服务方法(在root context中声明)。

此解决方案不透明(理想情况下,SimpMessagingTemplate应直接在服务中自动连接),但它绝对可以解决问题。

相关内容

  • 没有找到相关文章

最新更新