在我的 Spring 项目中,我确实有一个由 spring 管理的 JMS 消息监听器:
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616"/>
<bean id="simpleExampleListener" class="my.package.ExampleListener" />
<jms:listener-container container-type="default" connection-factory="jmsFactory" acknowledge="auto" concurrency="1-3">
<jms:listener destination="TEST.FOO" ref="simpleExampleListener" method="onMessage"/>
</jms:listener-container>
对于一条特定消息,我需要调用 Spring MVC Controller ,该 Controller 是请求范围的(实际上目标是调用服务,该服务也是请求范围的并由 Controller 调用)。因此,我无法直接从监听器执行此操作,因为 Spring 根据需要管理它们,并且它们不受请求范围限制(因此我无法通过 @Autowire
或 ApplicationContext
访问 Controller )。解决方案之一可能是使用 Rest Template 到 URL 的 HTTP 调用,由我的 Controller 映射。但是,我认为,这是一种开销,所以也许还有其他方法可以避免 HTTP 协议(protocol)开销并在 Spring MVC 框架内调用 Controller?
最佳答案
您需要质疑为什么服务类被定义为请求范围 - 理想情况下,服务层不应该对 Web 层有任何隐式/显式依赖。如果这不在您的控制范围内,您可以使用以下解决方法。您需要添加 spring-test.jar 作为依赖项。
class Listener {
@Autowired
RequestScopedService requestScopedService;
void handle() {
MockHttpServletRequest request = new MockHttpServletRequest();
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
try {
requestScopedService.callSomeMethod();
} finally {
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).requestCompleted();
RequestContextHolder.resetRequestAttributes();
}
如果服务bean配置为<aop:scoped-proxy/>
标记然后它可以 Autowiring 。否则,您需要获取应用程序上下文(通过实现 ApplicationContextAware)并进行查找。
关于spring - 如何在框架内调用Spring MVC Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10555161/