1. 程式人生 > >【javaWeb】第61天——Struts框架的第2天

【javaWeb】第61天——Struts框架的第2天

Struts2的第二天


課程回顧:Struts2框架第一天

1. Struts2框架的概述,前端控制器的模式,核心的過濾器
2. 入門,編寫struts.xml配置檔案
3. 配置檔案
	* 配置檔案的載入
4. Action類的編寫和訪問

Struts2的第二天的內容

1. Struts2框架中的Servlet的API的使用
2. Struts2中Action接收請求引數
3. Struts2中自定義攔截器

案例一:使用Struts2作為WEB層完成客戶的新增功能


需求分析

1. 原來是使用Servlet作為WEB層框架,現在需要使用Struts2作為WEB層完成客戶的新增功能

技術分析之在Struts2框架中使用Servlet的API

1. 在Action類中也可以獲取到Servlet一些常用的API
	* 需求:提供JSP的表單頁面的資料,在Action中使用Servlet的API接收到,然後儲存到三個域物件中,最後再顯示到JSP的頁面上。
		* 提供JSP註冊的頁面,演示下面這三種方式
			<h3>註冊頁面</h3>
			<form action="${ pageContext.request.contextPath }/xxx.action" method="post">
				姓名:<input type="text" name="username" /><br/>
				密碼:<input type="password" name="password" /><br/>
				<input type="submit" value="註冊" />
			</form>

2. 完全解耦合的方式
	* 如果使用該種方式,Struts2框架中提供了一個類,ActionContext類,該類中提供一些方法,通過方法獲取Servlet的API
	* 一些常用的方法如下
		* static ActionContext getContext()  										-- 獲取ActionContext物件例項
		* java.util.Map<java.lang.String,java.lang.Object> getParameters()  		-- 獲取請求引數,相當於request.getParameterMap();
		* java.util.Map<java.lang.String,java.lang.Object> getSession()  			-- 獲取的代表session域的Map集合,就相當於操作session域。
		* java.util.Map<java.lang.String,java.lang.Object> getApplication() 		-- 獲取代表application域的Map集合
		* void put(java.lang.String key, java.lang.Object value)  					-- 注意:向request域中存入值。

3. 使用原生Servlet的API的方式
	* Struts2框架提供了一個類,ServletActionContext,該類中提供了一些靜態的方法
	* 具體的方法如下
		* getPageContext()
		* getRequest()
		* getResponse()
		* getServletContext()

技術分析之結果頁面的跳轉

1. 結果頁面存在兩種方式
	* 全域性結果頁面
		> 條件:如果<package>包中的一些action都返回success,並且返回的頁面都是同一個JSP頁面,這樣就可以配置全域性的結果頁面。
		> 全域性結果頁面針對的當前的包中的所有的Action,但是如果區域性還有結果頁面,會優先區域性的。使用的標籤是
			<global-results>
				<result>/demo3/suc.jsp</result>
			</global-results>
	
	* 區域性結果頁面
		<result>/demo3/suc.jsp</result>

2. 結果頁面的型別
	* 結果頁面使用<result>標籤進行配置,包含兩個屬性
		> name	-- 邏輯檢視的名稱
		> type	-- 跳轉的型別,值一些,需要掌握一些常用的型別。常見的結果型別去struts-default.xml中查詢。
			* dispatcher		-- 轉發.type的預設值.Action--->JSP
			* redirect			-- 重定向.	Action--->JSP
			* chain				-- 多個action之間跳轉.從一個Action轉發到另一個Action.	Action---Action
			* redirectAction	-- 多個action之間跳轉.從一個Action重定向到另一個Action.	Action---Action
			* stream			-- 檔案下載時候使用的

技術分析之Struts2框架的資料封裝

1. 為什麼要使用資料的封裝呢?
	* 作為MVC框架,必須要負責解析HTTP請求引數,並將其封裝到Model物件中
	* 封裝資料為開發提供了很多方便
	* Struts2框架提供了很強大的資料封裝的功能,不再需要使用Servlet的API完成手動封裝了!!

