春季:如何将SimpMessagingTemplate bean暴露给根上下文? [英] Spring : how to expose SimpMessagingTemplate bean to root context ?

查看:96
本文介绍了春季:如何将SimpMessagingTemplate bean暴露给根上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个以Spring为主要框架的Java Web应用程序(特别使用Spring核心,Spring mvc,Spring安全性,Spring数据,Spring Websocket).

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).

在这样的Spring上下文中声明message-broker可以为上下文提供SimpMessagingTemplate bean:

Declaring a message-broker in a Spring context like this provides a SimpMessagingTemplate bean to the context :

<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.

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).

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

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).

以前,<websocket:message-broker>标记位于applicationContext.xml中,并且dispatcher-servlet.xml正在导入applicationContext.xml,并且一切正常-但是,令我惊讶的是,最近我使用SessionRegistry进行操作时,这是错误的修改任意用户会话.

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.

的确,由于DispatcherServlet明确地导入了已经隐式继承的根上下文,所以SessionRegistry bean被创建了两次,导致了意外的行为(SO上有几篇文章描述了这个常见错误,通常用户希望获得所有主体的列表,但由于SessionRegistry bean重复而获得空列表,并对此进行查找.

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).

为解决此问题,我删除了

So to fix this I removed the

<import resource="applicationContext.xml"/>

来自dispatcher-servlet.xml,但此后:

from the dispatcher-servlet.xml, but since then :

  • 或者我将<websocket:messagebroker>...</>标记放在了dispatcher-servlet.xml中,在这种情况下,成功连接到了websocket,但是服务无法自动连接SimpMessagingTemplate
  • 或者我将<websocket:messagebroker>...</>标记放在applicationContext.xml中,在这种情况下,客户端无法连接到websocket.
  • (或者我回到以前的版本,其中DispatcherServlet导入ApplicationContext,这会破坏SessionRegistry-不行)
  • either I put the <websocket:messagebroker>...</> tag in the dispatcher-servlet.xml, in which case connections to websocket are successful but services cannot autowire SimpMessagingTemplate
  • or I put the <websocket:messagebroker>...</> tag in applicationContext.xml, in which case clients cannot connect to websocket.
  • (or I go back to the previous version, where DispatcherServlet imports ApplicationContext, which breaks SessionRegistry - nope)

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

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 ?

推荐答案

我发现了一个肮脏的解决方案.我不喜欢它,但是由于缺少SO的答案(另请参见: Dispatcher-servlet无法映射到websocket请求),以及来自现任和前任同事的信息,我都必须继续进行该项目并实施了一个肮脏的修复程序.

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.

肮脏的修补程序是对Controller和Scheduled类中的Autowire SimpMessagingTemplate(全部由dispatcher-servlet扫描,在其中声明了websocket tag的地方)进行扫描,并将SimpMessagingTemplate作为参数传递给服务方法(在root context中声明).

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).

此解决方案不是透明的(理想情况下,SimpMessagingTemplate应该直接自动连接到服务中),但肯定可以解决问题.

This solution is not transparent (the SimpMessagingTemplate should be autowired directly in services ideally) but it definitely fixes the problem.

这篇关于春季:如何将SimpMessagingTemplate bean暴露给根上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