本文包括:
1、Struts 2 概述
2、Struts 2 快速入門
3、Struts 2 的執行流程
4、配置 struts.xml 時的問題與解決方法
5、Struts 2 各配置文件加載的順序
6、struts.xml 如何配置?
7、Struts 2 如何配置常量?
8、引入多個 struts 的配置文件(了解)
9、Action 類的三種寫法
10、Action 的訪問(重難點)
1、Struts 2 概述
-
什么是 Struts 2 的框架
Struts 2 是 Struts 1 的下一代產品,是在 struts 1和 WebWork 的技術基礎上進行了合并的全新的 Struts 2框架。
其全新的 Struts 2 的體系結構與 Struts 1 的體系結構差別巨大。
Struts 2 以 WebWork 為核心,采用攔截器的機制來處理用戶的請求,這樣的設計也使得業務邏輯控制器能夠與ServletAPI完全脫離開,所以 Struts 2 可以理解為 WebWork 的更新產品。
雖然從 Struts 1 到 Struts 2 有著太大的變化,但是相對于 WebWork,Struts 2 的變化很小。
-
Struts 2 是一個基于 MVC 設計模式的 Web 層框架
-
MVC 和 JavaEE 的三層結構
MVC 設計模式:是由一些網站的開發人員提出來的
JavaEE 三層結構:SUN公司為 JavaEE 開發劃分的結構
-
常見的 Web 層的框架
Struts 1
Struts 2
Webwork
SpringMVC
-
Web 層框架的特點
都是一個特點,前端控制器模式
記住:前端控制器(核心的控制器)
Struts 2 框架前端控制器就是過濾器(Filter)
-
前端控制器模式
2、Struts 2 快速入門
-
環境搭建
-
下載 jar 包,最好不要選擇最新的,盡量選擇較穩定的版本
https://struts.apache.org/ -- 官網地址
-
若解壓 struts-2.3.24-all.zip 包
-
解壓后會看到 jar 包和一些文件,大家需要掌握包相關的信息
apps -- Struts2框架提供了一些應用
libs -- Struts2框架開發的 jar 包
docs -- Struts2框架開發文檔
src -- Struts2框架源碼
-
若解壓 struts-2.3.24-apps / libs / docs / src .zip ,則會得到如上所述的各自內容,官網為了下載方便,各有所需
-
-
引入需要開發的 jar 包
Struts 2 框架的開發 jar 包非常多,但是不是所有都是必須要引入的,有一些必須要導入的 jar 包,這些 jar 包可以從 Struts 2 框架提供的應用中找到。
大家可以打開 apps 目錄,然后找到 struts2-blank.war 應用(blank 是空模版,所以這個包含了最基本的 jar 包)。war 包和 zip 包的壓縮格式是一樣的,所以可以自己修改后綴名為 zip 再解壓之。
找到解壓后的應用,打開 WEB-INF/lib 目錄下所有的 jar 包。并且把這些 jar 包復制到工程中就可以了。
-
配置 Struts 2 的前端控制器,注意:這一步是必須要做的操作,這是 Struts 2 核心的控制器。
Struts 2 的前端控制器就是一個過濾器,那么過濾器相關知識咱們都學習過,需要在 web.xml 中進行配置。
-
前端控制器的類的路徑和名稱:
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
-
具體配置代碼如下:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
-
編寫 jsp 文件,添加一個超鏈接,用來執行 Action 類
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h3>快速入門</h3> <a href="${ pageContext.request.contextPath }/hello.action">快速入門按鈕</a> </body> </html>
-
編寫 Action 類
-
Action 類是動作類,是 Struts 2 處理請求,封裝數據,響應頁面的核心控制器,需要自己編寫,Action 類中的方法有如下要求:
控制權限為 public
返回值為 String 類型,且返回值指明了要跳轉的頁面地址,默認是轉發
名稱任意(但最好有意義)
沒有參數列表
-
代碼如下:
package com.itheima.action; /** * Stuts2框架都使用Action類處理用戶的請求 * @author Administrator */ public class HelloAction { /** * Action類中的方法簽名有要求的,必須這么做 * public 共有的 * 必須有返回值,必須String類型 * 方法名稱可以是任意的,但是不能有參數列表 * 頁面的跳轉: * 1. return "字符串" * 2. 需要在strtus.xml配置文件中,配置跳轉的頁面 */ public String sayHello(){ // 編寫代碼 接收請求的參數 System.out.println("Hello Struts2!!"); return "ok"; } /** * 演示的method方法的默認值 * @return */ public String execute(){ System.out.println("method方法的默認值是execute"); return null; } }
-
-
編寫 Struts.xml 配置文件
配置文件名稱是 struts.xml(名稱必須是 struts.xml)
在 src 下引入 struts.xml 配置文件(配置文件的路徑必須是在 src 的目錄下)
-
struts.xml 配置如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> <action name="hello" class="com.itheima.action.HelloAction" method="sayHello"> <!-- 配置跳轉的頁面,路徑的寫法:在Struts2框架中,不管是轉發還是重定向,都不用寫項目名 --> <result name="ok">/demo1/suc.jsp</result> </action> </package> </struts>
注意:在 jsp 頁面中的路徑寫法為:
/工程名/hello.action
,其中xx
與 struts.xml 中的 action 的名字一致:action name="hello"
。
3、Struts 2 的執行流程
-
執行的流程
編寫的頁面,點擊超鏈接,請求提交到服務器端。
-
請求會先經過 Struts 2 的核心過濾器(StrutsPrepareAndExecuteFilter)
過濾器的功能是完成了一部分代碼功能。
就是一系列的攔截器執行了,進行一些處理工作。
咱們可以在 struts-default.xml 配置文件中看到有很多的攔截器,可以通過斷點的方式來演示。
攔截器執行完后,會根據 struts.xml 的配置文件找到請求路徑,找到具體的類,通過反射的方式讓方法執行。
-
總結
JSP 頁面-->StrutsPrepereAndExecuteFilter 過濾器-->執行一系列攔截器(完成了部分代碼)-->執行到目標 Action-->返回字符串-->結果頁面(result)-->頁面跳轉
-
執行流程圖解:
4、配置 struts.xml 時的問題與解決方法
-
先找到struts.xml的配置文件,復制 http://struts.apache.org/dtds/struts-2.3.dtd,注意,不要有雙引號。
MyEclipse工具欄 -- window -- preferences -- 搜索 -- 輸入xml -- 選擇 xml Catalog
-
選擇添加按鈕(add按鈕)
key type 要選擇URI
key的位置把剛才復制的路徑拷貝進去。http://struts.apache.org/dtds/struts-2.3.dtd
Location 要在本地能找到struts2-2.3.dtd的真實文件,即點擊 File System,去資料中找到它。
-
如果想查看源代碼
attachsource:選擇資料/struts2/struts-2.3.24-all.zip
5、Struts 2 各配置文件加載的順序
-
首先要需要掌握:
加載了哪些個配置文件(重點的)
配置文件的名稱是什么
配置文件的位置
配置文件的作用
-
Struts2 框架的核心是 StrutsPrepareAndExecuteFilter 過濾器,該過濾器有兩個功能
Prepare -- 預處理,加載核心的配置文件
Execute -- 執行,讓部分攔截器執行
-
StrutsPrepareAndExecuteFilter 過濾器會加載哪些配置文件呢?
-
通過源代碼可以看到具體加載的配置文件和加載配置文件的順序,從上到下依次加載:
-
init_DefaultProperties();
加載: org/apache/struts2/default.properties
-
init_TraditionalXmlConfigurations();
加載: struts-default.xml,struts-plugin.xml,struts.xml
-
init_LegacyStrutsProperties();
加載:自定義的 struts.properties.
-
init_CustomConfigurationProviders();
加載:用戶自定義配置提供者
-
init_FilterInitParameters() ;
加載: web.xml
-
-
-
重點了解的配置文件
-
default.properties
在 org/apache/struts2/ 目錄下,代表的是配置的是 Struts 2 框架各種常量的值
-
struts-default.xml
在 Struts 2 的核心包下,代表的是 Struts 2 核心功能的配置(Bean、攔截器、結果類型等)
-
struts.xml
重點中的重點配置,代表 WEB 應用的默認配置,在工作中,基本都是配置它就?。。梢耘渲贸A浚?/strong>
-
web.xml
配置前端控制器(可以配置常量)
-
-
配置文件加載順序總結
先加載 default.properties 文件,位于 org/apache/struts2/default.properties ,都是常量。
又加載 struts-default.xml 配置文件,在核心的 jar 包最下方,struts2 框架的核心功能都是在該配置文件中配置的。
再加載 struts.xml 的配置文件,在 src 的目錄下,代表用戶自己配置的配置文件
最后加載 web.xml 的配置文件
* 后加載的配置文件會覆蓋掉之前加載的配置文件(在這些配置文件中可以配置常量)
-
注意一個問題
-
哪些配置文件中可以配置常量?
-
default.properties
默認值,咱們是不能修改的!!
-
struts.xml
可以配置,開發中基本上都在該配置文件中配置常量
-
struts.properties
可以配置,但基本不會在該配置文件中配置
-
web.xml
可以配置,但基本不會在該配置文件中配置
-
后加載的配置文件會覆蓋掉之前加載的配置!!
-
6、struts.xml 如何配置?
-
<package>
標簽,如果要配置<Action>
的標簽,那么必須要先配置<package>
標簽,代表的包的概念-
包含的屬性
-
name
包的名稱,要求是唯一的,管理action配置
-
extends
繼承,可以繼承其他的包,只要繼承了,那么該包就包含了其他包的功能,一般都是繼承struts-default
-
namespace
名稱空間,一般與<action>標簽中的name屬性共同決定訪問路徑(通俗話:怎么來訪問action),常見的配置如下
-
namespace="/"
根名稱空間
-
namespace="/aaa"
帶有名稱的名稱空間
-
-
abstract
抽象的。這個屬性基本很少使用,值如果是true,那么編寫的包是被繼承的
-
-
-
<action>
標簽-
代表配置 action 類,包含的屬性
-
name
和<package>標簽的 namespace 屬性一起來決定訪問路徑的
-
class
配置Action類的全路徑(默認值是 ActionSupport 類)
-
method
Action類中執行的方法,如果不指定,默認值是 execute
-
-
-
<result>
標簽-
action 類中方法執行,返回的結果跳轉的頁面
name -- 結果頁面邏輯視圖名稱
type -- 結果類型(默認值是轉發,也可以設置其他的值)
-
7、Struts 2 如何配置常量
-
可以在 Struts 2 框架中的哪些配置文件中配置常量?
-
struts.xml(必須要掌握,開發中基本上就在該配置文件中編寫常量)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!-- 配置常量 --> <constant name="key" value="value"></constant> <package name="default" namespace="/" extends="struts-default"> <action name="hello" class="com.itheima.action.HelloAction" method="sayHello"> <!-- 配置跳轉的頁面,路徑的寫法:在Struts2框架中,不管是轉發還是重定向,都不用寫項目名 --> <result name="ok">/demo1/suc.jsp</result> </action> </package> </struts>
-
web.xml
在 StrutsPrepareAndExecuteFilter 配置文件中配置初始化參數(init-param)
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>key</param-name> <param-value>value</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
注意:后加載的配置的文件的常量會覆蓋之前加載的常量?。?/p>
-
-
需要了解的常量:
-
struts.i18n.encoding=UTF-8
指定默認編碼集,作用于HttpServletRequest的setCharacterEncoding方法
* struts.action.extension=action,,該屬性指定需要Struts 2處理的請求后綴,該屬性的默認值是action,即所有匹配*.action的請求都由Struts2處理。如果用戶需要指定多個請求后綴,則多個后綴之間以英文逗號(,)隔開
-
struts.serve.static.browserCache=true
設置瀏覽器是否緩存靜態內容,默認值為true(生產環境下使用),開發階段最好關閉
-
struts.configuration.xml.reload=false
當struts的配置文件修改后,系統是否自動重新加載該文件,默認值為false(生產環境下使用)
-
struts.devMode = false
開發模式下使用,這樣可以打印出更詳細的錯誤信息
-
8、引入多個 struts 的配置文件(了解)
-
在大部分應用里,隨著應用規模的增加,系統中 Action 的數量也會大量增加,導致 struts.xml 配置文件變得非常臃腫。
為了避免 struts.xml 文件過于龐大、臃腫,提高 struts.xml 文件的可讀性,我們可以將一個 struts.xml 配置文件分解成多個配置文件,然后在 struts.xml 文件中包含其他配置文件。
-
可以在
<package>
標簽中,使用<include>
標簽來引入其他的 struts_xx.xml 的配置文件。例如:<struts> ... <include file="struts-part1.xml"/> <include file="struts-part2.xml"/> </struts>
-
注意格式:
<include file="cn/itcast/demo2/struts-part1.xml"/>
9、Action 類的三種寫法
-
配置文件學習完成,下面的重點是 Action 類的三種寫法:
-
不繼承、不實現接口,此時該 Action 類就是一個 POJO 類
-
什么是POJO類,POJO(Plain Ordinary Java Object)簡單的 Java 對象。
簡單記:沒有繼承某個類,沒有實現接口,就是 POJO 的類。
-
代碼:
package com.itheima.action1; /** * 就是POJO類:沒有任何繼承和實現 * @author Administrator */ public class Demo1Action { /** * execute是默認方法 * return null; 不會進行跳轉 * @return */ public String execute(){ System.out.println("Demo1Action就是POJO類..."); return null; } }
-
-
Action 類實現 Action 接口
Action 接口中定義了5個常量,5個常量的值對應的是5個邏輯視圖跳轉頁面(跳轉的頁面還是需要自己來配置),還定義了一個方法,execute 方法。
-
需要掌握5個邏輯視圖的常量
SUCCESS -- 成功.
INPUT -- 用于數據表單校驗.如果校驗失敗,跳轉 INPUT 視圖.
LOGIN -- 登錄.
ERROR -- 錯誤.
NONE -- 頁面不轉向.
-
代碼:
package com.itheima.action1; import com.opensymphony.xwork2.Action; /** * 實現Action的接口,Action是框架提供的接口 * @author Administrator */ public class Demo2Action implements Action{ public String execute() throws Exception { System.out.println("Demo2Action實現了Action的接口"); // return "success"; // return LOGIN; // 表示頁面不跳轉 return NONE; } }
-
Action 類可以去繼承 ActionSupport 類(開發中這種方式使用最多)
- 設置錯誤信息
ActionSupport 也實現了 Action 接口
ActionSupport 中已經有了 excuete 方法,所以繼承時需要 override 父類的方法來實現開發者希望的邏輯功能
-
代碼:
package com.itheima.action1; import com.opensymphony.xwork2.ActionSupport; /** * 編寫Action類繼承ActionSupport類,ActionSupport類已經實現了Action和一些其他接口 * @author Administrator */ public class Demo3Action extends ActionSupport{ private static final long serialVersionUID = 2183101963251216722L; @override public String execute() throws Exception { System.out.println("Demo3Action繼承了ActionSupport類..."); return NONE; } }
-
-
在 struts.xml 中如下配置:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!-- 包結構 --> <package name="demo1" namespace="/" extends="struts-default"> <!-- POJO類的方式 --> <action name="demo1Action" class="com.itheima.action1.Demo1Action"/> <!-- 實現Action接口的方式 --> <action name="demo2Action" class="com.itheima.action1.Demo2Action"> <result name="login">/demo1/suc.jsp</result> </action> <!-- 繼承ActionSupport類的方式 --> <action name="demo3Action" class="com.itheima.action1.Demo3Action"/> </package> </struts>
10、Action 的訪問(重難點)
-
傳統配置方式:通過
<action>
標簽中的 method 屬性,可以 訪問到 Action 中的具體的方法。傳統配置方式:配置清晰、容易理解,但是擴展時需要修改配置文件等等,較麻煩。
-
具體的實例如下:
-
頁面代碼
<h3>傳統的配置文件的方式</h3> <a href="${ pageContext.request.contextPath }/saveCust.action">保存客戶</a> <a href="${ pageContext.request.contextPath }/delCust.action">刪除客戶</a>
-
struts.xml 配置文件的代碼
<!-- 演示Action的訪問 --> <package name="demo2" namespace="/" extends="struts-default"> <!-- 傳統方式 --> <action name="saveCust" class="com.itheima.action2.CustomerAction" method="save"/> <action name="delCust" class="com.itheima.action2.CustomerAction" method="delete"/> </package>
-
Action 的代碼
public class CustomerAction extends ActionSupport{ private static final long serialVersionUID = 7307785750944680651L; public String save(){ System.out.println("保存客戶..."); return NONE; } public String delete(){ System.out.println("刪除客戶..."); return NONE; } }
-
-
通配符的訪問方式:通配符就是 * ,代表任意的字符
通配符的訪問方式:可以簡化配置文件的代碼編寫,而且擴展和維護比較容易。
前提:訪問的路徑和方法的名稱必須要有某種聯系
-
具體實例如下:
-
頁面代碼
<h3>通配符的方式(應用比較多)</h3> <a href="${ pageContext.request.contextPath }/linkman_save.action">保存聯系人</a> <a href="${ pageContext.request.contextPath }/linkman_delete.action">刪除聯系人</a>
-
struts.xml 配置文件代碼
<!-- 演示Action的訪問 --> <package name="demo2" namespace="/" extends="struts-default"> <!-- 通配符的方式 --> <action name="linkman_*" class="com.itheima.action2.LinkmanAction" method="{1}"> <result name="saveOK">/demo1/suc.jsp</result> <result name="delOK">/demo1/suc.jsp</result> </action> </package>
-
Action的代碼
public class LinkmanAction extends ActionSupport{ private static final long serialVersionUID = -6462671346088624621L; public String save(){ System.out.println("保存聯系人..."); return "saveOK"; } public String delete(){ System.out.println("刪除聯系人..."); return "delOK"; } }
-
-
具體理解:在 JSP 頁面發送請求,http://localhost/struts2_01/linkman_save.action,配置文件中的 linkman_* 可以匹配該請求,method 屬性的值使用{1}來代替,{1}就表示的是第一個*號的位置??!所以 method 的值就等于 add ,那么就找到 LinkmanAction 類中的 save 方法,所以 save 方法就執行了!
<action name="linkman__" class="" method="{2}">
如果配置文件如上所示,那么匹配的是第二個*號的位置
-
動態方法訪問的方式(有的開發中也會使用這種方式)
-
如果想完成動態方法訪問的方式,需要開啟一個常量,struts.enable.DynamicMethodInvocation ,把值設置成 true。
注意:不同的 Struts 2 框架的版本,該常量的值不一定是 true 或者 false ,需要自己來看一下。如果是 false ,需要自己開啟。
-
在 struts.xml 中配置該常量(具體做法見本文第7點)。
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
-
具體代碼如下
-
頁面的代碼(注意請求時的路徑!)
<h3>動態方法訪問的方式</h3> <a href="${ pageContext.request.contextPath }/user!save.action">保存用戶</a> <a href="${ pageContext.request.contextPath }/user!delete.action">刪除用戶</a>
-
struts.xml 配置文件代碼
<!-- 演示Action的訪問 --> <package name="demo2" namespace="/" extends="struts-default"> <!-- 配置動態方法訪問 --> <action name="user" class="com.itheima.action2.UserAction"/> </package>
-
Action 的類的代碼
public class UserAction extends ActionSupport{ private static final long serialVersionUID = 4818164363592527550L; public String save(){ System.out.println("保存用戶..."); return NONE; } public String delete(){ System.out.println("刪除用戶..."); return NONE; } }
-
-