【发布时间】: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)。
以前,<websocket:message-broker> 标记位于 applicationContext.xml 中,而 dispatcher-servlet.xml 正在导入 applicationContext.xml 并且一切正常 - 但是当我最近使用 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导入ApplicationContext,这会破坏SessionRegistry- 不)
这个可能相当普遍的问题的解决方案是什么? DispatcherServlet 可以从根上下文访问 bean,但反之则不行,那么我应该如何解决这个问题?
【问题讨论】:
-
我尝试将 applicationContext.xml 中的所有内容放入 dispatcher-servlet,但是 spring-security 不能使用在根上下文中声明的身份验证 bean,这基本上是同一个问题 :)
标签: xml spring spring-mvc websocket applicationcontext