Struts2基础
1.Struts2 Actions動作?
Actions是Struts2框架的核心,因為它們適用于任何MVC(Model View Controller)框架。 每個URL映射到特定的action,其提供處理來自用戶的請求所需的處理邏輯。
但action還有另外兩個重要的功能。 首先,action在將數據從請求傳遞到視圖(無論是JSP還是其他類型的結果)方面起著重要作用。 第二,action必須協助框架確定哪個結果應該呈現在響應請求的視圖中。
2.Struts2 攔截器
攔截器在概念上與servlet過濾器或JDK代理類相同。攔截器允許橫切功能,把action以及框架分開實現。你可以使用攔截器實現以下操作:
-
在調用action之前提供預處理邏輯。
-
在調用action后提供后處理邏輯。
-
捕獲異常,以便可以執行備用處理。
Struts2框架中提供的許多功能都是使用攔截器實現的,包括異常處理,文件上傳,生命周期回調和驗證等。事實上,由于Struts2將其大部分功能基于攔截器,因此不太可能為每個action分配7個或8個攔截器。
Struts2框架攔截器
Struts 2框架提供了一個良好的開箱即用的攔截器列表,這些攔截器預先配置好并可以使用。 下面列出了幾個重要的攔截器:
| 1 | alias 允許參數在請求之間使用不同的別名。 |
| 2 | checkbox 通過為未檢查的復選框添加參數值false,以輔助管理復選框。 |
| 3 | conversionError 將字符串轉換為參數類型的錯誤信息放置到action的錯誤字段中。 |
| 4 | createSession 自動創建HTTP會話(如果尚不存在)。 |
| 5 | debugging 為開發人員提供一些不同的調試屏幕。 |
| 6 | execAndWait 當action在后臺執行時,將用戶發送到中間的等待頁面。 |
| 7 | exception 映射從action到結果拋出的異常,允許通過重定向自動處理異常。 |
| 8 | fileUpload 便于文件上傳。 |
| 9 | i18n 在用戶會話期間跟蹤選定的區域。 |
| 10 | logger 通過輸出正在執行的action的名稱提供簡單的日志記錄。 |
| 11 | params 設置action上的請求參數。 |
| 12 | prepare 這通常用于執行預處理工作,例如設置數據庫連接。 |
| 13 | profile 允許記錄action的簡單分析信息。 |
| 14 | scope 在會話或應用程序范圍內存儲和檢索action的狀態。 |
| 15 | ServletConfig 提供可訪問各種基于servlet信息的action。 |
| 16 | timer 以action執行時間的形式提供簡單的分析信息。 |
| 17 | token 檢查action的有效性,以防止重復提交表單。 |
| 18 | validation 提供action的驗證支持。 |
你可以閱讀Struts 2文檔,了解上述攔截器的完整信息。接下來我們會告訴你如何在Struts應用程序中使用攔截器。
如何使用攔截器?
?
讓我們看看如何在我們的“Hello World”程序中使用一個已經存在的攔截器。我們將首先使用timer攔截器,目的是測量執行action方法所需的時間。同時我們使用params攔截器,目的是將請求參數發送給action。你可以嘗試不在你的例子中使用這個攔截器,然后你會發現name屬性沒有被設置,因為參數無法發送給action。
我們可以保留HelloWorldAction.java,web.xml,HelloWorld.jsp和index.jsp文件,因為它們已在Hellow World示例一章中創建過了,然后讓我們參照下面修改struts.xml文件給它添加攔截器:
現在,在給定文本框中輸入任意單詞,然后單擊Say Hello按鈕執行定義的action。如果你去查看生成的日志,會看到以下文本
現在,在給定文本框中輸入任意單詞,然后單擊Say Hello按鈕執行定義的action。如果你去查看生成的日志,會看到以下文本這里的最后一行是由timer攔截器生成的,是表示ation總共需要109ms來執行。
創建自定義攔截器
在你的應用程序中使用自定義攔截器是提供跨切割應用程序功能的簡潔方式。創建自定義攔截器很容易,需要擴展的是以下Interceptor接口:
public interface Interceptor extends Serializable{void destroy();void init();String intercept(ActionInvocation invocation)throws Exception; }正如name所指出的,init()方法提供了一種初始化攔截器的方法,而destroy()方法為攔截器清理提供了一個工具。與action不同,攔截器在請求之間重復使用,需要線程安全,特別是intercept()方法。
ActionInvocation對象可訪問運行時的環境。它允許訪問action本身以及方法來調用action,并確定action是否已被調用。
如果你不需要初始化或清理代碼,可以擴展AbstractInterceptor類,以實現init()和destroy()的默認的無操作指令。
?
創建攔截器類
我們接下來在Java Resources>src文件夾中創建以下MyInterceptor.java文件:
package cn.w3cschool.struts2;import java.util.*; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class MyInterceptor extends AbstractInterceptor {public String intercept(ActionInvocation invocation)throws Exception{/* let us do some pre-processing */String output = "Pre-Processing"; System.out.println(output);/* let us call action or next interceptor */String result = invocation.invoke();/* let us do some post-processing */output = "Post-Processing"; System.out.println(output);return result;} }你可以發現,實際中action將通過攔截器使用invocation.invoke()調用執行,所以你可以根據你的需求做一些預處理和一些后處理。
框架本身通過第一次調用ActionInvocation對象的invoke()來啟動進程。每次調用invoke()時,ActionInvocation都會查詢其狀態,并執行下一個攔截器。當所有配置的攔截器都被調用時,invoke()將使得action本身被執行。以下圖表通過請求流顯示了所說的概念:
?
配置文件
現在我們需要注冊新的攔截器,然后調用它,因為我們在前面的例子中調用的是默認攔截器。要注冊一個新的攔截器,把<interceptors> ... </ interceptors>標簽直接放置在<package>標簽下的struts.xml文件中即可。對于默認攔截器,你可以跳過此步驟,就像我們前面的示例中所做的那樣。但現在讓我們使用以下方法注冊新的:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><constant name="struts.devMode" value="true" /><package name="helloworld" extends="struts-default"><interceptors><interceptor name="myinterceptor"class="cn.w3cschool.struts2.MyInterceptor" /></interceptors><action name="hello" class="cn.w3cschool.struts2.HelloWorldAction" method="execute"><interceptor-ref name="params"/><interceptor-ref name="myinterceptor" /><result name="success">/HelloWorld.jsp</result></action></package> </struts>?
需要注意的是,你可以在<package>標簽內注冊多個攔截器,同時可以在<action>標簽內調用多個攔截器,也可以用不同的action調用同一個攔截器。
web.xml文件需要在WebContent下的WEB-INF文件夾下創建,如下所示:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID" version="3.0"><display-name>Struts 2</display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class></filter>?
攔截器堆棧
<interceptor-stack name="basicStack"><interceptor-ref name="exception"/><interceptor-ref name="servlet-config"/><interceptor-ref name="prepare"/><interceptor-ref name="checkbox"/><interceptor-ref name="params"/><interceptor-ref name="conversionError"/> </interceptor-stack>?
?
你可以想象,為每個action配置的多個攔截器將很快變得極其難以管理。為此,攔截器使用攔截器堆棧進行管理。這里是直接從struts-default.xml文件展示的一個例子:
?
?面的堆棧稱為basicStack,可以如下所述在你的配置中使用,此配置節點放置在<package ... />節點下。<interceptor-ref ... />標簽引用的是在當前攔截器堆棧之前配置的攔截器或攔截器堆棧。因此非常重要的是在配置初始攔截器和攔截器堆棧時,確保name在所有攔截器和攔截器堆棧配置中是唯一的。
我們已經學習了如何將攔截器應用到action中,而攔截器堆棧的應用也是類似的。事實上,使用的標簽也是一樣的:
?
<action name="hello" class="com.tutorialspoint.struts2.MyAction"><interceptor-ref name="basicStack"/><result>view.jsp</result> </action上述的“basicStack”注冊將完整注冊hello action的所使用的六個攔截器。要注意的是,攔截器按照它們被配置的順序執行。例如,在上面的例子中,exception將首先執行,第二個將是servlet-config等。?
3.Struts2 結果類型
如前面所述,<results>標簽在Struts2 MVC框架中扮演視圖的角色。Action負責執行業務邏輯,下一步就是使用<results>標簽顯示視圖。
通常有一些導航規則附加的結果。例如,如果action是進行驗證用戶,則有三種可能的結果:(a)成功登錄(b)登錄失敗:用戶名或密碼不正確(c)帳戶鎖定。
在這種情況下,action將配置三個可能的結果字符串和三個不同的視圖來渲染結果,這在我們前面的例子中已經看到過了。
但是,Struts2不綁定使用JSP作為視圖技術。畢竟,MVC范例的目的是保持圖層分離和高度可配置。例如,對于Web2.0客戶端,你可能希望返回XML或JSON作為輸出。在這種情況下,你可以為XML或JSON創建一個新的結果類型并實現這一點。
Struts提供了許多預定義的結果類型,我們已經看到的是默認的結果類型dispatcher,它用于分發到JSP頁面。Struts允許你使用其他標記語言為視圖技術呈現結果,較常選用的包括Velocity,Freemaker,XSLT和Tiles。?
dispatcher結果類型?
dispatcher結果類型是默認的類型,如果未指定其他結果類型,則使用此類型。它用于轉發到服務器上的servlet,JSP,HTML等頁面。它使用RequestDispatcher.forward()方法。
我們在前面的示例中看到了“簡寫”版本,里面我們用一個JSP路徑作為結果標簽的主體。
我們還可以使用<result ...>元素中的<param name="location">標簽來指定JSP文件,如下所示:
<result name="success" type="dispatcher"><param name="location">/HelloWorld.jsp</param > </result>FreeMaker結果類型
在這個例子中,我們將介紹如何使用FreeMaker作為視圖技術。Freemaker是一個流行的模板引擎,使用預定義的模板生成輸出。讓我們創建一個包含以下內容的名為hello.fm的Freemaker模板文件:
Hello World ${name}上面的文件是一個模板,其中name是一個參數,將使用定義的action從外部傳遞。你可以在CLASSPATH中保留此文件。接下來,讓我們參考下面修改struts.xml以指定結果:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"><struts><constant name="struts.devMode" value="true" /><package name="helloworld" extends="struts-default"><action name="hello" class="cn.w3cschool.struts2.HelloWorldAction"method="execute"><result name="success" type="freemarker"><param name="location">/hello.fm</param></result></action></package></struts>redirect結果類型?
redirect結果類型調用標準的response.sendRedirect()方法,使得瀏覽器向給定的位置創建一個新請求。
我們可以在<result...>元素的主體中或作為<param name="location">的元素中給定位置。redirect也支持parse參數,以下是使用XML配置的示例:
所以只需修改你的struts.xml文件來定義上面提到的redirect結果類型,并創建一個新的文件NewWorld.jpg,那么當你的hello action返回“success”時就會產生redirect結果。你可以檢查Struts 2的Redirect Action示例,以便更詳細地了解。
Struts2 值棧/OGNL
值棧是一組對象,按照提供的順序存儲以下這些對象:
| 1 | Temporary對象 實際中存在各種在頁面執行期間創建的temporary對象。例如,JSP標簽循環集合的當前迭代值。 |
| 2 | Model對象 如果在struts應用程序中使用Model對象,則當前Model對象放在值堆棧上的action之前。 |
| 3 | Action對象 這是指正在執行的當前action對象。 |
| 4 | 命名對象 這些對象包括#application,#session,#request,#attr和#parameters以及所引用的相應的servlet作用域。 |
值棧可以通過為JSP,Velocity或Freemarker提供的標簽進行訪問。我們將在單獨的章節中學習到用于獲取和設置struts2 值棧的各種標簽。你可以在action中獲取值棧對象,如下所示:
ActionContext.getContext().getValueStack()一旦你有一個值棧對象,你可以使用以下方法來操縱該對象:
| 1 | Object findValue(String expr) 通過在默認搜索順序中對值棧評估所給定的表達式來查找值。 |
| 2 | CompoundRoot getRoot() 獲取將對象推入值棧的CompoundRoot。 |
| 3 | Object peek() 獲取值棧頂部的對象而不改變值棧。 |
| 4 | Object pop() 獲取值棧頂部的對象,并將其從值棧中刪除。 |
| 5 | void push(Object o) 將對象放在值棧的頂部。 |
| 6 | void set(String key,Object o) 使用給定的key在值棧上設置一個對象,使其可通過findValue(key,...)檢索。 |
| 7 | void setDefaultType(Class defaultType) 設置在獲取值時要轉換的默認類型。 |
| 8 | void setValue(String expr,Object value) 嘗試使用由默認搜索順序給定的表達式在值棧的bean上設置屬性。 |
| 9 | int size() 獲取值棧中的對象數。 |
OGNL
?
OGNL(Object-Graph Navigation Language,對象圖導航語言)是一種強大的表達式語言,用于引用和操作值棧上的數據,還可用于數據傳輸和類型轉換。
OGNL非常類似于JSP表達式語言。OGNL基于上下文中存有根對象或默認對象的理念,使用標記符號(即#號)來引用默認或根對象的屬性。
如前面所述,OGNL是基于上下文的,而Struts構建了一個ActionContext映射以供OGNL使用。 ActionContext映射包含以下內容:
?
-
應用程序?-?應用程序作用域變量
-
會話?-?會話作用域變量
-
根/值棧?-?所有的action變量都存儲在這里
-
請求?- 請求作用域變量
-
參數?- 請求參數
-
屬性?-?存儲在頁面,請求,會話和應用程序作用域中的屬性
?
有必要了解的是,Action對象在值棧中總是可用的,因此如果你的Action對象有x和y屬性,你可以隨時使用。
ActionContext中的對象使用#號引用,但是,值棧中的對象可以直接引用,例如,如果employee是action類的屬性,則可以按如下方式引用:
果你在會話中有一個名為“login”的屬性,你可以按如下方式檢索:
<s:property value="#session.login"/>OGNL還支持處理集合 - 即Map,List和Set。例如,要顯示顏色的下拉列表,你可以執行以下操作:
<s:select name="color" list="{'red','yellow','green'}" />?
OGNL表達式很智能地將“紅色”,“黃色”,“綠色”解釋為顏色,并基于此構建了列表。
在下一章我們學習各種的標簽時,OGNL表達式將會廣泛的用到。因此,不要用孤立的方式去了解OGNL,讓我們結合Form標簽/Control標簽/Data標簽和Ajax標簽部分中的一些示例來了解它。
值棧/ OGNL示例
創建Action:
讓我們參考下面用于訪問值棧的action類,然后在ie.JSP視圖頁面設置使用OGNL進行訪問的幾個key。
package cn.w3cschool.struts2;import java.util.*; import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport;public class HelloWorldAction extends ActionSupport{private String name;public String execute() throws Exception {ValueStack stack = ActionContext.getContext().getValueStack();Map<String, Object> context = new HashMap<String, Object>();context.put("key1", new String("This is key1")); context.put("key2", new String("This is key2"));stack.push(context);System.out.println("Size of the valueStack: " + stack.size());return "success";} public String getName() {return name;}public void setName(String name) {this.name = name;} }實際上,Struts 2在執行時會將action添加到值棧的頂部。所以,通常放置東西在值棧的方法是添加getters/setters的值到Action類,然后使用<s:property>標簽訪問值。我們前面已展示了ActionContext和值棧在struts中的工作原理。
創建視圖
在你的eclipse項目的WebContent文件夾中創建下面的jsp文件HelloWorld.jsp,如果action返回為success將顯示視圖:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body>Entered value : <s:property value="name"/><br/>Value of key 1 : <s:property value="key1" /><br/>Value of key 2 : <s:property value="key2" /> <br/> </body> </html>我們還需要在WebContent文件夾中創建index.jsp文件,其內容如下:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"pageEncoding="ISO-8859-1"%> <%@ taglib prefix="s" uri="/struts-tags"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Hello World</title> </head> <body><h1>Hello World From Struts2</h1><form action="hello"><label for="name">Please enter your name</label><br/><input type="text" name="name"/><input type="submit" value="Say Hello"/></form> </body> </html>配置文件
以下是struts.xml文件的內容
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><constant name="struts.devMode" value="true" /><package name="helloworld" extends="struts-default"><action name="hello" class="cn.w3cschool.struts2.HelloWorldAction" method="execute"><result name="success">/HelloWorld.jsp</result></action></package> </struts>以下是web.xml文件的內容:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"id="WebApp_ID" version="3.0"><display-name>Struts 2</display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class></filter><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping> </web-app>?
轉載于:https://www.cnblogs.com/lukelook/p/11125374.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: 为什么要用 redis/为什么要用缓存
- 下一篇: SpeedFan 控制风扇转速