1. 程式人生 > >Struts2框架學習總結(從入門到精通)

Struts2框架學習總結(從入門到精通)

文章目錄

一、Struts2入門

struts2概述

  1. javaee三層中的web層
  2. 在struts1和webwork基礎上的全新的框架
  3. 解決一些問題
    ①當功能很多,會建立很多的servlet,那麼維護起來不方便,在javaweb階段我們是通過BaseServlet的的底層反射來實現的
    在這裡插入圖片描述
  4. struts2版本
    在這裡插入圖片描述
    目前比較穩定的版本
  5. web層框架
    ①struts2
    ②springMVC

struts2入門案例

  1. 從lib目錄中匯入jar包,但是裡面可能上百個jar包,你可以從app目錄(裡面是一些案例,最好從blank案例中拿)中找到裡面的web-inf->lib下的jar包進行copy
    在這裡插入圖片描述
    在這裡插入圖片描述
    關於jar包詳情可參考:https://blog.csdn.net/For_ZZHacker/article/details/85675995
  2. 建立action(這裡的action就相當於javaweb學的servlet)

① 每次訪問servlet的時候都會預設執行service方法(寫一個servlet:寫一個類的時候需要繼承httpservlet類,然後重寫裡面的方法(例如doget,dopost),然後再web.xml中配置訪問servlet的路徑)
② 每次訪問action的時候都會預設執行execute方法(同樣需要配置action的訪問路徑,見下一步)

在這裡插入圖片描述

  1. 配置action類的訪問路徑
    ① 建立struts2的核心配置檔案,該配置檔案的名稱和位置是固定的,跟hibernate的配置檔案一樣。位置在src下面,檔名稱叫struts.xml
    ② 引入dtd的約束
    在這裡插入圖片描述
    在這裡插入圖片描述
    訪問路徑為:http://127.0.0.1:8080/專案名/hello.action
    (action可加可不加,常用瀏覽器例如火狐,谷歌,IE沒問題,雜牌瀏覽器還是加上後面的action有可能會出錯)
    注意:此時訪問會出現404問題,一個可能是伺服器啟動報異常了,另一個就是沒有配置過濾器!!!
  2. 配置struts2的過濾器(在web.xml中配置)
    (struts2已經幫我們封裝好了過濾器,我們只需要配置一下即可)
    在這裡插入圖片描述
    在這裡插入圖片描述
    此時再去訪問就會訪問成功!!!
  3. 小總結:通過一個案例我們知道了使用框架我們可以少些很多的程式碼,他給我們封裝了許多程式碼,但是我們需要去配置運用這些封裝好了的類。
    另外:struts.xml裡面有許多的action,web.xml就定義了一個過濾器

struts2底層執行過程

  1. 幾個概念
    過濾器是在啟動伺服器的時候建立的,servlet預設是在第一次訪問的時候建立的
    框架的學習反射是重點!!!!
    在這裡插入圖片描述

  2. 檢視過濾器原始碼

    在這裡插入圖片描述
    裡面有init方法,doFilter方法,destroy方法
    ①過濾器在伺服器啟動的時候就會執行,建立過濾器時候執行init方法

  • init方法中載入struts2自帶的配置檔案和自己建立的配置檔案(struts.xml,web.xml)
  • 在這裡插入圖片描述
  • 在這裡插入圖片描述
  • 在這裡插入圖片描述
  • 在這裡插入圖片描述
  • 在這裡插入圖片描述
  • 現在再來看一下第二個載入的配置檔案是什麼在這裡插入圖片描述
  • 在這裡插入圖片描述
  • 在這裡插入圖片描述
  • 在這裡插入圖片描述

小總結:我們開發的時候只需要關心struts.xml,web.xml這兩個需要自己配的配置檔案即可

struts2相關配置

struts2的核心配置檔案struts.xml