2. Struts2中提供了兩類資料封裝的方式?
	* 第一種方式:屬性驅動
		> 提供對應屬性的set方法進行資料的封裝。
			* 表單的哪些屬性需要封裝資料,那麼在對應的Action類中提供該屬性的set方法即可。
			* 表單中的資料提交,最終找到Action類中的setXxx的方法,最後賦值給全域性變數。
			
			* 注意0:Struts2的框架採用的攔截器完成資料的封裝。
			* 注意1:這種方式不是特別好:因為屬性特別多,提供特別多的set方法,而且還需要手動將資料存入到物件中.
			* 注意2:這種情況下,Action類就相當於一個JavaBean,就沒有體現出MVC的思想,Action類又封裝資料,又接收請求處理,耦合性較高。
		
		> 在頁面上,使用OGNL表示式進行資料封裝。
			* 在頁面中使用OGNL表示式進行資料的封裝,就可以直接把屬性封裝到某一個JavaBean的物件中。
			* 在頁面中定義一個JavaBean,並且提供set方法:例如:private User user;
			* 頁面中的編寫發生了變化,需要使用OGNL的方式,表單中的寫法:<input type="text" name="user.username">
			
			* 注意:只提供一個set方法還不夠,必須還需要提供user屬性的get和set方法!!!
				> 先呼叫get方法,判斷一下是否有user物件的例項物件,如果沒有,呼叫set方法把攔截器建立的物件注入進來,
	
	* 第二種方式:模型驅動
		> 使用模型驅動的方式,也可以把表單中的資料直接封裝到一個JavaBean的物件中,並且表單的寫法和之前的寫法沒有區別!
		> 編寫的頁面不需要任何變化,正常編寫name屬性的值
		> 模型驅動的編寫步驟:
			* 手動例項化JavaBean,即:private User user = new User();
			* 必須實現ModelDriven<T>介面,實現getModel()的方法,在getModel()方法中返回user即可!!

技術分析之Struts2把資料封裝到集合中

1. 封裝複雜型別的引數(集合型別 Collection 、Map介面等)
2. 需求:頁面中有可能想批量新增一些資料,那麼現在就可以使用上述的技術了。把資料封裝到集合中
3. 把資料封裝到Collection中
	* 因為Collection介面都會有下標值,所有頁面的寫法會有一些區別,注意:
		> <input type="text" name="products[0].name" />
	* 在Action中的寫法,需要提供products的集合,並且提供get和set方法。

4. 把資料封裝到Map中
	* Map集合是鍵值對的形式,頁面的寫法
		> <input type="text" name="map['one'].name" />
	* Action中提供map集合,並且提供get和set方法

案例:新增客戶

1. 功能

案例總結之Struts2的攔截器技術

1. 攔截器的概述
	* 攔截器就是AOP(Aspect-Oriented Programming)的一種實現。(AOP是指用於在某個方法或欄位被訪問之前,進行攔截然後在之前或之後加入某些操作。)
	* 過濾器:過濾從客服端傳送到伺服器端請求的
	
	* 攔截器:攔截對目標Action中的某些方法進行攔截
		* 攔截器不能攔截JSP
		* 攔截到Action中某些方法

2. 攔截器和過濾器的區別
	1)攔截器是基於JAVA反射機制的,而過濾器是基於函式回撥的
	2)過濾器依賴於Servlet容器,而攔截器不依賴於Servlet容器
	3)攔截器只能對Action請求起作用(Action中的方法),而過濾器可以對幾乎所有的請求起作用(CSS JSP JS)
	
	* 攔截器 採用 責任鏈 模式
		> 在責任鏈模式裡,很多物件由每一個物件對其下家的引用而連線起來形成一條鏈
		> 責任鏈每一個節點,都可以繼續呼叫下一個節點,也可以阻止流程繼續執行
	
	* 在struts2 中可以定義很多個攔截器,將多個攔截器按照特定順序 組成攔截器棧 (順序呼叫 棧中的每一個攔截器 )

3. Struts2的核心是攔截器,看一下Struts2的執行流程


案例總結之自定義攔截器和配置

1. 編寫攔截器,需要實現Interceptor介面,實現介面中的三個方法
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		// 獲取session物件
		User user = (User) ServletActionContext.getRequest().getSession().getAttribute("existUser");
		if(user == null){
			// 說明,沒有登入,後面就不會執行了
			return "login";
		}
		return invocation.invoke();
	}

2. 需要在struts.xml中進行攔截器的配置,配置一共有兩種方式
	<!-- 定義了攔截器 第一種方式
	<interceptors>
		<interceptor name="DemoInterceptor" class="com.itheima.interceptor.DemoInterceptor"/>
	</interceptors>
	-->
	
	<!-- 第二種方式:定義攔截器棧 -->
	<interceptors>
		<interceptor name="DemoInterceptor" class="com.itheima.interceptor.DemoInterceptor"/>
		<!-- 定義攔截器棧 -->
		<interceptor-stack name="myStack">
			<interceptor-ref name="DemoInterceptor"/>
			<interceptor-ref name="defaultStack"/>
		</interceptor-stack>
	</interceptors>
	
	<action name="userAction" class="com.itheima.demo3.UserAction">
		<!-- 只要是引用自己的攔截器,預設棧的攔截器就不執行了,必須要手動引入預設棧 
		<interceptor-ref name="DemoInterceptor"/>
		<interceptor-ref name="defaultStack"/>
		-->
		
		<!-- 引入攔截器棧就OK -->
		<interceptor-ref name="myStack"/>
	</action>

案例二:使用攔截器判斷使用者是否已經登入