說說項目架構整個變化過程吧web
拿用戶註冊來舉例:spring
數據庫裏面有一張User表數據庫
須要把註冊信息存儲到User表中apache
1. 最開始是兩層架構網絡
就是cliect + jsp + DB架構
就是在view裏面直接操做數據庫,就是在視圖上創建數據庫鏈接,而後把每一個字段存儲到數據庫中app
2. 加入Domain Modeljsp
構造一個Entity類測試
cliect + jsp + Entity + DBui
對Entity的管理交給Jsp
創建一個User類,view中先對User進行實例化,而後再進行存儲
這一步沒有什麼意義
3. 加入管理層
cliect + jsp + Entity + Service + DB
把對User的管理交給Service層
管理層,也就是業務邏輯層
4. 加入Hibernate
使用Hibernate對數據庫進行操做
這種作法是在項目中引入了Hibernate
Hibernate的做用是把數據插入到數據庫中。
可是,
若是要跨數據庫呢
若是要把數據存儲到Xml文件中或者網絡上呢而不須要數據庫呢
因此UserManage對User的存儲就不能寫死成了Hibernate或者JDBC或者xml
因此要引入DAO層
5. 加入DAO層
cliect + jsp + UserManage + UserManageImpl+ User+ +UserDAO + UserDAOimpl + DB
把對數據的存儲操做抽象成一個接口,這個接口裏面定義增刪改查的方法,而後有不一樣的實現類,實現不一樣的存儲方式
能夠把業務邏輯類也抽象出來,不過這種作法並很少
6. 加入Struct
也就是引入MVC
Controller就是Struct的filter
Action先執行業務邏輯,而後根據配置的view在,返回結果
M是由兩層構成的,bussinuiss layer和DAO layer
7. 加入spring
spring實際上是貫穿於整個過程的
在抽象須要實例化的地方用spring的IOC
在各個業務處理的時候能夠用spring的AOP
在這裏面,UserManage拿userDAO的時候使用的是注入(必須給他一個實現類)
Action用UserManage的時候也是注入
因此
spring和struct2結合的主要地方是Action
實際上,spring是struct的一個插件
在struct的文檔插件一節能夠看到spring插件
因此,spring纔是主導,struct向spring要須要的Action。(即要的時候向插件來要)
8. 配置
要加入spring
web.xml中要有監聽器,在application啓動的時候,找到bean所對應的xml的文件,並初始化全部的bean
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> <!-- default: /WEB-INF/applicationContext.xml --> </listener>
默認尋找的路徑是 WEB-INF/applicationContext.xml
若是改了路徑或者改了名稱,須要配置
<context-param> <param-name>contextConfigLocation</param-name> <!-- <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value> --> <param-value>classpath:beans.xml</param-value> </context-param>
classpath 表示是在src文件夾下
*的意思是可能配置文件有多個,好比不一樣的業務配置不一樣的文件,這裏一會兒讀進來
這樣,在啓動的時候就啓動了spring容器
Action和spring的關係能夠有兩種方式
1. Action交給spring容器管理
把Action配到spring中去
加入struct2-spring-plugin.jar包
而後找到相應的Action,加上@Compont和@Resource,這樣就交給了spring管理
@Component("u") @Scope("prototype") public class UserAction extends ActionSupport implements ModelDriven {
private UserManager userManager;
......
@Resource
public void setUserManager(UserManager userManager) {
this.userManager = userManager;
}
}
<package name="registration" extends="struts-default"> <action name="u" class="u"> <result name="success">/registerSuccess.jsp</result> <result name="fail">/registerFail.jsp</result> </action> </package>
這裏面Action上的component值必須和struct.xml中的action的class相同
同時還加上@Scope("prototype") 非單例模式
action交給spring管理,spring的bean默認是單例模式,
可是strct每次收到一個請求,都要創建一個ActionContext,ValueStack,Action,而後把action放進valuestack
若是定義成單例顯示不符
可是若是在action中不涉及成員變量的讀寫操做,能夠用單例,稍微提升點效率
struct2-spring-plugin.jar這個jar包裏有一個文件struct-plugin.xml:
<struts> <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" /> <!-- Make the Spring object factory the automatic default --> <constant name="struts.objectFactory" value="spring" /> ....... </structs>
有一個name=spring的bean是一個springFactory
通常狀況下,Struct須要一個Action的時候,會去找本身的StructFactory,可是在執行上面後,會去找spring拿,而springFactory會自動找到配置文件
好比struct中Action的name爲User
它會根據這個名稱到spring容器中找到name爲User的bean
Struct啓動時,讀取文件de順序
而spring啓動是在web.xml中,也就是說應用啓動時,spring容器就已經初始化了,當struct須要時,直接去容器中拿。
2.Action由struct容器管理
這種作法是Action上什麼也不用加,action對象的產生是放在struct容器中的,不禁spring管理
public class UserAction extends ActionSupport implements ModelDriven { private UserManager userManager; ......... public void setUserManager(UserManager userManager) { this.userManager = userManager; } }
<struts> <package name="registration" extends="struts-default"> <action name="u" class="com.bjsxt.registration.action.UserAction"> <result name="success">/registerSuccess.jsp</result> <result name="fail">/registerFail.jsp</result> </action> </package> </struts>
就是在Action上什麼標記也不加,那麼Action就會在struct容器裏
可是service和DAO改加仍是要加,仍是要放在spring容器裏面
那麼在struct容器裏產生的時候,會自動到spring容器裏找須要注入的東西,固然因爲什麼標記都沒加,就是ByName找的
那若是想匹配指定的name怎麼辦呢,就不須要寫set方法了,直接在Action的屬性上加
public class UserAction extends ActionSupport implements ModelDriven { @Resource(「u」); private UserManager userManager; ......... }
固然,第一種方法比較好測試