通配符映射和值栈
通配符映射
使用原因
一个 Web 应用可能有成百上千个 action 声明,为了简化配置,可以使用通配符。
使用方法
在action中使用,一个为通配符*,另一个为引用字串,{1}、{2}…
匹配规则
优先匹配全匹配规则;
有通配符的按照顺序匹配;
例子:
index.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<a href="add_action.do">add</a>
<br>
<a href="delete_action.do">delete</a>
<br>
<a href="query_action.do">query</a>
</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.action.extension" value="action,do"></constant>
<package name="default03" namespace="/" extends="struts-default">
<action name="*_action" class="com.test.Test" method="{1}">
<result name="{1}_sucess">/test.jsp</result>
</action>
</package>
</struts>
Action类:
package com.test;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
public class Test {
private Map<String,Object> request=(Map<String, Object>) ActionContext.getContext().get("request");
public String add()
{
request.put("mesg", "add");
return "add_sucess";
}
public String delete()
{
request.put("mesg", "delete");
return "delete_sucess";
}
public String query()
{
request.put("mesg", "query");
return "query_sucess";
}
}
test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
${requestScope.mesg}
</body>
</html>
动态方法调用
说明:通过 url 动态调用 Action 中的方法
调用代码:/path1/path2…/action名!方法名.后缀
例如:http://localhost:8080/struts2-4/add_action!test.do
需要把动态配置设置成打开:
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
struts.xml中需要配置action。
<action name="*_action" class="com.test.Test" method="{1}">
<result name="{1}_sucess">/test.jsp</result>
<result name="test_sucess">/test.jsp</result><!--必须有,否则无法调用-->
</action>
值栈
在struts2中页面获得的seesion、application、request、parameters并非是servlet中对应的对象,是经过struts封装之后的值栈中获取的。
ValueStack对象
在 ValueStack 对象的内部有两个逻辑部分.
ObjectStack:
Struts 把 Action 和相关对象压入 ObjectStack 中。
默认情况下, Action 对象会被 Struts2 自动的放到对象栈的栈顶。
Action类中获取值栈:
ValueStack valueStack=ActionContext.getContext().getValueStack();
向值栈中压入对象:
valueStack.push(object);
存值示例:
public String save(){
System.out.println("save: " + this);
ValueStack valueStack=ActionContext.getContext().getValueStack();
Test test=new Test();
test.setProductName("aaa");
test.setProductDesc("bbb");
valueStack.push(test);
return "details";
}
ContextMap
Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中. 实际上就是对 ActionContext 的一个引用。
Struts 会把下面这些映射压入 ContextMap 中:
- parameters: 该 Map 中包含当前请求的请求参数
- request: 该 Map 中包含当前 request 对象中的所有属性
- session: 该 Map 中包含当前 session 对象中的所有属性
- application:该 Map 中包含当前application 对象中的所有属性
- attr: 该 Map 按如下顺序来检索某个属性: request, session,
application
OGNL
Object-Graph Navigation Language: 对象-图导航语言,在 JSP 页面上可以可以利用 OGNL(访问到值栈(ValueStack) 里的对象属性。
OGNL表达式:
访问对象栈中的数值
1.在jsp中进行debug测试:
<s:debug></s:debug>
2.在jsp中,Struts 的 property 标签用来输出值栈中的一个属性值.
- default:可选,如果value值为null或没有给定,将显示该属性值
- escape:可选,是否要对HTML特殊字符进行转义
- value:将要显示的内容
注意:如果 value 属性没有给出(就是不赋值,空串也不行), ValueStack 值栈栈顶对象的值被输出。
<s:property value="" default=""/>
3.value的取值方法:
- 1).ObjectStack 里的对象可以通过一个从零开始的下标来引用.
[n].propertyName;[n].[‘propertyName’] ; [n].[“propertyName”]
[n] 的含义是从第 n 个开始搜索, 而不是只搜索第 n 个对象 - 2).若从栈顶对象开始搜索, 则可以省略下标部分: propertyName
页面取值示例代码:
<s:debug></s:debug>
ProductId: <s:property value="[1].['propertyName'] " default=""/>
<br><br>
ProductName:<s:property value="[1].productName" default=""/>
<br><br>
ProductDesc: <s:property value="[1].productDesc" default=""/>
<br><br>
ProductPrice:<s:property value="[1].productPrice" default=""/>
访问Context Map栈中的数值
需要给 OGNL 表达式加上一个前缀字符 #.。
如果没有前缀字符 #, 搜索将在 ObjectStack 里进行。
Test test=new Test();
test.setProductName("aaa");
test.setProductDesc("bbb");
valueStack.push(test);
session.put("sessionTest", test);
application.put("applicationTest",test);
session:
<s:property value="#session.sessionTest.productName" default=""/>
<br><br>
application:<s:property value="#application.applicationTest.productName" default=""/>
<br><br>
调用字段和方法
前置条件:
调用静态方法需要设置struts.ognl.allowStaticMethodAccess 标记变量的值为 true。
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
语法:
1)调用静态字段:@全类名@属性名
2)调用静态方法:@全类名@方法名(参数列表)
<s:property value="@java.lang.Math@PI"/>
<s:property value="@java.lang.Math@cos(0)"/>
3)调用Object Stack一个实例的字段:.object.fieldName
4)调用Object Stack一个实例的方法.object.methodName(argumentList)
test:<s:property value="[1].setProductName('test')" default=""/>
5)访问数组类型的属性
<%
String [] names=new String[]{"aa","bb","cc","dd"};
request.setAttribute("names",names);
%>
<s:property value="#attr.names.length" default=""/>
<s:property value="#attr.names[2]" default=""/>
6)访问 List 类型的属性
长度:colors.size 或 colors.size()
List 是不是空. colors.isEmpty 或 colors.isEmpty()
7)访问 Map 类型的属性
若希望检索出某个 Map 的值, 需要使用如下格式: map[‘key’]
可以使用 size 或 size() 得出某个给定的 Map 的键值对的个数
可以使用 isEmpty 或 isEmpty() 检查某给定 Map 是不是空.
可以使用如下语法来创建一个 Map(测试但是没有成功,以后再测)
Map<String,String> letters=new HashMap<String,String>();
request.setAttribute("letters",letters);
letters.put("aa","a");
letters.put("bb","b");
letters.put("cc","c");
size:<s:property value="#attr.letters.size" default=""/>
<br>
isEmpty:<s:property value="#attr.letters.isEmpty" default=""/>
<br>
aa:<s:property value="#attr.letters['aa']" default=""/>
运行结果如下:
size:3
isEmpty:false
aa:a