【问题标题】:Spring : how to expose SimpMessagingTemplate bean to root context ?Spring:如何将 SimpMessagingTemplate bean 公开给根上下文?
【发布时间】:2016-04-18 20:50:14
【问题描述】:

我正在开发一个以 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)。

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

确实,由于DispatcherServlet 显式导入了根上下文,该上下文已经隐式继承,SessionRegistry bean 被创建了两次,导致了意外行为(SO 上有几篇文章描述了这个常见错误,通常用户想要获得所有主体的列表,但由于SessionRegistry bean 重复而获得空列表并了解这一点)。

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

<import resource="applicationContext.xml"/>

来自 dispatcher-servlet.xml,但从那时起:

  • 要么我将&lt;websocket:messagebroker&gt;...&lt;/&gt; 标签放在dispatcher-servlet.xml 中,在这种情况下与websocket 的连接成功,但服务无法自动连接SimpMessagingTemplate
  • 或者我把&lt;websocket:messagebroker&gt;...&lt;/&gt;标签放在applicationContext.xml中,在这种情况下客户端无法连接到websocket。
  • (或者我回到以前的版本,DispatcherServlet 导入 ApplicationContext,这会破坏 SessionRegistry - 不)

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

【问题讨论】:

  • 我尝试将 applicationContext.xml 中的所有内容放入 dispatcher-servlet,但是 spring-security 不能使用在根上下文中声明的身份验证 bean,这基本上是同一个问题 :)

标签: xml spring spring-mvc websocket applicationcontext


【解决方案1】:

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

肮脏的修复是 Autowire SimpMessagingTemplate 在 Controller 和 Scheduled 类(都由 dispatcher-servlet 扫描,其中声明了 websocket tag),并将 SimpMessagingTemplate 作为参数传递给服务方法(在root context 中声明)。

此解决方案不透明(理想情况下,SimpMessagingTemplate 应该直接在服务中自动装配)但它确实解决了问题。

【讨论】:

  • 这很痛苦。我正在使用类似的解决方案:使用@PostConstruct,然后将其设置为 Service。
猜你喜欢
  • 2010-12-26
  • 2013-04-12
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多