struts2如何跟spring整合的,原來是:struts2-spring-plugin.jar
在我們整合struts2+spring+hibernate,也就是所謂的S2SH,不可避免的要引入struts2-spring-plugin.jar外掛。當引入這個外掛後,原先所struts建立的action類,交給了spring建立。在struts2-spring-plugin.jar中有一個struts-plugin.xml,裡面聲明瞭action類由spring工廠建立。在struts2外掛文件裡,這樣寫著“The
Spring Plugin works by overriding the Struts ObjectFactory to enhance the creation of core framework objects
那時我有些不是很明白,為什麼我的action類沒有寫註解@Component("xxAction"),還是可以被spring自動裝配。那是因為action類被struts和struts2-spring-plugin建立,再由spring自動裝配,但不由spring管理。如果我們想使用spring複雜的aop或spring其他的功能時,強烈建議將acion類註冊到spring容器中
今天,再次做測試,又有了出乎意料的結果。在此說明,我的測試中用的是annotion註解,不是xml檔案。
之前,我們說過,當建立一個action類時,它會根據struts的配置檔案的class屬性的值與spring配置檔案中的id屬性的值相匹配。如果沒有與之相匹配,將會像沒有使用這個外掛前一樣建立,然後由spring自動裝配。這兩種情況會出現不同的結果。現在我們慢慢來說明。
假設我們有一個AddUserAction的類,位於com.action包下,它有屬性userService:
package com.action;
import com.opensymphony.xwork2.ActionSupport;
import com.service.UserService;
public class AddUserAction extends ActionSupport {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public String execute() throws Exception {
System.out.println(userService==null);
return SUCCESS;
}
}
以上這個類是我們最簡單的action類,在沒有引入struts2-spring-plugin.jar外掛時,action類是由struts建立的,我們struts.xml檔案是這樣寫的:
<struts>
<package name="registration" extends="struts-default">
<action name="addUser" class="com.action.AddUserAction">
<result>success.jsp</result>
</action>
</package>
</struts>
但如果我們引入struts2-spring-plugin.jar外掛後,如果我們的struts.xml檔案還是如同以上一樣寫,就會出現struts的配置檔案的class屬性的值與spring配置檔案中的id屬性的值不匹配,因為action類沒有註冊到spring的容器中。那action的建立由strutst和struts2-spring-plugin.jar外掛建立,預設地根據名字到spring容器中去找相應的物件進行自動裝配(不管你是否願意,只要提供了set方法),所以userService不會是null值,這個action類的scope也預設的是prototype,但這個action類不在spring容器中。
自然的,以上這種情況不是我們想要的,因為很多情況都不在我們的控制範圍內。那隻要我們將action類的建立交給spring,就可以自主也配置我們想要的屬性。這時我們將原來的action類改為:
package com.action;
mport javax.annotation.Resource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.opensymphony.xwork2.ActionSupport;
import com.service.UserService;
@Component("addUserAction")
@Scope("prototype")
public class AddUserAction extends ActionSupport {
private UserService userService;
@Resource(name="userService")
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public String execute() throws Exception {
System.out.println(userService==null);
return SUCCESS;
}
}
在第二個action類中,我們加入了相應的annotion,把我們的action類註冊到spring容器中。我們的struts.xml檔案也改為:
<struts>
<package name="registration" extends="struts-default">
<action name="addUser" class="addUserAction">
<result>success.jsp</result>
</action>
</package>
</struts>
這時,struts的配置檔案的class屬性的值與spring配置檔案中的id屬性的值匹配。如果我們不想裝配userService,可以將@Resource(name="userService")刪除。
所以,在struts.xml裡的class的屬性值決定你以那種方式建立action類,我個人傾向於將action類交給spring管理和自動裝配。
如果有什麼不正確的地方,歡迎大家指出。 小結: 1 @Component("addUserAction")和@Controller效果是一樣的,可換成@Controller,因為@Controller被spring自動裝配為“addUserAction”; 2 @Resource(name="userService") public void setUserService(UserService userService) {this.userService = userService;
} @Resource(name="userService")加上set()方法和 @Resource privateUserService userService ;是一樣的效果,@Resource被spring自動裝配為(name="userService")