本文包括:
1、Struts 2 概述
2、Struts 2 快速入門
3、Struts 2 的執(zhí)行流程
4、配置 struts.xml 時(shí)的問題與解決方法
5、Struts 2 各配置文件加載的順序
6、struts.xml 如何配置?
7、Struts 2 如何配置常量?
8、引入多個(gè) struts 的配置文件(了解)
9、Action 類的三種寫法
10、Action 的訪問(重難點(diǎn))

1、Struts 2 概述
-
什么是 Struts 2 的框架
Struts 2 是 Struts 1 的下一代產(chǎn)品,是在 struts 1和 WebWork 的技術(shù)基礎(chǔ)上進(jìn)行了合并的全新的 Struts 2框架。
其全新的 Struts 2 的體系結(jié)構(gòu)與 Struts 1 的體系結(jié)構(gòu)差別巨大。
Struts 2 以 WebWork 為核心,采用攔截器的機(jī)制來處理用戶的請求,這樣的設(shè)計(jì)也使得業(yè)務(wù)邏輯控制器能夠與ServletAPI完全脫離開,所以 Struts 2 可以理解為 WebWork 的更新產(chǎn)品。
雖然從 Struts 1 到 Struts 2 有著太大的變化,但是相對于 WebWork,Struts 2 的變化很小。
-
Struts 2 是一個(gè)基于 MVC 設(shè)計(jì)模式的 Web 層框架
-
MVC 和 JavaEE 的三層結(jié)構(gòu)
MVC 設(shè)計(jì)模式:是由一些網(wǎng)站的開發(fā)人員提出來的
JavaEE 三層結(jié)構(gòu):SUN公司為 JavaEE 開發(fā)劃分的結(jié)構(gòu)
-
常見的 Web 層的框架
Struts 1
Struts 2
Webwork
SpringMVC
-
Web 層框架的特點(diǎn)
都是一個(gè)特點(diǎn),前端控制器模式
記?。呵岸丝刂破鳎ê诵牡目刂破鳎?/p>
Struts 2 框架前端控制器就是過濾器(Filter)
-
前端控制器模式

