2012-01-19 51 views
3

簡單地在GWT servlet中將字段標記爲@Autowired不能按預期工作。該代碼可以編譯和Web應用程序將啓動 - 這意味着春天是能夠成功地自動裝配領域,但是當servlet實際上是由客戶端代碼擊中,它會產生一個NullPointerException - 像有一個不同的,未初始化的副本該servlet被擊中。爲什麼不在Spring工作中自動裝配GWT servlet中的字段?

,我在網上找到了幾種方法來得到這個工作,一個是使用基礎的Servlet類,做了一些春天的邏輯,但這樣做意味着每個GWT Servlet必須擴展這個基類。另一種方法是使用AspectJ和Spring註釋。這裏涉及的配置很少,只是神奇的工作。

我的問題是,爲什麼不只是自動裝配如預期的領域只是工作? GWT這麼做會導致這種情況發生。

回答

0

事實證明,至少使用Spring的時候,有一個更簡單的做到這一點,這樣你可以使用@Autowired和它不涉及大規模的配置或基類的方法。需要注意的是,您還必須使用AspectJ。這裏有您需要爲您的GWT的servlet:

@Configurable 
public class MyGwtServiceImpl extends RemoteServiceServlet implements MyGwtService 
{ 
    @Autowired 
    private MyService service; 

    // ... 
} 

而在你的Spring配置確保你也有:

<!-- enable autowiring and configuration of non-spring managed classes, requires AspectJ --> 
    <context:spring-configured/> 

最後一個音符。如果您還在使用GWT應用程序(以及您的GWT servlet)中使用Spring安全性,則需要確保定義了正確的模式以確保AspectJ編織正確完成(即,您同時獲得@Secured註釋處理和@Autowired處理),你將需要:

<!-- turn on spring security for method annotations with @Secured(...) --> 
    <!-- the aspectj mode is required because we autowire spring services into GWT servlets and this 
     is also done via aspectj. a server 500 error will occur if this is changed or removed. --> 
    <security:global-method-security secured-annotations="enabled" mode="aspectj"/> 
4

的代碼可以編譯和Web應用程序將啓動 - 這意味着 春天是能夠成功地自動裝配領域

不一定。 Web容器可以在沒有任何Spring幫助的情況下實例化一個servlet。你可能會遇到:

但是當servlet實際上是由客戶端代碼擊中,它會產生 一個NullPointerException - 像有這個servlet的不同,未初始化 副本被擊中。

嘗試重寫Servlet的init():

@Override 
public void init(ServletConfig config) throws ServletException { 
    super.init(config); 

    WebApplicationContextUtils.getWebApplicationContext(config.getServletContext()) 
     .getAutowireCapableBeanFactory().autowireBean(this); 
} 
+0

當你在你的答案,春天的第一部分技術上是正確的,默認情況下,自動連接對待的要求,因此,將驗證它構建了一個註釋字段/方法可以匹配註釋項目的bean。如果沒有,它會炸燬,Web容器將無法啓動。 – icfantv

+0

此外,在答案的第二部分中,我在網絡上看到了這個解決方案,但是需要注意的是1)我需要創建一個父Servlet類來讓所有的GWT servlet類擴展,這是我期望避免的,以及2)這種模式混淆了異常處理,並且在拋出時阻止正確處理它們。在這裏看到作者的評論:http://blog.maxmatveev.com/2011/02/simple-spring-bean-autowiring-in-gwt.html,和他的解決方案 - 這是使用AspectJ。 – icfantv

+0

你*不需要*創建一個基類,每個servlet都可以爲自己覆蓋init():) – milan

1

當RPC服務從客戶端調用時,「服務器端」尋找被叫URL和servlet的映射將找到類,將生成實例並且它將滿足請求。這意味着如果您有註解,或者您已經在春季上下文中擁有RPC類的實例,則無關緊要。新實例將被創建,它不會「知道」Spring。

我通過實現一個擴展了RemoteServiceServlet並實現了Controller(來自Spring MVC)和ServletContextAware的類來解決此問題。 這樣你可以使用Spring MVC方法映射通過URL每個RPC服務,爲前:

<bean id="publicUrlMapping" 
     class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
     <property name="mappings"> 
      <props> 
      <prop key="/myFirstRpc">firstRpcServiceBeanRef</prop> 
      <prop key="/mySecondRpc">secondRpcServiceRef</prop> 
      </props> 
     </property> 
    </bean> 

也避免了聲明,在web.xml每一個RPC的servlet,映射是乾淨的,你有春天注入。 您在聲明爲web.xmlorg.springframework.web.servlet.DispatcherServlet一個映射,這將服務所有RPC調用。

有幾個有關GWT RPC和Spring MVC控制器集成解釋在網絡上的例子。

希望這會有所幫助。

+0

Ack!對不起。我沒有說清楚,我們沒有使用Spring MVC,只是Spring Web。考慮到我在網上找到的信息,即單控制器到規則他們所有的模式都覺得我真的錯了,因爲我們會吮吸整個框架組件,只使用一小塊。 – icfantv

+0

對我來說,Spring MVC的真正威力在於能夠創建任意數量的控制器,將功能組合在一起,將控制器方法綁定到URI,並在逐個方法的基礎上添加安全性 - 而且這一切都會自動發生,並且非常少編碼。 – icfantv

+0

我認爲你正在將dispacher-servlet與one-controller-to-rule-them-all混合在一起。這個servlet映射給出了控制器使用的URL的一般定義,如/ rpc/*。這是主意。如果你已經包含了像Spring Security這樣的框架,你仍然有可能在方法級別上實現安全性。 –

相關問題