spring:如何将SimpMessagingTemplate bean暴露给根上下文?
问题内容:
我正在开发一个以Spring为主要框架的Java Web应用程序(特别使用Spring核心,Spring
mvc,Spring安全性,Spring数据,Spring websocket)。
message-broker
在这样的Spring上下文中声明a 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
并且一切正常-但是,令我惊讶的是,最近使用a
SessionRegistry
修改任意用户会话时,这是错误的。
确实,由于DispatcherServlet
明确地导入了已经隐式继承的根上下文,因此该SessionRegistry
bean被创建了两次,导致了意外的行为(SO上有几篇文章描述了这个常见错误,通常用户希望获得所有主体的列表但由于SessionRegistry
Bean复制而获得空列表,并对此进行查找)。
因此,要解决此问题,我删除了
<import resource="applicationContext.xml"/>
从dispatcher-servlet.xml开始,但是从那时起:
- 要么我将
<websocket:messagebroker>...</>
标签放在dispatcher-servlet.xml中,在这种情况下,到websocket的连接成功,但是服务无法自动装配SimpMessagingTemplate
- 或者我将
<websocket:messagebroker>...</>
标签放在中applicationContext.xml
,在这种情况下,客户端无法连接到websocket。 - (或者我回到以前的版本,在这里
DispatcherServlet
importApplicationContext
会中断SessionRegistry
-不)
解决这个可能相当普遍的问题的方法是什么?在DispatcherServlet
从根上下文可以访问bean而不是相反,所以我应该怎么来解决这一问题?
问题答案:
我找到了一个肮脏的解决方案。我不喜欢它,但是由于缺少SO的答案另请参见:Dispatcher-
servlet无法映射到websocket请求,以及现有和以前的同事,我都必须继续进行该项目并实施了一个肮脏的项目固定。
脏的解决方法是Autowire
将SimpMessagingTemplate
在控制器和预定类(全部由扫描dispatcher- servlet
中,在那里websocket tag
被声明),以及传递SimpMessagingTemplate
作为参数传递给服务方法(在声明root context
)。
该解决方案不是透明的(理想情况下SimpMessagingTemplate
应直接自动连接到服务中),但肯定可以解决该问题。