在這裡插入圖片描述
在這裡插入圖片描述
最大的標籤是<struts> 裡面有3個常用標籤從大到小<package><action><results>,以及裡面的屬性.
① package標籤

  • 類似一個程式碼包,區別不同的action,要配置action,必須首先寫package標籤,在package標籤中才能配置action
  • package標籤屬性
    - name屬性:用來區分不同的package,隨便起名
    - extends屬性:就是個繼承的意思在這裡插入圖片描述
    - namespace屬性:不寫預設也是“/”,最好寫上。
    在這裡插入圖片描述

② action標籤

  • action標籤主要配置action的訪問路徑
  • action的標籤屬性
    - name屬性:區分不同的action;package標籤中的namespace屬性和這裡的name屬性構成了訪問路徑
    - class屬性:全路徑=包名+類名,通過反射的原理去執行該類的
    - method屬性:在這裡插入圖片描述

③ result標籤

  • 根據你的action中的方法返回值,將頁面定位到指定的頁面或action上
  • result標籤的屬性
    - name屬性:和你方法的返回值要一樣
    在這裡插入圖片描述
    裡面的“/”代表的是當前專案的根目錄
    - type屬性
    在這裡插入圖片描述
    有4個值:dispatcher(預設),redirect,chain,redirectAction
    dispatcher(預設)和redirect:result標籤中“/”代表的是專案根路徑,不寫就代表當前路徑下
    chain和redirectAction:result標籤中“/”沒有任何意義,不需要寫,寫了就是多餘,也就是隻能從當前路徑去指定頁面!!!
    chain:只能轉發到同一名稱空間下的Action
    redirect:可以重定向到action中去,也可以重定向到顯示頁面中去

轉發後頁面變了,但是位址列並沒變,本質來講轉發就是同一個請求,重定向是又一次新的請求(相當於2次請求)

struts2常量配置

  1. struts2框架,幫我們實現一部分功能,struts2裡面有常量,在常量裡面封裝一部分功能。
  2. struts2預設的常量位置(記住)
    在這裡插入圖片描述
  3. 修改struts2預設常量值
    ① 常用方法
    在這裡插入圖片描述
    該標籤寫<struts>下面,和<package>標籤同級
    ② 還有2種方式(瞭解)
    在這裡插入圖片描述
  4. 常用常量
    在這裡插入圖片描述
    在這裡插入圖片描述

分模組開發

  1. 每個人自己的模組配置檔案單獨開發,最後合併引入到核心配置檔案中就行,這樣就不會將我們的核心配置檔案給弄亂了。在這裡插入圖片描述

在這裡插入圖片描述

struts2的action建立

action的編寫方式

  1. action編寫的3種方式在這裡插入圖片描述
  2. 建立類,實現Action介面方式(將一些常用的返回值定義為常量例如SUCCESS=“success”),不常用在這裡插入圖片描述在這裡插入圖片描述
  3. 建立類,繼承類ActionSupport,常用
    在這裡插入圖片描述
    當然也可以用那些常量,因為也實現了interface Action
    在這裡插入圖片描述

struts2的action方法訪問(重點)

  1. 一共三種方式實現
    第一種:使用action標籤的method屬性,在這個屬性裡面寫執行的action的方法,不寫預設執行execute()方法
    在這裡插入圖片描述
    第二種:使用萬用字元的方式實現
    在這裡插入圖片描述
    第三種:動態訪問實現(不用)
    在這裡插入圖片描述
    在這裡插入圖片描述
    在這裡插入圖片描述
  2. 一個錯誤演示
    在這裡插入圖片描述
    在這裡插入圖片描述
    在這裡插入圖片描述
  3. 一個action訪問不同方法的例子
  • 普通方式在這裡插入圖片描述
  • 使用萬用字元的方式
    在這裡插入圖片描述
    在這裡插入圖片描述
    在這裡插入圖片描述
    在這裡插入圖片描述
  1. 又是一個struts2應用的案例
    在這裡插入圖片描述
    在這裡插入圖片描述