2、Struts 2 快速入門
-
環(huán)境搭建
-
下載 jar 包,最好不要選擇最新的,盡量選擇較穩(wěn)定的版本
https://struts.apache.org/ -- 官網(wǎng)地址
-
若解壓 struts-2.3.24-all.zip 包
-
解壓后會(huì)看到 jar 包和一些文件,大家需要掌握包相關(guān)的信息
apps -- Struts2框架提供了一些應(yīng)用
libs -- Struts2框架開發(fā)的 jar 包
docs -- Struts2框架開發(fā)文檔
src -- Struts2框架源碼
-
若解壓 struts-2.3.24-apps / libs / docs / src .zip ,則會(huì)得到如上所述的各自內(nèi)容,官網(wǎng)為了下載方便,各有所需
-
-
引入需要開發(fā)的 jar 包
Struts 2 框架的開發(fā) jar 包非常多,但是不是所有都是必須要引入的,有一些必須要導(dǎo)入的 jar 包,這些 jar 包可以從 Struts 2 框架提供的應(yīng)用中找到。
大家可以打開 apps 目錄,然后找到 struts2-blank.war 應(yīng)用(blank 是空模版,所以這個(gè)包含了最基本的 jar 包)。war 包和 zip 包的壓縮格式是一樣的,所以可以自己修改后綴名為 zip 再解壓之。
找到解壓后的應(yīng)用,打開 WEB-INF/lib 目錄下所有的 jar 包。并且把這些 jar 包復(fù)制到工程中就可以了。
-
配置 Struts 2 的前端控制器,注意:這一步是必須要做的操作,這是 Struts 2 核心的控制器。
Struts 2 的前端控制器就是一個(gè)過濾器,那么過濾器相關(guān)知識咱們都學(xué)習(xí)過,需要在 web.xml 中進(jìn)行配置。
-
前端控制器的類的路徑和名稱:
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 文件,添加一個(gè)超鏈接,用來執(zhí)行 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 類是動(dòng)作類,是 Struts 2 處理請求,封裝數(shù)據(jù),響應(yīng)頁面的核心控制器,需要自己編寫,Action 類中的方法有如下要求:
控制權(quán)限為 public
返回值為 String 類型,且返回值指明了要跳轉(zhuǎn)的頁面地址,默認(rèn)是轉(zhuǎn)發(fā)
名稱任意(但最好有意義)
沒有參數(shù)列表
-
代碼如下:
package com.itheima.action; /** * Stuts2框架都使用Action類處理用戶的請求 * @author Administrator */ public class HelloAction { /** * Action類中的方法簽名有要求的,必須這么做 * public 共有的 * 必須有返回值,必須String類型 * 方法名稱可以是任意的,但是不能有參數(shù)列表 * 頁面的跳轉(zhuǎn): * 1. return "字符串" * 2. 需要在strtus.xml配置文件中,配置跳轉(zhuǎn)的頁面 */ public String sayHello(){ // 編寫代碼 接收請求的參數(shù) System.out.println("Hello Struts2!!"); return "ok"; } /** * 演示的method方法的默認(rèn)值 * @return */ public String execute(){ System.out.println("method方法的默認(rèn)值是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"> <!-- 配置跳轉(zhuǎn)的頁面,路徑的寫法:在Struts2框架中,不管是轉(zhuǎn)發(fā)還是重定向,都不用寫項(xiàng)目名 --> <result name="ok">/demo1/suc.jsp</result> </action> </package> </struts>
注意:在 jsp 頁面中的路徑寫法為:
/工程名/hello.action,其中xx與 struts.xml 中的 action 的名字一致:action name="hello"。
3、Struts 2 的執(zhí)行流程
-
執(zhí)行的流程
編寫的頁面,點(diǎn)擊超鏈接,請求提交到服務(wù)器端。
-
請求會(huì)先經(jīng)過 Struts 2 的核心過濾器(StrutsPrepareAndExecuteFilter)
過濾器的功能是完成了一部分代碼功能。
就是一系列的攔截器執(zhí)行了,進(jìn)行一些處理工作。
咱們可以在 struts-default.xml 配置文件中看到有很多的攔截器,可以通過斷點(diǎn)的方式來演示。
攔截器執(zhí)行完后,會(huì)根據(jù) struts.xml 的配置文件找到請求路徑,找到具體的類,通過反射的方式讓方法執(zhí)行。
-
總結(jié)
JSP 頁面-->StrutsPrepereAndExecuteFilter 過濾器-->執(zhí)行一系列攔截器(完成了部分代碼)-->執(zhí)行到目標(biāo) Action-->返回字符串-->結(jié)果頁面(result)-->頁面跳轉(zhuǎn)
-
執(zhí)行流程圖解:
4、配置 struts.xml 時(shí)的問題與解決方法
-
先找到struts.xml的配置文件,復(fù)制 http://struts.apache.org/dtds/struts-2.3.dtd,注意,不要有雙引號。
MyEclipse工具欄 -- window -- preferences -- 搜索 -- 輸入xml -- 選擇 xml Catalog
-
選擇添加按鈕(add按鈕)
key type 要選擇URI
key的位置把剛才復(fù)制的路徑拷貝進(jìn)去。http://struts.apache.org/dtds/struts-2.3.dtd
Location 要在本地能找到struts2-2.3.dtd的真實(shí)文件,即點(diǎn)擊 File System,去資料中找到它。
-
如果想查看源代碼
attachsource:選擇資料/struts2/struts-2.3.24-all.zip
5、Struts 2 各配置文件加載的順序
-
首先要需要掌握:
加載了哪些個(gè)配置文件(重點(diǎn)的)
配置文件的名稱是什么
配置文件的位置
配置文件的作用
-
Struts2 框架的核心是 StrutsPrepareAndExecuteFilter 過濾器,該過濾器有兩個(gè)功能
Prepare -- 預(yù)處理,加載核心的配置文件
Execute -- 執(zhí)行,讓部分?jǐn)r截器執(zhí)行
-
StrutsPrepareAndExecuteFilter 過濾器會(huì)加載哪些配置文件呢?
-
通過源代碼可以看到具體加載的配置文件和加載配置文件的順序,從上到下依次加載:
-
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
-
-
-
重點(diǎn)了解的配置文件
-
default.properties
在 org/apache/struts2/ 目錄下,代表的是配置的是 Struts 2 框架各種常量的值
-
struts-default.xml
在 Struts 2 的核心包下,代表的是 Struts 2 核心功能的配置(Bean、攔截器、結(jié)果類型等)
-
struts.xml
重點(diǎn)中的重點(diǎn)配置,代表 WEB 應(yīng)用的默認(rèn)配置,在工作中,基本都是配置它就?。。梢耘渲贸A浚?/strong>
-
web.xml
配置前端控制器(可以配置常量)
-
-
配置文件加載順序總結(jié)
先加載 default.properties 文件,位于 org/apache/struts2/default.properties ,都是常量。
又加載 struts-default.xml 配置文件,在核心的 jar 包最下方,struts2 框架的核心功能都是在該配置文件中配置的。
再加載 struts.xml 的配置文件,在 src 的目錄下,代表用戶自己配置的配置文件
最后加載 web.xml 的配置文件
* 后加載的配置文件會(huì)覆蓋掉之前加載的配置文件(在這些配置文件中可以配置常量)
-
注意一個(gè)問題
-
哪些配置文件中可以配置常量?
-
default.properties
默認(rèn)值,咱們是不能修改的?。?/p>
-
struts.xml
可以配置,開發(fā)中基本上都在該配置文件中配置常量
-
struts.properties
可以配置,但基本不會(huì)在該配置文件中配置
-
web.xml
可以配置,但基本不會(huì)在該配置文件中配置
-
后加載的配置文件會(huì)覆蓋掉之前加載的配置!!
-
6、struts.xml 如何配置?
-
<package>標(biāo)簽,如果要配置<Action>的標(biāo)簽,那么必須要先配置<package>標(biāo)簽,代表的包的概念-
包含的屬性
-
name
包的名稱,要求是唯一的,管理action配置
-
extends
繼承,可以繼承其他的包,只要繼承了,那么該包就包含了其他包的功能,一般都是繼承struts-default
-
namespace
名稱空間,一般與<action>標(biāo)簽中的name屬性共同決定訪問路徑(通俗話:怎么來訪問action),常見的配置如下
-
namespace="/"
根名稱空間
-
namespace="/aaa"
帶有名稱的名稱空間
-
-
abstract
抽象的。這個(gè)屬性基本很少使用,值如果是true,那么編寫的包是被繼承的
-
-
-
<action>標(biāo)簽-
代表配置 action 類,包含的屬性
-
name
和<package>標(biāo)簽的 namespace 屬性一起來決定訪問路徑的
-
class
配置Action類的全路徑(默認(rèn)值是 ActionSupport 類)
-
method
Action類中執(zhí)行的方法,如果不指定,默認(rèn)值是 execute
-
-
-
<result>標(biāo)簽-
action 類中方法執(zhí)行,返回的結(jié)果跳轉(zhuǎn)的頁面
name -- 結(jié)果頁面邏輯視圖名稱
type -- 結(jié)果類型(默認(rèn)值是轉(zhuǎn)發(fā),也可以設(shè)置其他的值)
-
7、Struts 2 如何配置常量
-
可以在 Struts 2 框架中的哪些配置文件中配置常量?
-
struts.xml(必須要掌握,開發(fā)中基本上就在該配置文件中編寫常量)
<?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"> <!-- 配置跳轉(zhuǎn)的頁面,路徑的寫法:在Struts2框架中,不管是轉(zhuǎn)發(fā)還是重定向,都不用寫項(xiàng)目名 --> <result name="ok">/demo1/suc.jsp</result> </action> </package> </struts> -
web.xml
在 StrutsPrepareAndExecuteFilter 配置文件中配置初始化參數(shù)(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> 注意:后加載的配置的文件的常量會(huì)覆蓋之前加載的常量??!
-
-
需要了解的常量:
-
struts.i18n.encoding=UTF-8
指定默認(rèn)編碼集,作用于HttpServletRequest的setCharacterEncoding方法
* struts.action.extension=action,,該屬性指定需要Struts 2處理的請求后綴,該屬性的默認(rèn)值是action,即所有匹配*.action的請求都由Struts2處理。如果用戶需要指定多個(gè)請求后綴,則多個(gè)后綴之間以英文逗號(,)隔開
-
struts.serve.static.browserCache=true
設(shè)置瀏覽器是否緩存靜態(tài)內(nèi)容,默認(rèn)值為true(生產(chǎn)環(huán)境下使用),開發(fā)階段最好關(guān)閉
-
struts.configuration.xml.reload=false
當(dāng)struts的配置文件修改后,系統(tǒng)是否自動(dòng)重新加載該文件,默認(rèn)值為false(生產(chǎn)環(huán)境下使用)
-
struts.devMode = false
開發(fā)模式下使用,這樣可以打印出更詳細(xì)的錯(cuò)誤信息
-
8、引入多個(gè) struts 的配置文件(了解)
-
在大部分應(yīng)用里,隨著應(yīng)用規(guī)模的增加,系統(tǒng)中 Action 的數(shù)量也會(huì)大量增加,導(dǎo)致 struts.xml 配置文件變得非常臃腫。
為了避免 struts.xml 文件過于龐大、臃腫,提高 struts.xml 文件的可讀性,我們可以將一個(gè) struts.xml 配置文件分解成多個(gè)配置文件,然后在 struts.xml 文件中包含其他配置文件。
-
可以在
<package>標(biāo)簽中,使用<include>標(biāo)簽來引入其他的 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 類的三種寫法
-
配置文件學(xué)習(xí)完成,下面的重點(diǎn)是 Action 類的三種寫法:
-
不繼承、不實(shí)現(xiàn)接口,此時(shí)該 Action 類就是一個(gè) POJO 類
-
什么是POJO類,POJO(Plain Ordinary Java Object)簡單的 Java 對象。
簡單記:沒有繼承某個(gè)類,沒有實(shí)現(xiàn)接口,就是 POJO 的類。
-
代碼:
package com.itheima.action1; /** * 就是POJO類:沒有任何繼承和實(shí)現(xiàn) * @author Administrator */ public class Demo1Action { /** * execute是默認(rèn)方法 * return null; 不會(huì)進(jìn)行跳轉(zhuǎn) * @return */ public String execute(){ System.out.println("Demo1Action就是POJO類..."); return null; } }
-
-
Action 類實(shí)現(xiàn) Action 接口
Action 接口中定義了5個(gè)常量,5個(gè)常量的值對應(yīng)的是5個(gè)邏輯視圖跳轉(zhuǎn)頁面(跳轉(zhuǎn)的頁面還是需要自己來配置),還定義了一個(gè)方法,execute 方法。
-
需要掌握5個(gè)邏輯視圖的常量
SUCCESS -- 成功.
INPUT -- 用于數(shù)據(jù)表單校驗(yàn).如果校驗(yàn)失敗,跳轉(zhuǎn) INPUT 視圖.
LOGIN -- 登錄.
ERROR -- 錯(cuò)誤.
NONE -- 頁面不轉(zhuǎn)向.
-
代碼:
package com.itheima.action1; import com.opensymphony.xwork2.Action; /** * 實(shí)現(xiàn)Action的接口,Action是框架提供的接口 * @author Administrator */ public class Demo2Action implements Action{ public String execute() throws Exception { System.out.println("Demo2Action實(shí)現(xiàn)了Action的接口"); // return "success"; // return LOGIN; // 表示頁面不跳轉(zhuǎn) return NONE; } }
-
Action 類可以去繼承 ActionSupport 類(開發(fā)中這種方式使用最多)
- 設(shè)置錯(cuò)誤信息
ActionSupport 也實(shí)現(xiàn)了 Action 接口
ActionSupport 中已經(jīng)有了 excuete 方法,所以繼承時(shí)需要 override 父類的方法來實(shí)現(xiàn)開發(fā)者希望的邏輯功能
-
代碼:
package com.itheima.action1; import com.opensymphony.xwork2.ActionSupport; /** * 編寫Action類繼承ActionSupport類,ActionSupport類已經(jīng)實(shí)現(xiàn)了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> <!-- 包結(jié)構(gòu) --> <package name="demo1" namespace="/" extends="struts-default"> <!-- POJO類的方式 --> <action name="demo1Action" class="com.itheima.action1.Demo1Action"/> <!-- 實(shí)現(xiàn)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 的訪問(重難點(diǎn))
-
傳統(tǒng)配置方式:通過
<action>標(biāo)簽中的 method 屬性,可以 訪問到 Action 中的具體的方法。傳統(tǒng)配置方式:配置清晰、容易理解,但是擴(kuò)展時(shí)需要修改配置文件等等,較麻煩。
-
具體的實(shí)例如下:
-
頁面代碼
<h3>傳統(tǒng)的配置文件的方式</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"> <!-- 傳統(tǒng)方式 --> <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; } }
-
-
通配符的訪問方式:通配符就是 * ,代表任意的字符
通配符的訪問方式:可以簡化配置文件的代碼編寫,而且擴(kuò)展和維護(hù)比較容易。
前提:訪問的路徑和方法的名稱必須要有某種聯(lián)系
-
具體實(shí)例如下:
-
頁面代碼
<h3>通配符的方式(應(yīng)用比較多)</h3> <a href="${ pageContext.request.contextPath }/linkman_save.action">保存聯(lián)系人</a> <a href="${ pageContext.request.contextPath }/linkman_delete.action">刪除聯(lián)系人</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("保存聯(lián)系人..."); return "saveOK"; } public String delete(){ System.out.println("刪除聯(lián)系人..."); return "delOK"; } }
-
-
具體理解:在 JSP 頁面發(fā)送請求,http://localhost/struts2_01/linkman_save.action,配置文件中的 linkman_* 可以匹配該請求,method 屬性的值使用{1}來代替,{1}就表示的是第一個(gè)*號的位置??!所以 method 的值就等于 add ,那么就找到 LinkmanAction 類中的 save 方法,所以 save 方法就執(zhí)行了!
<action name="linkman__" class="" method="{2}">
如果配置文件如上所示,那么匹配的是第二個(gè)*號的位置
-
動(dòng)態(tài)方法訪問的方式(有的開發(fā)中也會(huì)使用這種方式)
-
如果想完成動(dòng)態(tài)方法訪問的方式,需要開啟一個(gè)常量,struts.enable.DynamicMethodInvocation ,把值設(shè)置成 true。
注意:不同的 Struts 2 框架的版本,該常量的值不一定是 true 或者 false ,需要自己來看一下。如果是 false ,需要自己開啟。
-
在 struts.xml 中配置該常量(具體做法見本文第7點(diǎn))。
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
-
具體代碼如下
-
頁面的代碼(注意請求時(shí)的路徑!)
<h3>動(dòng)態(tài)方法訪問的方式</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"> <!-- 配置動(dòng)態(tài)方法訪問 --> <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; } }
-
-
