第一部分
- Struts2框架介紹
Struts2是一個基於MVC設計模式的Web應用框架,它本質上相當於一個servlet,在MVC設計模式中,Struts2作爲控制器(Controller)來建立模型與視圖的數據交互。Struts2=struts1+webwork 。
問題:struts2是一個mvc框架,它的mvc是什麼?
javaweb開發中的mvc,是在jsp的model2模式中提過
Model------javabean
View--------jsp
Controller----servlet
核心點:
- 攔截器 interceptor;
- Action;
- ognl與valueStack;
Struts2框架流程
一個簡單的登錄案例:
在這個案例中,我們要使用struts2框架怎樣解決。
重點:
- struts2框架如何完成原來由servlet完成的工作。
- Struts2框架如何完成請求參數的封裝處理
- Struts2框架如何完成頁面跳轉。
- 簡單登錄案例原型
需要三個jsp頁面 login.jsp success.jsp failer.jsp
還需要一個servlet LoginServlet 主要完成的是業務邏輯操作。
login.jsp
LoginServlet
- Struts2框架來完成登錄操作
怎樣使用strtuts2框架步驟:
- 導入相關的jar文件;
- 需要在web.xml文件中配置一個Filter(只有配置了它纔可以使用struts2框架);
- struts.xml配置;
- 創建Action來完成邏輯操作;
快速入門:
使用的是struts2 2.3.24版本;使用strtus2框架不是直接將它的lib包下的所有的jar文件copy到項目中,而是使用其中的一部分。
我們可以參考它的示例代碼:
- 導入13個jar包
- 需要在web.xml文件中配置StrutsPrepareAndExecuteFilter
- 創建一個struts.xml文件,它的位置是可以放置在src下。
代碼實現:
jsp頁面
Action
struts.xml文件配置
流程分析:
使用struts2完成簡單登錄操作:
- login.jsp頁面不變動
- 創建一個LoginAction來完成邏輯操作
- 在struts.xml文件中完成配置操作
問題1?在LoginAction中如何得到username與password?
可以直接在Action類中提供成員屬性,併爲其提供get/set方法。就可以得到請求參數。
問題2:如果實現路徑跳轉?
- 我們可以給action中的方法添加一個String返回值
- 在struts.xml配置文件中,在其對應的action配置上通過<result>來確定跳轉的路徑
- Struts2框架執行流程
- 當通過瀏覽器發送一個請求;
- 會被StrutsPrepareAndExecuteFilter攔截;
- 會調用strtus2框架默認的攔截器(interceptor)完成部分功能;
- 在執行Action中操作;
- 根據Action中方法的執行結果來選擇來跳轉頁面Resutl視圖。
一般管StrutsPrepareAndExecuteFilter 叫做前端控制器(核心控制器),只有配置了這個filter我們的strtus2框架才能使用。
Strtus2的默認攔截器(interceptor)它們是在struts-default.xml文件中配置
注意:這上xml文件是在strtus-core.jar包中。
默認的攔截器是在defaultStack中定義的。
- Struts2配置詳解
Struts2配置文件加載順序:
第一個加載的是default.properties文件
位置:strtus2-core.jar包 ,org.apache.struts2包下
作用:主要是聲明瞭struts2框架的常量
第二個加載的是一批配置文件
Strtus-default.xml
位置:struts2-corl.jar ,作用:聲明瞭interceptor result bean。
Strtus-plugin.xml
位置:在strtus2的插件包中,作用:主要用於插件的配置聲明。
Strtus.xml
位置:在我們自己的工程中,作用:用於我們自己工程使用strtus2框架的配置。
第三個加載的是自定義的strtus.properties
位置:都是在自己工程的src下,作用:定製常量。
第四自定義配置提供
第五加載的是web.xml配置文件
主要是加載strtus2框架在web.xml文件中的相關配置.
第六 bean相關配置
重點掌握:
- Default.properties
- Struts-default.xml
- Struts-plugin.xml
- Strtus.xml
- web.xml
struts.xml文件配置介紹:
package配置:
- name屬性 作用:定義一個包的名稱,它必須唯一。
- namespace屬性 作用:主要是與action標籤的name屬性聯合使用來確定一個action的訪問路徑。
- extends屬性作用:指定繼承自哪個包。一般值是strtus-default。strtus-default包是在strtus-default.xml文件中聲明的。
- abstruct屬性它代表當前包是一個抽象的,主要是用於被繼承。
action配置:
- name屬性作用:主要是與package的namespace聯合使用來確定一個action的訪問路徑;
- class屬性作用:用於指示當前的action類;
- method屬性作用:用於指示當前的action類中的哪個方法執行;
result配置:
它主要是用於指示結果視圖
- name屬性作用是與action類的method方法的返回值進行匹配,來確定跳轉路徑;
- type屬性 作用是用於指定跳轉方式;
擴展:
關於action配置中的class與method的默認值以及result中的name與type 默認值問題。
原因:strtus-default.xml文件中配置。
它的作用就是當一個請求來時,如果查找不到指定的class及對應的method就會執行ActionSupport類中的execute方法。在這個類的execute方法中默認返回的是”success”也就是說,result的name屬性默認值是success,默認的跳轉方式是請求轉發 dispatcher。
常量配置:
default.properties文件中定義了struts2框架常用常量 。
問題:我們怎樣可以定義常量
- 可以在src下創建一個strtus.properties配置文件
- 可以在web.xml文件中配置
- 可以直接在strtus.xml文件中定義常量 (推薦)
注意:後加載的配置文件中的常量會將先加載的常量覆蓋
- Struts2的Action詳解
Struts2中的action,主要是完成業務邏輯操作。Action替代在servlet中完成的作用。
Action的學習主要有兩點:
- 如何創建一個struts2的action
- 如果訪問一個struts2的action
Action類創建方式(三種)
1、創建一個pojo類
Pojo(plani Ordinary java object)簡單的java對象
Pojo類就是沒有實現任何接口沒有繼承任何類
優點:無耦合 ,缺點:所有的功能都要自己完成。
2、創建一個類實現一個Action接口
com.opensymphony.xwork2.Action
在Action接口中定義了五個常量,一個execute方法
五個常量:它們是默認的五個結果視圖<result name=””>:
ERROR : 錯誤視圖
INPUT: 它是struts2框架中interceptor中發現問題後會訪問的一個視圖
LOGIN:它是一個登錄視圖,可以在權限操作中使用
NONE:它代表的是null,什麼都不做(也不會做跳轉操作)
SUCCESS:這是一個成功視圖
優點:耦合度低,缺點:還是需要自己來完成功能。
3、創建一個類繼承ActionSupport類
com.opensymphony.xwork2.ActionSupport
ActionSupport類也實現了Action接口。我們在開發中一般會使用這種方案:
優點:具有豐富的功能,例如 表單校驗 錯誤信息設置 國際化,缺點:耦合度高。
action的訪問方式:
- 直接通過<action>標籤來配置,通過method來指定訪問的方法,如果method沒有,默認訪問的是execute方法。
- 簡化的action訪問方式,可以使用*通配符來訪問。
這種方式的缺點:不建議使用過多的*號,它帶來程序閱讀障礙,不便於理解
使用*來簡化操作方案,它對名稱規範必須進行一個統一。
擴展--動態方法調用:
這是strtus2提供的動態方法調用。
注意:對於strtus2的動態方法調用,要想使用我們必須配置一個常量來開啓動態方法調用
這代表動態方法調用沒有開啓。
個人不建議使用動態方法調用
- Struts2框架封裝數據
主要解決的問題:是在action中如果獲取請求參數
主要有兩種方式:
1、屬性驅動
- 直接在action類中提供與請求參數匹配屬性,提供get/set方法;
- 在action類中創始一個javaBean,對其提供get/set ,在請求時頁面上要進行修改, 例如 user.username user.password ,要使用ognl表達式;
以上兩種方式的優缺點:
第一種比較簡單,在實際操作我們需要將action的屬性在賦值給模型(javaBean) 去操作。
第二種:不需要在直接將值給javaBean過程,因爲直接將數據封裝到了javaBean中。它要求在頁面上必須使用ognl表達式,就存在頁面不通用問題。
2、模型驅動
步驟:
- 讓Action類要實現一個指定接口ModelDriven
- 實例化模型對象(就是要new出來javaBean)
- 重寫getModel方法將實例化的模型返回。
對於模型驅動它與屬性驅動對比,在實際開發中使用比較多,模型驅動缺點,它只能對 一個模型數據進行封裝。
3.request.getParameter()的傳統方法
- 總結:主要內容是圍繞着簡單的登錄案例來講解
- 關於strtus2框架的環境搭建;
- 關於strtus2框架配置;
- 關於strtus2框架請求參數封裝;
- 關於strtus2框架的路徑跳轉;
關於action訪問的配置:
<package name=”” namespace=”” extends=””>
<action name=”” class=”” method=””>
<result name=”” type=””>路徑</result>
</action>
</package>
關於路徑跳轉問題:
是通過<result>來配置跳轉的路徑,它的name屬性是與action中的方法的返回值進行對比的。
它的type屬性可以取哪些值?
默認值是dispatcher 它代表的是請求轉發。針對於jsp頁面
redirect 它代表的是重定向 針對於jsp頁面
chain 它類似於請示轉發,只不過它是針對於action跳轉.
redirectAction 它類似於重定向 針對於action
關於路徑跳轉的配置:
可以直接在<package>下創建全局的result
Struts2-第二部分
- Struts2中獲取Servlet API
簡單說,可以在action類中獲取request response session...對象
有兩種方案:
1、ServletActionContext獲取
org.apache.struts2.ServletActionContext
2、採用注入方式
Struts2框架在運行時,請求會被StrutsPrepareAndExecuteFilter攔截,會根據請求,去 strtus.xml文件中查找到匹配的action,在action執行前,會走一些interceptor。默認執行的攔截器是struts-default.xml文件中定義的。
在默認執行的攔截器中有一個:
查看一下ServletConfigInterceptor源代碼
以下是部分源代碼:
ServletRequestAware, 實現這個接口可以獲取HttpServletRequest
ServletResponseAware ,實現這個接口可以獲取HttpServletResponse
ServletContextAware 實現這個接口可以獲取ServletContext
- OGNL表達式
OGNL是Object-Graph Navigation Language(對象圖導航語言)的縮寫,它是一種功能強大的表達式語言,通過它簡單一致的表達式語法,可以存取對象的任意屬性,調用對象的方法,遍歷整個對象的結構圖,實現字段類型轉化等功能。它使用相同的表達式去存取對象的屬性。
Strtsu2框架內置了OGNL
OGNL本身也是一個項目,它是可以單獨使用。
OGNL作用:
支持對象的操作,調用對象的方法
支持靜態成員訪問
支持賦值操作與表達串聯
訪問OGNL上下文,訪問ActionContext
操作集合對象。
搭建環境:單獨使用OGNL來完成示例。
OGNL三要素: 表達式 、OgnlContext 上下文 、Root 根。
1、支持對象操作
2、支持靜態成員訪問
3、訪問Ognl上下文
如果從根中獲取數據,不需要添加#號,如果不是從根中獲取,需要#。
4、操作集合
支持賦值操作與表達式串聯
Strtus2框架中如何使用ognl表達式:
在struts2框架中我們使用ognl表達式的作用是從valueStack中獲取數據。我們在struts2框架中可以使用ognl+valueStack達到在頁面(jsp)上來獲取相關的數據。要想在jsp頁面上使用ognl表達式,就需要結合struts2框架的標籤<s:property value=”表達式”>來使用。
- valueStack 值棧
valueStack介紹:
我們使用valueStack的主要目的是爲我將我們action中產生的數據攜帶到頁面上,也就是說valueStack它就是一個容器。
在Struts2框架中將valueStack設計成一個接口。
com.opensymphony.xwork2.util.ValueStack
我們主要使用的是它的實現類
com.opensymphony.xwork2.ognl.OgnlValueStack。
當客戶端向我們發送一個請求,服務器就會創始一個Action來處理請求,struts2中的action是一個多例,每一次請求都會有一個新的action對應。所以它不存在線程安全問題。
一個valueStack對應一個action,valueStack貫穿整個action的生命週期。
rquest-------Action------ValueStack
struts2框架將valueStack保存在request中。
valueStack內部結構:
valueStack主要有兩部分組成:
CompoundRoot:它就是一個ArrayList,它主要存儲的是action的相關數據。
Map<String,Object> context:就是一個Map,Context中主要存儲了一些引用,這個引用主要是關於web開發中相關信息。
pameters :請求參數。
request:請求對象中所有屬性。
session:會話對象中所有屬性。
application:application對象中的所有發展。
以上都是Map。在struts2框架中我們通過ognl表達式來獲取valueStack中數據,沒有使用#就會從CompoundRoot中獲取數據,
如果使用#來獲取,這時就會從context中來獲取。
獲取ValueStack:
第一種方式:可以直接通過request對象來獲取.
第二種方式:使用ActionContext來獲取
1、ActionContext是什麼?
ActionContext它是action上下文,strtus2框架它使用actionContext來保存Action在執行過程中所需要的一些對象,例如 session, application…
ActionContext的獲取是通過它的靜態方法getContext()得到。
Struts2會根據每一次的http請求來創建對應的ActionContext,它是與當前線程綁定的。
每一次請求,就是一個線程,對應着一個request,每一次請求,會創建一個Action,每一個action對應一個ActionContext.每一次請求也對應着一個valueStack。
request---ActionContext----Action-----ValueStack它們都對應着一次請求(一個線程).
valueStack與ActionContext本質上是可以獲取
2、valueStack操作---存儲數據:
注意:我們使用valueStack來存儲數據時,主要是向root中存儲。
介紹兩部分:
手動向valueStack存儲數據:
Struts2框架自動向valueStack中存儲數據:
每次請求,訪問action,這個對象會存儲到valueStack中。
在DefaultActionInvocation的init方法內
在ModelDrivernInterceptor中
以上代碼會將模型對象存儲到valueStack中。
3、valueStack操作-獲取數據
在頁面中獲取
Action中屬性
使用模型驅動
訪問時的路徑
http://localhost:8080/struts2-day02/vs?username=tom&password=123
在action類中的業務處理時,又對user對象重新賦值
在頁面上獲取數據
EL表達式從valueStack中獲取數據:
El表達式可以從valueStack中獲取信息
問題:爲什麼el表達式可以從valueStack中獲取數據?
org.apache.struts2.dispatcher.StrutsRequestWrapper
Struts2框架對request進行了增強,重寫了getAttribute方法,如果在request域中查找不到數據,就會在valueStack中獲取。
Ognl表達式中特殊字符:
OGNL是通常要結合Struts 2的標誌一起使用。主要是#、%和$這三個符號的使用
#號:它是從非root中獲取數據
%用於強制是否要解析ognl表達式
$它主要是從配置文件中來獲取valueStack中數據
valueStack練習
關於登錄失敗處理:
如果用戶登錄時,用戶名或密碼錯誤,將錯誤信息存儲到valueStack中
在login.jsp頁面上獲取錯誤信息展示
注意:在實際開發中,我們一般會讓action去繼承ActionSupport類。
讓action類繼承ActionSupport類
可以使用父類提供的對於錯誤操作的處理
在頁面上可以直接使用struts2提供的標籤來顯示錯誤信息
總結:在struts2中處理簡單的信息(字符串)
在頁面上可以使用對應的標籤來獲取錯誤信息
展示商品信息:
在success.jsp頁面上
創建action
在product.jsp頁面上展示數據
要想在頁面上展示集合信息可以使用<s:iterator>標籤來完成
如果使用var設置別名,它存儲在context中,所以在使用時要添加#號
也可以使用以下方案
我們將List<Product> ps聲明成action的屬性,並提供了get/set方法
也可以在頁面上獲取到ps數據
- Interceptor攔截器
Interceptor介紹 :
Struts2中的interceptor它是基於spring aop思想,而aop思想它本質上是通過動態代理來實現。我們strtus2的攔截器它主要是攔截Action的操作,在action的執行前或執行後進行一些其它的功能操作。
攔截器鏈(攔截器棧)簡單說,就是可以將多個攔截器形成一個鏈,在訪問它們時依次訪問。
以下是struts2的執行流程圖
執行的過程:
當我們發送請求訪問Action時,會被StrutsPrepareAndExecuteFilter攔截
在其doFilter方法內執行了
execute.executeAction(request, response, mapping);
這個代碼執行後
dispatcher.serviceAction(request, response, mapping);
serviceAction方法執行
在這個方法執行過程中會創建Action代理對象
ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
通過proxy去執行了proxy.execute();
在execute方法內
return invocation.invoke();
invocation它是ActionInvocation一個對象
在invoke方法內
會去加載我們的配置文件,將配置文件中所有的interceptor得到進行遍歷。
在struts-default.xml文件中定義了默認加載的攔截器棧 defaultStack
在每一個攔截器的interceptor方法內,又調用了DefaultActionInvocation的invoke方法,其實就是遞歸調用。
Interceptor作用與自定義Interceptor:
我們使用intercep[tor可以在action執行前後進行處理工作。例如,完成權限控制。
問題:如何定義Interceptor?
所有的Interceptor都要實現一個接口
com.opensymphony.xwork2.interceptor.Interceptor
在配置文件中聲明Interceptor
我們也可以將多個interceptor封裝成一個stack
可以在Action的配置中引入自己的interceptor
在使用時name也可以引入一個interceptor stack.
注意:當我們顯示的引入了一個自定義的Interceptor,那麼默認的defaultStack就不會在導入,需要手動導入。
Interceptor練習:
如果用戶沒有登錄,不可以查看所有的商品信息。
創建一個Interceptor
在struts.xml文件中聲明,並在指定的action中引用
完成功能
修改登錄action中操作
將用戶存儲到session中。
在interceptor中完成權限控制
問題1:如何在login指定的視圖頁面上展示錯誤信息,例如權限不足。
問題2:我們在struts.xml文件中配置action時,可以使用*通配置符,這時它可以處理多個方法,你指定的interceptor只想攔截某一個方法,怎樣處理?
我們可以使用Interceptor接口的一個實現類來完成操作
在配置時,就可以指定哪些方法攔截,哪些方法不攔截
Struts2-第三部分
- Struts2文件上傳
文件上傳介紹:
瀏覽器端注意事項::表單提交方式method=post;表單中必須有一個<input type=”file”>組件;表單中必須設置enctype=”multipart/form-data”。
服務器端:Commons-fileupoad.jar包完成。
Struts2框架本身支持文件上傳
問題:struts2框架如何完成文件上傳?
Struts2框架使用一個fileupload的interceptor來完成文件上傳,而我們要使用它在action中我們可以提供類似以下的操作就能完成文件上傳操作。
在execute方法中將文件copy就可以完成文件上傳。
文件上傳快速入門
第一步:創建一個upload.jsp頁面
第二步:創建action
文件上傳注意事項:
文件上傳時出現了問題
現在的問題是我們的action中沒有設置input視圖
在頁面上可以通過
在default.properties中
struts.multipart.maxSize=2097152 (2m)
它是描述文件上傳時允許的最大值
只需要在struts.xml文件中
我們還可以查看FileuploadInterceptor
如果我們上傳時,允許上傳多個文件如何操作?
Action如何處理?
也可以使用List<File> List<String>來控制屬性
在方法中
- Struts2框架Ajax開發
JSON介紹:
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基於ECMAScript的一個子集。 JSON採用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成爲理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網絡傳輸速率)。
JSON結構:
json簡單說就是javascript中的對象和數組,所以這兩種結構就是對象和數組兩種結構,通過這兩種結構可以表示各種複雜的結構。
1、對象:對象在js中表示爲“{}”括起來的內容,數據結構爲 {key:value,key:value,...}的鍵值對的結構,在面向對象的語言中,key爲對象的屬性,value爲對應的屬性值,所以很容易理解,取值方法爲 對象.key 獲取屬性值,這個屬性值的類型可以是 數字、字符串、數組、對象幾種。
2、數組:數組在js中是中括號“[]”括起來的內容,數據結構爲 ["java","javascript","vb",...],取值方式和所有語言中一樣,使用索引獲取,字段值的類型可以是 數字、字符串、數組、對象幾種。經過對象、數組2種結構就可以組合成複雜的數據結構了。
Java中json工具介紹:
Fastjson簡單使用介紹
1、導入jar包
2、對於User對象
3、對於List<User>
如果對Date類型進行格式化輸出
關於屬性是否生成在json串中設置
Jackson簡單使用介紹:
Spring mvc它的底層使用的就是jackson
1.導入jar包
2.使用
處理日期類型
過濾屬性
編碼方案實現
需要在類上添加一個註解
Strtus2框架如何處理ajax請求:
1、可以使用HttpServletResponse響應數據
在struts2框架中可以獲取HttpServletResponse對象,就可以通過response來完成將數據(json)響應到瀏覽器過程
瀏覽器端
需要使用onblure失去焦點事務來處理文本框,向服務器發送ajax請求(jquery完成)
服務器端
數據響應沒有問題,處理中文亂碼
在瀏覽器端處理服務器響應的數據
2、使用strtus2框架的json插件來完成ajax操作:
首先要導入插件包
我們怎樣使用struts2提供的json插件?
- 將我們自己配置文件中的<package extends=”json-default”>.
- Action的返回視圖<result name=”” type=”json”>
- 因爲我們配置了上面兩步,那麼struts2框架就會將valueStack中的棧頂元素轉換成json響應到瀏覽器
案例---查找商品信息:
瀏覽器端操作
服務器端
關於響應的json處理:
1、怎樣忽略屬性
上面這種方案有弊端
在org.apache.struts2.json.JSONResult類中有兩個屬性
它們可以設置響應的數據中是否包含或不包含屬性
2、設置root
沒有設置root前返回的json結構 ps:[{},{}]
設置root它的根爲ps後的返回的json [{},{}]
處理服務器響應數據到瀏覽器展示
- Struts2註解開發
注意:要想使用struts2的註解,我們必須單獨在導入一個jar包。
它是在strtus2的2.1版本後引入
<package name=”” namespace=”” extedns=”>
<action name=”” class=”” method>
<result name=”” type=””>
快速入門:
@Namespace來代替<package namespace=””>
@ParentPackage來代替<package extends=””>
@Action來描述關於<action>配置
value屬性<action name=””>
使用@Action的results來描述關於結果類型的配置<result>
<result name=”” type=””>
@Action(results={@Result(name=””,type=””,location=””)})
其它註解:
@Actions
作用:可以通過多個映射來訪問同一個action
@Results
類似於全局的結果視圖
@InterceptorRef
它是用於處理攔截器的
問題:我們在action類中定義了註解,strtus2框架怎樣識別它們?
原因:我們必須查看插件包中的配置
是在action,actions,struts,struts2這樣的包下掃描註解。
案例-使用註解來完成登錄與顯示商品
1、搭建環境
創建庫與表
DROP DATABASE exam;
CREATE DATABASE exam;
USE exam;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
PASSWORD VARCHAR(20)
);
INSERT INTO USER VALUES(NULL,'tom','123');
INSERT INTO USER VALUES(NULL,'fox','456');
CREATE TABLE product(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
COUNT INT,
price DOUBLE
);
INSERT INTO product VALUES(NULL,'電視機',100,1200);
INSERT INTO product VALUES(NULL,'洗衣機',800,2200);
INSERT INTO product VALUES(NULL,'空調機',10,3200);
導入jar包
Struts2框架的jar包 基本jar包 插件包
C3p0連接池jar包 mysql驅動jar
Dbutils
Jquery的js文件
配置文件
Web.xml文件中配置StrutsPrepareAndExecuteFilter
Src/struts.xml
Src/c3p0.properties
創建package
2、登錄操作
login.jsp
UserAction
UserService
UserDao
product.jsp
3、商品顯示
product.jsp頁面完成部分功能
Action
Service
dao
在product.jsp頁面上處理服務器響應json並展示
4、控制用戶登錄後可以訪問商品展示
Interceptor步驟
- 創建一個類來實現Interceptor接口或繼承MethodFilterInterceptor
- 在struts.xml文件中聲明
- 在action的配置中引用
我們將所有響應到瀏覽器的數據都封裝到Result類中
正確情況下響應的數據
錯誤情況下數據