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() 方法.