二、Struts2資料操作

結果頁面的配置

  1. 全域性結果頁面
    使用global-results標籤將result標籤寫這裡面,global-results標籤位於package標籤裡面,此時action標籤預設就有global-results標籤中包含的result標籤
    在這裡插入圖片描述
  2. 區域性結果頁面
    在這裡插入圖片描述
  3. result標籤type屬性
    在這裡插入圖片描述
    在這裡插入圖片描述

在action獲取表單提交的資料

  1. 使用ActionContext類獲取
    在這裡插入圖片描述
    在這裡插入圖片描述
  • 一個例子來演示
  • 建立表單,提交表單到action裡面在這裡插入圖片描述
  • 在這裡插入圖片描述
  1. 使用ServletActionContext類獲取
    在這裡插入圖片描述
    在這裡插入圖片描述
  2. 使用介面注入方式獲取(實現不同的介面,例如ServletRequestAware接口裡面有個方法可以設定出request物件)

讓action實現介面,為了得到request物件,需要新建一個成員變數來進行賦值的,然後在execute方法中才能使用
ware:器皿,物品—》容器
在這裡插入圖片描述

在這裡插入圖片描述
request用的多,session經典案例是用在登入的時候,context用的少

struts2提供獲取表單資料方式(減少了程式碼,替代了上面的方式例如:ServletActionContext)

原始的寫法獲取表單資料並封裝到實體類中(麻煩費勁,但是有效穩定)
在這裡插入圖片描述

  1. 屬性封裝(會用即可)
    在這裡插入圖片描述
    在這裡插入圖片描述
  2. 模型驅動封裝(重點)
    在這裡插入圖片描述
    在這裡插入圖片描述

在這裡插入圖片描述

  1. 表示式封裝(也可以認為是屬性封裝的特例,因為寫法原理一樣)
    在這裡插入圖片描述
    在這裡插入圖片描述

struts2獲取資料封裝到集合中

  1. 封裝到list集合
    在這裡插入圖片描述
  2. 封裝到map集合
    在這裡插入圖片描述

擴充套件-表示式封裝和模型驅動比較

相同點:都封裝到實體類中
不同點:模型驅動只能封裝到同一個實體類物件中,表示式封裝可以封裝到不同實體類中
在這裡插入圖片描述
在這裡插入圖片描述

案例-新增客戶功能

在這裡插入圖片描述
在這裡插入圖片描述

三、Struts2值棧

OGNL概述

  1. web階段用EL表示式在jsp頁面中來獲取域物件裡面的值
  2. ognl表示式比EL表示式功能更強大
    在這裡插入圖片描述

(1)在struts2裡面操作值棧資料
(2)一般把ognl在struts2操作:和struts2標籤一起使用操作值棧

EL表示式,OGNL表示式(從表單獲取資料三種方式中的表示式方式(隸屬於屬性封裝方式))
html標籤,jstl標籤,struts2標籤

  1. OGNL不是struts2的一部分,單獨的專案,經常和struts2一起使用
    (1)使用ognl時候首先匯入jar包,struts2提供了ognl的jar包

OGNL入門案例

在這裡插入圖片描述

什麼是值棧

在這裡插入圖片描述
在這裡插入圖片描述

獲取值棧物件

在這裡插入圖片描述
在這裡插入圖片描述

值棧內部結構

在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述

下圖中root部分是個棧,棧裡面有2個元素,因為沒有操作值棧,所以棧頂元素是當前值棧所在action的一個引用(為了方便操作的),當你往棧裡面放東西就會放到棧頂的位置上。
在這裡插入圖片描述

向值棧放資料

1 向值棧放資料多種方式
第一種 獲取值棧物件,呼叫值棧物件裡面的 set 方法

在這裡插入圖片描述
在這裡插入圖片描述
第二種 獲取值棧物件,呼叫值棧物件裡面的 push方法

在這裡插入圖片描述
在這裡插入圖片描述

