2012-05-11 64 views
2

在我的Spring項目,我有一個JMS消息監聽器,由Spring管理:如何在Framework中調用Spring MVC控制器?

<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調用)。所以我不能直接從監聽器那裏做,因爲Spring根據需要管理它們,它們不是請求範圍的限制(因爲我無法通過@AutowireApplicationContext訪問控制器)。其中一個解決方案可能是一個HTTP調用,其餘的模板爲URL,由我的控制器進行映射。但是,我認爲,它的一種開銷,所以也許有其他方法可以避免HTTP協議開銷並在Spring MVC框架內調用Controller?

+0

你可以使用原型範圍,而不是請求範圍? – skaffman

+0

如果您確實至少使用了與Web應用程序代碼鬆散耦合的Http調用。直接打電話給控制器是非常醜陋的。 –

+0

你能解釋一下**爲什麼你想從消息監聽器調用一個控制器?我想不出任何用例... –

回答

2

您需要質疑爲什麼將服務類定義爲請求範圍 - 理想情況下,服務層不應該在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/>標籤,那麼它可以是自動裝配的。否則,您需要獲取應用程序上下文(通過實現ApplicationContextAware)並執行查找。