1. 關於 Struts2 請求的擴展名問題
1). org.apache.struts2 包下的 default.properties 中配置了 Struts2 應用的一些常量
2). struts.action.extension 定義了當前 Struts2 應用可以接受的請求的擴展名.
3). 可以在 struts.xml 文件中以常量配置的方式修改 default.properties 所配置的常量.
<constant name="struts.action.extension" value="action,do,"></constant>
2. ActionSupport
1). ActionSupport 是默認的 Action 類: 若某個 action 節點沒有配置 class 屬性, 則 ActionSupport 即爲
待執行的 Action 類. 而 execute 方法即爲要默認執行的 action 方法
<action name="testActionSupport">
<result>/testActionSupport.jsp</result>
</action>
等同於
<action name="testActionSupport"
class="com.opensymphony.xwork2.ActionSupport"
method="execute">
<result>/testActionSupport.jsp</result>
</action>
2). 在手工完成字段驗證, 顯示錯誤消息, 國際化等情況下, 推薦繼承 ActionSupport.
result:
1). result 是 action 節點的子節點
2). result 代表 action 方法執行後, 可能去的一個目的地
3). 一個 action 節點可以配置多個 result 子節點.
4). result 的 name 屬性值對應着 action 方法可能有的一個返回值.
<result name="index">/index.jsp</result>
5). result 一共有 2 個屬性, 還有一個是 type: 表示結果的響應類型, 默認值爲 dispatcher
6). result 的 type 屬性值在 struts-default 包的 result-types 節點的 name 屬性中定義.
常用的有
> dispatcher(默認的): 轉發. 同 Servlet 中的轉發.
> redirect: 重定向
> redirectAction: 重定向到一個 Action
注意: 通過 redirect 的響應類型也可以便捷的實現 redirectAction 的功能!例子:
<package name="hello" extends="struts-default" >
<action name="ouhe" class="product.ouhe" >
<result type="redirectAction">
<param name="actionName">testAction</param>
<param name="namespace">/a</param>
</result>
</action>
<action name="ouhejiekou" class="product.ouhejiekou" >
<result name="success" type="redirect">/a/testAction.do</result>
</action>
</package>
<package name="lala" extends="struts-default" namespace="/a">
<action name="testAction">
<result >/index2.jsp</result>
</action>
</package>
> chain: 轉發到一個 Action
注意: 不能通過 type=dispatcher 的方式轉發到一個 Action
只能是(例子:在上個例子基礎上)
<action name="ouhe" class="product.ouhe" >
<result type="chain">
<param name="actionName">testAction</param>
<param name="namespace">/a</param>
</result>
</action>
不能是:
<result name="test">/atguigu/testAction.do</result>
總結
結果類型: dispatcher
dispatcher 結果類型是最常用的結果類型, 也是 struts 框架默認的結果類型
該結果類型有一個 location 參數, 它是一個默認參數
等同
dispatcher 結果類型將把控制權轉發給應用程序裏的指定資源.
dispatcher 結果類型不能把控制權轉發給一個外部資源. 若需要把控制權重定向到一個外部資源, 應該使用 redirect 結果類型
結果類型: redirect
redirect 結果類型將把響應重定向到另一個資源, 而不是轉發給該資源.
redirect 結果類型接受下面這些參數:
location: 用來給出重定向的目的地.它是默認屬性
parse: 用來表明是否把 location 參數的值視爲一個 OGNL 表達式來解釋. 默認值爲 true
redirect 結果類型可以把響應重定向到一個外部資源
實例代碼:
通配符映射
一個 Web 應用可能有成百上千個 action 聲明. 可以利用 struts 提供的通配符映射機制把多個彼此相似的映射關係簡化爲一個映射關係
通配符映射規則
若找到多個匹配, 沒有通配符的那個將勝出(精確匹配優先)
若指定的動作不存在, Struts 將會嘗試把這個 URI 與任何一個包含着通配符 * 的動作名及進行匹配
被通配符匹配到的 URI 字符串的子串可以用 {1}, {2} 來引用. {1} 匹配第一個子串, {2} 匹配第二個子串…
{0} 匹配整個 URI
若 Struts 找到的帶有通配符的匹配不止一個, 則按先後順序進行匹配
- 可以匹配零個或多個字符, 但不包括 / 字符. 如果想把 / 字符包括在內, 需要使用 **. 如果需要對某個字符進行轉義, 需要使用 \ .
例子:
<action name="ouhe*" class="product.ouhe" method="{1}">
<result name="{1}">/index1.jsp</result>
</action>
動態方法調用(平時開發不建議使用暴露調用方法)
動態方法調用: 通過 url 動態調用 Action 中的方法
默認情況下, Struts 的動態方法調用處於禁用狀態
例子:
在struts.xml中打開動態調用
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
.java
package product;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
public class ouhe {
private String name;
public void setName(String name) {
this.name = name;
}
public String execute(){
System.out.println("execute");
return "success";
}
public String save(){
System.out.println("save");
return "success";
}
}
配置.java
<action name="ouhe" class="product.ouhe" >
<result >/index1.jsp</result>
</action>
調用save方法url
http://pc2004141500:8080/web1/ouhe!save.action
OGNL(重點)
頁面顯示效果:
值棧
關於值棧
1). helloWorld 時, ${productName} 讀取 productName 值, 實際上該屬性並不在 request 等域對象中, 而是從值棧中獲取的.
2). ValueStack:
I. 可以從 ActionContext 中獲取值棧對象
II. 值棧分爲兩個邏輯部分
> Map 棧: 實際上是 OgnlContext 類型, 是個 Map, 也是對 ActionContext 的一個引用. 裏邊保存着各種 Map:
requestMap, sessionMap, applicationMap, parametersMap, attr
> 對象棧: 實際上是 CompoundRoot 類型, 是一個使用 ArrayList 定義的棧. 裏邊保存各種和當前 Action 實例相關的對象.
是一個數據結構意義的棧。
獲取值棧裏面的屬性
1.OGNL
在 JSP 頁面上可以可以利用 OGNL(Object-Graph Navigation Language: 對象-圖導航語言) 訪問到值棧(ValueStack) 裏的對象屬性.
若希望訪問值棧中 ContextMap 中的數據, 需要給 OGNL 表達式加上一個前綴字符 #. 如果沒有前綴字符 #, 搜索將在 ObjectStack 裏進行.
2.property 標籤
truts 的 property 標籤用來輸出值棧中的一個屬性值.
讀取 ObjectStack 裏的對象的屬性
- Struts2 利用 s:property 標籤和 OGNL 表達式來讀取值棧中的屬性值
1). 值棧中的屬性值:
> 對於對象棧: 對象棧中某一個對象的屬性值
> Map 棧: request, session, application 的一個屬性值 或 一個請求參數的值.
2). 讀取對象棧中對象的屬性:
> 若想訪問 Object Stack 裏的某個對象的屬性. 可以使用以下幾種形式之一:
object.propertyName ; object['propertyName'] ; object["propertyName"]
> ObjectStack 裏的對象可以通過一個從零開始的下標來引用. ObjectStack 裏的棧頂對象可以用 [0] 來引用,
它下面的那個對象可以用 [1] 引用.
[0].message
> [n] 的含義是從第 n 個開始搜索, 而不是隻搜索第 n 個對象
> 若從棧頂對象開始搜索, 則可以省略下標部分: message
> 結合 s:property 標籤: <s:property value="[0].message" /> <s:property value="message" />
3). 默認情況下, Action 對象會被 Struts2 自動的放到值棧的棧頂.
讀取 Context Map 裏的對象的屬性
若想訪問 ContextMap 裏的某個對象的屬性, 可以使用以下幾種形式之一:
示例:
返回 session 中的 code 屬性: #session.code
返回 request 中的 customer 屬性的 name 屬性值: #request.customer.name
返回域對象(按 request, session, application 的順序)的 lastAccessDate 屬性: #attr.lastAccessDate
例子:
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<a href="product-save.action?productName=ni">ouhe</a><br>dh
<a href="ouhesave.action?name=123">ouhe</a><br>
<a href="ouhejiekou.action?name=123">ouhejiekou</a>
<%
if(application.getAttribute("date") == null)
application.setAttribute("date", new Date());
request.setAttribute("i","d");
%>
<form action="product-save.action" >
ProductName: <input type="text" name="productName"/>
<br><br>
ProductDesc: <input type="text" name="productDesc"/>
<br><br>
ProductPrice: <input type="text" name="productPrice" />
<br><br>
<input type="submit" value="Submit"/>
<br><br>
</form>
</body>
</html>
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="struts.enable.DynamicMethodInvocation" value="true"></constant>
<constant name="struts.action.extension" value="action,do,"></constant>
<package name="hello" extends="struts-default" >
<action name="product-save" class="product.Product" method="save">
<result name="details">/index1.jsp</result>
</action>
<action name="ouhejiekou" class="product.ouhejiekou" >
<result name="success" type="redirect">/a/testAction.do</result>
</action>
</package>
<package name="lala" extends="struts-default" namespace="/a">
<action name="testAction">
<result >/index2.jsp</result>
</action>
</package>
</struts>
package product;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
public class Product implements SessionAware{
private Integer productId;
private String productName;
private String productDesc;
private Map<String, Object> session;
private double productPrice;
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductDesc() {
return productDesc;
}
public void setProductDesc(String productDesc) {
this.productDesc = productDesc;
}
public double getProductPrice() {
return productPrice;
}
public void setProductPrice(double productPrice) {
this.productPrice = productPrice;
}
public String save(){
ValueStack a=ActionContext.getContext().getValueStack();
Product b=new Product();
b.setProductName("lalala0");
a.push(b);
System.out.println("save: " + this);
session.put("session",this);
return "details";
}
public String test(){
System.out.println("test");
return "success";
}
@Override
public void setSession(Map<String, Object> arg0) {
// TODO Auto-generated method stub
this.session=arg0;
}
}
//index1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %> //重點
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<s:debug></s:debug>
ProductId: ${productId }
<br><br>
ProductName: ^<%= request.getAttribute("productName") %>
<br><br>
ProductDesc: ${productDesc }
<br><br>
ProductPrice: ${productPrice }
<br><br>
ProductPrice: ^<s:property value="productPrice"/>
<br><br>
<s:property value="[1].productName"/><br><br>
<%= request %>
<br><br>
session ${sessionScope.session.productName}<br><br>
<s:property value="#session.session.productName"/><br><br>
</body>
</html>
調用字段和方法
可以利用 OGNL 調用
任何一個 Java 類裏的靜態字段或方法.
被壓入到 ValueStack 棧的對象上的公共字段和方法.
默認情況下, Struts2 不允許調用任意 Java 類靜態方法, 需要重新設置 struts.ognl.allowStaticMethodAccess 標記變量的值爲 true.
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
調用靜態字段或方法需要使用如下所示的語法:
@fullyQualifiedClassName@fieldName: @java.util.Calendar@DECEMBER
@fullyQualifiedClassName@methodName(argumentList): @app4.Util@now()
例子:
在前面代碼此處上,在struts.xml相應變量設置true
在index1.jsp加入
<s:property value="@java.lang.Math@PI"/><br><br>
<s:property value="@java.lang.Math@cos(0)"/>
調用一個實例字段或方法的語法, 其中 object 是 Object Stack 棧裏的某個對象的引用:
.object.fieldName: [0].datePattern
.object.methodName(argumentList): [0].repeat(3, “Hello”);
例子
在前面代碼此處上
在index1.jsp加入
<s:property value="setProductName('ryr')"/>
<s:property value="productName"/><br><br>
訪問數組類型的屬性
有些屬性將返回一個對象數組而不是單個對象, 可以像讀取任何其他對象屬性那樣讀取它們. 這種數組型屬性的各個元素以逗號分隔, 並且不帶方括號
可以使用下標訪問數組中指定的元素: colors[0]
可以通過調用其 length 字段查出給定數組中有多少個元素**: colors.length**
例子
在前面代碼此處上
在index1.jsp加入
<%String []a={"Ese","gte"};
request.setAttribute("name",a);
%>
<s:property value="#attr.name.length"/><br><br>
<s:property value="#attr.name[0]"/><br><br>
</body>
訪問 List 類型的屬性
有些屬性將返回的類型是 java.util.List, 可以像讀取任何其他屬性那樣讀取它們. 這種 List 的各個元素是字符串, 以逗號分隔, 並且帶方括號
可以使用下標訪問 List 中指定的元素: colors[0]
可以通過調用其 size 方法或專用關鍵字 size 的方法查出給定List 的長度: colors.size 或 colors.size()
可以通過使用 isEmpty() 方法或專用關鍵字 isEmpty 來得知給定的 List 是不是空. colors.isEmpty 或 colors.isEmpty()
還可以使用 OGNL 表達式來創建 List, 創建一個 List 與聲明一個 Java 數組是相同的: {“Red”, “Black”, “Green”}
訪問 Map 類型的屬性
讀取一個 Map 類型的屬性將以如下所示的格式返回它所有的鍵值對:
若希望檢索出某個 Map 的值, 需要使用如下格式: map[key]
可以使用 size 或 size() 得出某個給定的 Map 的鍵值對的個數
可以使用 isEmpty 或 isEmpty() 檢查某給定 Map 是不是空.
可以使用如下語法來創建一個 Map:
例子
在前面代碼此處上
在index1.jsp加入
使用 EL 訪問值棧中對象的屬性
<s:property value=“fieldName”> 也可以通過 JSP EL 來達到目的: ${fieldName}
原理: Struts2 將包裝 HttpServletRequest 對象後的 org.apache.struts2.dispatcher.StrutsRequestWrapper 對象傳到頁面上, 而這個類重寫了 getAttribute() 方法.