第三種 在action定義變數,生成變數的get方法(好處是減少空間的分配了)
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

向值棧放物件

在這裡插入圖片描述

向值棧放list集合

在這裡插入圖片描述
在這裡插入圖片描述

從值棧獲取資料

1 使用struts2的標籤+ognl表示式獲取值棧資料
(1)<s:property value=”ognl表示式”/>

獲取字串

1 向值棧放字串
在這裡插入圖片描述
2 在jsp使用struts2標籤+ognl表示式獲取
在這裡插入圖片描述

獲取物件

在這裡插入圖片描述

獲取list集合

在這裡插入圖片描述
在這裡插入圖片描述
第三種方式使用struts2的iterator標籤類似於jstl的foreach標籤
在這裡插入圖片描述
在這裡插入圖片描述
想使用context裡面的資料需要加個“#”,將資料放到context這樣的操作目的是為了方便取值,不佔用root部分,提高效率
在這裡插入圖片描述
這裡注意一下application,其實就是ServletContext物件,記得這個applicatIon域中是共享的

foreach+EL表示式的方式(需要jstl.jar包和standard.jar,並且在開頭引入c標籤taglib uri是jstl/core)
在這裡插入圖片描述

其他操作

在這裡插入圖片描述
ognl的陣列獲取值的寫法先寫下標,再寫陣列名,中間有點號,值棧的棧頂就是0號位置,依次向下排,所有的都會放到這個top陣列,不是隻有push這種沒有key的。
注意:很多種寫法都用<s:property value="ognl表示式">來獲取,實質上這個標籤是從棧頂先來尋找符合的值,找到就直接顯示,不管後面符合該表示式的值了。

EL表示式獲取值棧資料(為什麼能取到)

如果資料在值棧中雖然能取到,但是效能很低,因為有多餘操作,例如先去域物件中找等等。
先看例子:能夠取到值棧中的資料
在這裡插入圖片描述
在這裡插入圖片描述
先解釋一個詞wrap:包起來,穿外衣,纏繞—》本質就是增強的意思
原始碼裡面會有這個詞,以及wrapper可以理解為包裝器和增強器
EL表示式中就是對request進行了增強,本質就是對getAttubute進行了增強
看原始碼首先從struts2的過濾器中開始看-----》找到裡面有個doFilter方法—》再看到這個doFilter方法中的request被增強了使用wrapRequest(oldRequest)方法
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
最後這個選中的ActionContext.put,又將標誌值(看好了不是attribute,只是一個標誌而已)放到了值棧的第二部分context中去了,其實這個context中包含request物件的引用,Httpsession物件的引用,servletContext物件的引用等等(也因此可以用ognl表示式獲取到域物件中的資料),此時put進去就和這些域物件平起平坐了。

ActionContext.getContext.put(String,Object)是把物件放到了StackContext中,這個物件跟request,session等一樣,它們平起平坐,但這些都不是root物件(這些是context物件),所以要通過#訪問。

request.setAttribute(String,Object)就是把值放到request範圍,而StackConext裡含有request物件,所以可以通過#request.*來訪問。

OGNL的#、%使用

#使用

在這裡插入圖片描述

%使用

在這裡插入圖片描述
注意是表單標籤
上面這個圖就相當於html中的input標籤,所以一般不用ognl的表單標籤,因為效能低,不如直接用html的表單標籤
在這裡插入圖片描述

案例-顯示所有資訊列表(用值棧來存資料,以前用的域物件)

首先想到3種方式set,put,直接定義成員變數方式,第三種最常用
在這裡插入圖片描述

四、Struts2攔截器(interceptor)

