[英]Spring : how to expose SimpMessagingTemplate bean to root context ?
I'm developing a Java webapp with Spring as the main framework (Spring core, Spring mvc, Spring security, Spring data, Spring websocket are notably used). 我正在开发一个以Web为主框架的Java webapp(Spring核心,Spring mvc,Spring安全,Spring数据,Spring websocket特别使用)。
Declaring a message-broker
in a Spring context like this provides a SimpMessagingTemplate
bean to the context : 在这样的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>
I have to put this tag in dispatcher-servlet.xml
(not applicationContext.xml
), otherwise clients will get a 404 when trying to connect to the websocket (on initial page load). 我必须将此标记放在dispatcher-servlet.xml
(而不是applicationContext.xml
)中,否则客户端在尝试连接到websocket时会获得404(在初始页面加载时)。
However, since this tag which provides the SimpMessagingTemplate
bean (to send messages to connected clients) is not available in the root context, when a service (scanned by the root context) sends a websocket message, the SimpMessagingTemplate
bean cannot be autowired (classical NoSuchBeanDefinitionException
). 但是,由于此提供SimpMessagingTemplate
bean的标记(向连接的客户端发送消息)在根上下文中不可用,因此当服务(由根上下文扫描)发送websocket消息时, SimpMessagingTemplate
bean无法自动装配(经典NoSuchBeanDefinitionException
)。
Previously, the <websocket:message-broker>
tag was in applicationContext.xml
and dispatcher-servlet.xml
was importing applicationContext.xml
and everything was working fine - however I found out to my surprise that this was wrong when I recently used a SessionRegistry
to modify arbitrary user sessions. 以前, <websocket:message-broker>
标签位于applicationContext.xml
而dispatcher-servlet.xml
正在导入applicationContext.xml
,一切正常 - 但是当我最近使用SessionRegistry
时,我发现这是错误的SessionRegistry
修改任意用户会话。
Indeed, since the DispatcherServlet
was explicitely importing the root context, which is already inherited implicitely, the SessionRegistry
bean was created twice, leading to unexpected behaviours (there are several posts on SO that depict this common mistake, usually users want to get a list of all principals but get empty lists due to the SessionRegistry
bean duplication and find out about this). 实际上,由于DispatcherServlet
明确地导入了已经隐含继承的根上下文,因此SessionRegistry
bean被创建了两次,导致意外的行为(SO上有几个帖子描述了这个常见的错误,通常用户希望得到一个列表所有主体但由于SessionRegistry
bean重复而获得空列表并找到相关信息。
So to fix this I removed the 所以为了解决这个问题,我删除了
<import resource="applicationContext.xml"/>
from the dispatcher-servlet.xml, but since then : 来自dispatcher-servlet.xml,但从那时起:
<websocket:messagebroker>...</>
tag in the dispatcher-servlet.xml, in which case connections to websocket are successful but services cannot autowire SimpMessagingTemplate
或者我将<websocket:messagebroker>...</>
标记放在dispatcher-servlet.xml中,在这种情况下,与websocket的连接成功但服务无法自动装配SimpMessagingTemplate
<websocket:messagebroker>...</>
tag in applicationContext.xml
, in which case clients cannot connect to websocket. 或者我在applicationContext.xml
放置了<websocket:messagebroker>...</>
标记,在这种情况下,客户端无法连接到websocket。 DispatcherServlet
imports ApplicationContext
, which breaks SessionRegistry
- nope) (或者我回到之前的版本,其中DispatcherServlet
导入ApplicationContext
,它打破了SessionRegistry
- SessionRegistry
) What is the solution to this probably rather common problem ? 这可能是一个相当常见的问题的解决方案是什么? The DispatcherServlet
can access beans from the root context but not vice-versa, so how should I work this out ? DispatcherServlet
可以从根上下文访问bean,反之则不然,所以我应该如何处理?
I found a dirty solution. 我发现了一个肮脏的解 I don't like it, but given the lack of answers on SO (see also : Dispatcher-servlet cannot map to websocket requests ), as well as from current and former colleagues, I had to go forward with the project and implemented a dirty fix. 我不喜欢它,但鉴于SO上缺少答案(另请参阅: Dispatcher-servlet无法映射到websocket请求 ),以及当前和以前的同事,我不得不继续进行项目并实施一个脏的固定。
The dirty fix is to Autowire
the SimpMessagingTemplate
in Controller and Scheduled classes (all scanned by the dispatcher-servlet
, where the websocket tag
is declared), and to pass the SimpMessagingTemplate
as a parameter to service methods (declared in the root context
). 脏的解决方法是Autowire
的SimpMessagingTemplate
在控制器和预定类(全部由扫描dispatcher-servlet
,其中所述websocket tag
被声明),以及传递SimpMessagingTemplate
作为参数传递给服务方法(在声明root context
)。
This solution is not transparent (the SimpMessagingTemplate
should be autowired directly in services ideally) but it definitely fixes the problem. 这个解决方案不透明( SimpMessagingTemplate
应该直接在服务中直接自动装配),但它肯定能解决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.