Spring:如何将SimpMessagingTemplate bean暴露给root上下文?

时间:2016-01-13 18:18:57

标签: xml spring spring-mvc websocket applicationcontext

我正在开发一个以Web为主框架的Java webapp(Spring核心,Spring mvc,Spring安全,Spring数据,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消息时,{ {1}} bean无法自动装配(经典SimpMessagingTemplate)。

以前,NoSuchBeanDefinitionException标记位于<websocket:message-broker>applicationContext.xml正在导入dispatcher-servlet.xml,一切正常 - 但我发现这是错误的我最近使用applicationContext.xml来修改任意用户会话。

实际上,由于SessionRegistry明确地导入了已经隐含继承的根上下文,因此DispatcherServlet bean被创建了两次,导致意外行为(SO上有几个帖子描述了这一点)常见的错误,通常用户希望获得所有主体的列表,但由于SessionRegistry bean重复而得到空列表,并找出相关信息。

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

SessionRegistry
来自dispatcher-servlet.xml的

,但从那时起:

  • 我将<import resource="applicationContext.xml"/> 标记放在dispatcher-servlet.xml中,在这种情况下,与websocket的连接成功但服务无法自动装配<websocket:messagebroker>...</>
  • 或者我将SimpMessagingTemplate标记放在<websocket:messagebroker>...</>中,在这种情况下,客户端无法连接到websocket。
  • (或者我回到之前的版本,其中applicationContext.xml导入DispatcherServlet,这会打破ApplicationContext - nope

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

1 个答案:

答案 0 :(得分:0)

我找到了一个肮脏的解决方案。我不喜欢它,但由于缺乏SO的答案(另见:Dispatcher-servlet cannot map to websocket requests),以及现任和前任同事,我不得不继续进行项目并实施一个肮脏的修复。

脏修复是Autowire控制器和预定类中的SimpMessagingTemplate(全部由dispatcher-servlet扫描,其中websocket tag已声明),并通过SimpMessagingTemplate作为服务方法的参数(在root context中声明)。

此解决方案不透明(理想情况下SimpMessagingTemplate应直接在服务中自动连接)但它肯定能解决问题。