攔截器的概述

  1. 攔截器是struts2裡面的概念
  2. struts2框架封裝的功能都是在攔截器裡面
  3. 在沒有自定義攔截器的情況下,每次執行action,預設只會執行預設的攔截器
    下圖是常量的位置:
    在這裡插入圖片描述
    下圖是struts2裡面預設攔截器的位置:
    在這裡插入圖片描述
    這個檔案結構跟自己定義的struts.xml結構差不多
    其中的package標籤名字就是struts-default,還定義了result-type,預設是dispatcher
    在這裡插入圖片描述
    這裡還指定了預設的攔截器棧
    在這裡插入圖片描述

在這個檔案中<interceptors>裡面定義了大量的<interceptor>這些就是定義的攔截器,還有一些攔截器棧
在這裡插入圖片描述
下圖這些只是引用<interceptor-ref>,真正的定義攔截器是在上面定義的
在這裡插入圖片描述
4. 攔截器的執行時間:
在action建立之後,執行action中的方法之前 ,執行的攔截器,可以通過在預設的隨便一個攔截器上打個斷點來驗證,會發現先到攔截器中的斷點,再到action中的具體方法中的斷點上

追蹤一個攔截器看一下(就拿這個模型驅動的攔截器來演示一下):
這裡是xml檔案,用ctrl+滑鼠左鍵不能連線到,先選中用ctrl+shift+t來找到該類
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

百度解釋攔截器:
一、概述:
java裡的攔截器是動態攔截Action呼叫的物件。它提供了一種機制可以使開發者可以定義在一個action執行的前後執行的程式碼,也可以在一個action執行前阻止其執行,同時也提供了一種可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中攔截器用於在某個方法或欄位被訪問之前,進行攔截然後在之前或之後加入某些操作。
二、原理:
大部分時候,攔截器方法都是通過代理的方式來呼叫的。Struts 2的攔截器實現相對簡單。當請求到達Struts 2的ServletDispatcher時,Struts 2會查詢配置檔案,並根據其配置例項化相對的攔截器物件,然後串成一個列表(list),最後一個一個地呼叫列表中的攔截器。Struts2攔截器是可插拔的,攔截器是AOP的一種實現。Struts2攔截器棧就是將攔截器按一定的順序聯結成一條鏈。在訪問被攔截的方法或欄位時,Struts2攔截器鏈中的攔截器就會按其之前定義的順序被呼叫。
三、定義一個攔截器
自定義一個攔截器需要三步:
1 .自定義一個實現Interceptor介面(或者繼承自AbstractInterceptor)的類。
2 .在struts.xml中註冊上一步中定義的攔截器。
3 .在需要使用的Action中引用上述定義的攔截器,為了方便也可將攔截器定義為預設的攔截器,這樣在不加特殊宣告的情況下所有的Action都被這個攔截器攔截。
四、與過濾器的區別:
過濾器可以簡單理解為“取你所想取”,忽視掉那些你不想要的東西;攔截器可以簡單理解為“拒你所想拒”,關心你想要拒絕掉哪些東西,比如一個BBS論壇上攔截掉敏感詞彙。
1.攔截器是基於java反射機制的,而過濾器是基於函式回撥的。
2.攔截器不依賴於servlet容器,而過濾器依賴於servlet容器。
3.攔截器只對action起作用,而過濾器幾乎可以對所有請求起作用。
4.攔截器可以訪問action上下文、值棧裡的物件,而過濾器不能。
5.在action的生命週期裡,攔截器可以多起呼叫,而過濾器只能在容器初始化時呼叫一次。

攔截器底層原理

1 攔截器底層使用兩個原理
第一個 aop思想(aop的底層是動態代理)
(0)後面在spring裡面把aop做更深層次分析
(1)文字描述:
Aop是面向切面(方面)程式設計:有個基本功能,需要擴充套件功能,不通過修改原始碼方式擴充套件功能。
(2)畫圖分析:
在這裡插入圖片描述
第二個 責任鏈模式
(1)在java中有很多的設計模式,責任鏈模式是其中的一種
(2)責任鏈模式和過濾鏈很相似的
責任鏈模式:
要執行多個操作,有新增、修改、刪除三個操作。
首先執行新增操作,新增操作執行之後 做類似於放行操作,執行修改操作,修改操作執行之後做類似於放行操作,執行刪除操作
過濾鏈:一個請求可有多個過濾器進行過濾,每個過濾器只有做放行才能到下一個過濾器
在這裡插入圖片描述
2 aop思想和責任鏈模式如何應用到攔截器裡面?

(1)文字描述:

  • 攔截器在action物件建立之後,action的方法執行之前執行

  • 在action方法執行之前執行預設攔截器,執行過程使用aop思想,在action沒有直接呼叫攔截器的方法,使用配置檔案方式進行操作

  • 在執行攔截器時候,執行很多的攔截器,這個過程使用責任鏈模式
    – 假如執行三個攔截器,執行攔截器1,執行攔截器1之後做放行操作,執行攔截器2,執行攔截器2之後做放行,執行攔截器3,執行攔截器3之後放行,執行action的方法

(2)畫圖分析
在這裡插入圖片描述

3 檢視原始碼
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
原始碼主要步驟:
在這裡插入圖片描述

重要概念

1 過濾器和攔截器區別
(1)過濾器:伺服器啟動時建立,過濾器理論上可以任意內容,比如html、jsp、servlet、圖片路徑
(2)攔截器:攔截器只可以攔截action

2 Servlet和action區別
(1)servlet預設第一次訪問時候建立,建立一次,單例項物件
(2)action每次訪問時候建立,建立多次,多例項物件

自定義攔截器

在這裡插入圖片描述

自定義登入攔截器

1 需求:在專案中,有很多的action的超連結,實現只有是登入的狀態,才可以點選action的超連結實現功能,如果不是登入狀態,點選action超連結返回到登入頁面

2 登入的狀態:使用session域物件實現
(1)登入成功之後,把資料放到session裡面
(2)判斷session是否有值,可以知道是否是登入狀態

3 實現登入的基本功能
(1)查詢資料庫判斷使用者名稱和密碼
在這裡插入圖片描述
此時可以在jsp頁面用EL表示式來獲取到session域中的資訊
在這裡插入圖片描述

4 新增登入攔截器功能
(1)判斷是否登入:判斷session裡面是否有名稱是username的值
(2)攔截器實現過程
第一步 建立類,繼承MethodFilterInterceptor類
第二步 重寫MethodFilterInterceptor類裡面的方法寫攔截器邏輯
在這裡插入圖片描述
第三步 配置action和攔截器關係(註冊攔截器)
(1)在要攔截的action標籤所在的package標籤裡面宣告攔截器

在這裡插入圖片描述

(2)在具體的action標籤裡面使用宣告的攔截器
在這裡插入圖片描述
(3)struts2裡面執行很多的預設攔截器,但是如果在action裡面配置自定義攔截器,
問題:預設的攔截器不會執行了,如果沒有到預設攔截器中的功能也可以不引用。
解決:把預設攔截器手動使用一次
在這裡插入圖片描述
5 配置的攔截器,會對action裡面所有的方法都進行攔截
(1)在action裡面有login的登入的方法,這個方法不需要攔截,如果這個方法都攔截,問題是,永遠登入不進去了

(2)解決:讓login方法不進行攔截
這裡就是為什麼要繼承MethodFilterIntercepor類的原因了,如果繼承的是AbstractInterceptor類需要用反射的方法才讓實現讓一些方法不攔截,而繼承這個類直接就可以使用配置的方式來實現,如下:

  • 直接通過配置方式讓action裡面某些方法不進行攔截,多個方法用逗號分隔
    在這裡插入圖片描述
    6 如果登入狀態,直接到功能頁面,如果不是登入顯示登陸頁面
    登入之後出現小問題:
    在這裡插入圖片描述
    原因:
    在這裡插入圖片描述
    解決:設定開啟的位置是在父視窗中開啟,這個target在以前a標籤中見過
    在這裡插入圖片描述