Struts2:
Struts 2是一个MVC框架,以WebWork框架的设计思想为核心,吸收了Struts 1的部分优点,Struts 2拥有更加广阔的前景,自身功能强大
Struts2的核心:拦截器
Struts2的核心功能由内置拦截器实现:
params拦截器:参数在页面和action之间的传递、国际化
fileUpload拦截器:文件上传
.......
核心过滤器:(StrutsPrepareAndExecuteFilter):以前为:filterDispatcher。将Servlet的请求和响应过滤封装后通过Struts2拦截器实现Struts2的基本功能。
Struts 2官方地址:
http://struts.apache.org
Struts2目录结构:
apps:Struts2示例应用程序
docs:Struts2指南、向导、API文档
lib:Struts2的发行包及依赖包
src:Struts2项目源代码
Struts 2中的符号:
1、“#”符号:相当于ActionContext.getContext();
①、访问非根对象(struts中值栈为根对象)
如:#parameters.id[0] 相当于 request.getParameter("id")
②、用于过滤和投影(projecting)集合。
如: books.{?#this.price>35}、books.{?#this.price>35}
③、构造Map,如: #{'foo1':'bar1', 'foo2':'bar2'}
这种方式常用在给radio或select、checkbox等标签赋值上。
<--! 页面中获取一个map的值可以这样写 -->
<s:property value="#myMap['foo1']"/>
<s:property value="#myMap['foo1']"/>
2、“%”符号:
在标签的属性值是为字符串类型时,告诉执行环境%{}里的是OGNL表达式。
<s:set name="myMap" value="#{'key1':'value1','key2':'value2'}"/>
<!-- -->
<!-- 在页面上输出“value1” -->
<s:property value="#myMap['key1']"/>
<!-- 输出"#myMap['key1']"这么一个字符串 -->
<s:url value="#myMap['key1']" />
property标签中,value之后的字符串会自动被解析为OGNL表达式
URL标签在被struts解析的时候默认当做字符串
正确代码如下:
<s:url value="%{#myMap['key1']}"/>
3、“$”符号:
①、在国际化资源文件中,引用OGNL表达式。
②、在Struts 2配置文件中,引用OGNL表达式:
<action name="saveUser" class="userAction" method="save">
<!-- 这里的${}不是EL表达式,而是OGNL表达式,他只是在不同的地方定义的解析字符不一样而已 -->
<result type="redirect">listUser.action?msg=${msg}</result>
</action>
Struts 2文件上传下载:
Struts 2访问Servlet API的两种方式:(如何使用session保存用户信息?)
1、与Servlet API解耦的访问方式
Action可以摆脱Servlet容器的束缚,可以直接访问所需要的对象。而这些对象被定义成了Map类型,以key-value的形式进行读取。
//action中进行保存到Map集合中
public String execute() {
if("jason".equals(username) && "2010".equals(password)) {
Map<String, Object> session = null;
//从actionContext中获取session
session = ActionContext.getContext().getSession();
if(session.containsKey(CURRENT_USER)) {
session.remove(CURRENT_USER);
}
//以key/value形式保存数据
session.put(CURRENT_USER, username);
return "success";
} else {
return "error";
}
}
<!-- 页面显示用EL表达式显示数据 -->
<body>
<h1>读取Session中保存的用户名</h1>
<div>欢迎您,${sessionScope.CURRENT_USER}!</div>
</body>
2、与Servlet API耦合的访问方式
public class LoginAction implements Action {
private static final String CURRENT_USER = "CURRENT_USER";
… //省略username、password属性及其setter和getter方法
public String execute() {
if("jason".equals(username) && "2010".equals(password)) {
//获取session
HttpSession session = null;
session = ServletActionContext.getRequest().getSession();
if(session.getAttribute(CURRENT_USER) != null) {
session.removeAttribute(CURRENT_USER);
}
//以setAttribute的方式保存数据
session.setAttribute(CURRENT_USER, username);
return "success";
} else {
return "error";
}
}
}
Struts2服务器端数据校验
1、Struts 2提供了数据验证机制
继承ActionSupport类来完成Action开发
ActionSupport类不仅对Action接口进行简单实现,同时增加了验证、本地化等支持
2、valid方法可以进行数据验证
//1、让action继承ActionSupport
//2、分情况用addFieldError方法添加错误信息
public class LoginAction extends ActionSupport{
//......省略代码
public void validate() {
if(this.getUsername().length()==0){
//通过addField方法添加的错误信息显示到页面
addFieldError("name","用户名不能为空");
}
if(this.getPassword().length()==0){
addFieldError("pwd", "用户密码不能为空");
}
}
//......省略代码
}
<!-- 在页面中用struts标签显示错误信息 -->
<s:fielderror/>
Struts 2标签
Struts 2迭代标签输出数据
1、在页面中引入strurs2标签库
<%@ taglib prefix="s" uri="/struts-tags"%>
2、struts2标签分为UI标签和通用标签
UI标签
标 签 | 说 明 |
---|---|
<s:form> …</s:form> | 表单标签 |
<s:textfield>…</s: textfield> | 文本输入框 |
<s:password>…</s: password> | 密码输入框 |
<s:textarea>…</s: textarea> | 文本域输入框 |
<s:radio>…</s: radio> | 单选按钮 |
<s:checkbox>…</s: checkbox> | 多选框 |
<s:submit/> | 提交标签 |
<s:reset/> | 重置标签 |
<s:hidden/> | 隐藏域标签 |
非表单标签
标 签 | 说 明 |
---|---|
<s:actionerror/> | 显示Action错误 |
<s:actionmessage/> | 显示Action消息 |
<s:fielderror/> | 显示字段错误 |
<s:property value="user.name" /> | 标签用于输出指定对象的属性值 |
<s:set> | 标签将一个值赋给指定范围的变量 |
条件判断标签
标 签 | 说 明 |
---|---|
<s:if>……</s:if> | 根据表达式的值,判断将要执行的内容 |
<s:elseif>……</s:elseif> | |
<s:else>……</s:else> |
<s:if test="表达式">
<!-- 需要执行的代码 -->
</s:if>
<s:elseif test="表达式">
<!-- 需要执行的代码 -->
</s:elseif>
<s:else>
<!-- 需要执行的代码 -->
</s:else>
迭代标签
标 签 | 说 明 |
---|---|
<s:iterator>……</s:iterator> | 用于遍历集合 |
<s:iterator value="集合对象" status="status" id="name">
<!-- 读取集合对象并输出显示 -->
</s:iterator>
<!-- value属性:需要进行遍历的集合对象 -->
<!-- status属性:当前迭代元素的IteratorStatus实例 -->
<!-- id属性:当前迭代元素的id,可直接访问元素,该参数可选 -->
URL标签
<s:url value="url" />
<s:param name="parname" value="parvalue" />
</s:url>
<!-- value属性:表示指定生成URL的地址 -->
<!-- <s:param />表示需要传递的参数信息 -->
<!-- name属性:表示传递的参数名称 -->
<!-- value属性:表示传递参数所具有的值 -->
日期标签
<s:date format="format" nice="true|false" name="name" id="id">
……
</s:date>
<!-- format属性:指定格式进行日期格式化 -->
<!-- nice属性:该属性只有true和false两个值,用于指定是否输出指定日期与当前时间的时差,默认是false -->
<!-- name属性:表示当前需要格式化的日期 -->
<!-- id属性:表示引用该元素的id值 -->
Struts 2的执行流程
1、加载Struts 2 类库(导入jar包)
文件名 | 说 明 |
---|---|
struts2-core-xxx.jar | Struts 2框架的核心类库 |
xwork-core-xxx.jar | XWork类库,Struts 2的构建基础,现已并到Struts2-core中 |
ognl-xxx.jar | Struts 2使用的一种表达式语言类库 |
freemarker-xxx.jar | Struts 2的标签模板使用类库 |
javassist-xxx.GA.jar | 对字节码进行处理 |
commons-fileupload-xxx.jar | 文件上传时需要使用 |
commons-io-xxx.jar | Java IO扩展 |
commons-lang-xxx.jar | 包含了一些数据类型的工具类 |
2、配置web.xml文件
<filter>
<filter-name>struts2</filter-name>
<filter-class>①</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>②</url-pattern>
</filter-mapping>
注解:
①、org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
//Struts 2的核心控制器,对框架进行初始化,以及处理所有的请求
②、/* 所有文件
3、开发视图层页面
4、开发控制层Action
创建Action类
实现Action接口
继承ActionSupport类
配置Action
Action的作用
①、封装工作单元
②、数据转移的场所
③、返回结果字符串
在struts.xml文件中配置默认Action
默认Action作用:没有Action匹配请求时,默认Action将被执行
<!-- 通过<default-action-ref name="defaultAction"/ >元素配置默认Action -->
<struts>
<default-action-ref name="defaultAction"/ >
<package name="default" extends="struts-default">
<action name="defaultAction">
<!-- 如果请求的action不存在,页面跳转到error.jsp -->
<result>error.jsp</result>
</action>
</package>
</struts>
5、配置struts.xml文件
Struts.xml:核心配置文件,主要负责Action,通常放在src目录下,可以被自动加载
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 在struts2 core的jar包中可以找到对应的语句 -->
<!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.ui.theme" value="simple" />
<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开-->
<constant name="struts.configuration.xml.reload" value="true" />
<package name="default" namespace="/" extends="struts-default">
<!-- name值与显示页面的表单中的action对应 -->
<action name="helloWorld" class="cn.strutsdemo.HelloWorldAction">
<result name="success">helloWorld.jsp</result>
</action>
</package>
</struts>
constant标签:配置常量,可以改变Struts 2框架的一些行为
name属性:表示常量名称;
value属性:表示常量值
<!-- 默认的视图主题 -->
<constant name="struts.ui.theme" value="simple" />
<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开-->
<constant name="struts.configuration.xml.reload" value="true" />
package标签
包的作用:简化维护工作,提高重用性(包可以“继承”已定义的包,并可以添加自己包的配置)
name属性:为必需的且唯一,用于指定包的名称
extends属性:指定要扩展的包
namespace属性:定义该包中action的命名空间 ,可选
固定格式:<package name="default" namespace="/" extends="struts-default"></package>
struts-default.xml :Struts 2默认配置文件,会自动加载
注意点:struts-default 包 在 struts-default.xml 文件中定义
struts-plugin.xml :Struts 2插件使用的配置文件
运行加载顺序:struts-default.xml ---->struts-plugin.xml----->struts.xml
action标签:一个action对应一个Action类的请求;
action动态方法调用 :解决一个Action对应多个请求的处理,以免Action太多
第一种方式:指定method属性
JSP调用一个方法,便需要在配置文件中配置一个action标签;
这种方式是以方法为单位进行配置,调用多少个方法,便需要配置多少个action,而指向的action类全是一个。
不可避免的增加了不必要的重复配置,笨拙繁琐。
method属性:实现Action中不同方法的调用,
特点:
①、避免动态方法调用的安全隐患
②、导致大量的Action配置
第二种方式:通配符
1、首先得关闭开关:
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
2、主要看URL里写的是XXXUser 则* === XXX
<action name= "*User" class="cn.houserent.action.UserAction" method="{1}">
<result>/page/{1}_success.jsp</result>
<result name="input">/page/{1}.jsp</result>
</action>
在地址栏中输入:/loginUser.action //通配符为:login
method="login"
/page/login_success.jsp
/page/login.jsp
在地址栏中输入:/registerUser.action //通配符为:regist
method="register"
/page/register_success.jsp
/page/register.jsp
//{1}、{2}表示第一第二个占位符 、*为通配符
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
<result>/{1}_{2}_success.jsp</result>
</action>
第三种方式:DMI(Dynamic Method Invocation)
不推荐使用
调用aciton时不直接等同于调用某个action的名字,而是通过“actionname !methodname”的形式,调用指定到action中具体方法执行。
//action类:
package chapter3.action;
public class Chapter3Action {
public String result1(){
return "result1";
}
public String result2(){
return "result2";
}
}
①、设置struts.xml 文件DMI常量启动动态方法调用:
<constant name="struts. enable. DynamicMethodInvocation" value="true"/>
②、配置好action result值跳转页面<不同方法的返回值均配置到一个action标签中>
<package name="chapter3" namespace="/chapter3" extends="struts-default">
<action name="chapter3Action" class="chapter3.action.Chapter3Action">
<result name="result1">/WEB-INF/JspPage/chapter3/result1.jsp</result>
<result name="result2">/WEB-INF/JspPage/chapter3/result2.jsp</result>
<result name="chapter3">/WEB-INF/JspPage/chapter3/chapter3.jsp</result>
</action>
</package>
③、JSP中通过“actionname !methodname”的形式调用指定action中指定方法
<body>
<a href="basePath/chapter3/chapter3Action!result1">result1</a><br>
<a href="{basePath}/chapter3/chapter3Action!result2">result2</a><br>
</body>
Result标签:实现对结果的调用
result元素的值指定对应的实际资源位置
name属性:表示result逻辑名
常用结果类型
dispatcher类型:默认结果类型,后台使用RequestDispatcher转发请求
redirect类型:后台使用的sendRedirect()将请求重定向至指定的URL
redirectAction类型:主要用于重定向到Action
全局结果:实现同一个包中多个action共享一个结果
<!-- 全局结果位于package元素内 -->
<global-results>
<result name="error">/page/error.jsp</result>
<result name="login" type="redirect">/page/login.jsp</result>
</global-results>
动态结果:动态结果集可以在action中指定要跳转的页面(${}是OGNL表达式,不是EL表达式)
<package name="resultTypes" namespace="/r" extends="struts-default">
<action name="result_mul" class="cn.edu.hpu.action.ResultAction">
<!-- 这种写法代表在配置文件中可以用这种方法去读值栈里面的内容 -->
<result>${r}</result>
</action>
</package>
//ResultAction.java
package cn.edu.hpu.action;
import com.opensymphony.xwork2.ActionSupport;
public class ResultAction extends ActionSupport {
private int type;
private String r="/Hello.jsp";
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getR() {
return r;
}
public void setR(String r) {
this.r = r;
}
public String execute() throws Exception {
//因为r是后来保存在值栈中的,所以能被配置文件以${r}
//的形式读到
if(type==1) r="/User_Add_success.jsp";
else if(type==2) r="/User_Add_error.jsp";
return SUCCESS;
}
}
//index.jsp:
<a href="<%=basePath %>/r/result_mul?type=1">动态结果集1</a>
<a href="<%=basePath %>/r/result_mul?type=2">动态结果集2</a>
<a href="<%=basePath %>/r/result_mul?type=3">动态结果集3</a>
6、部署、运行项目
Struts 2类型转换
进行类型转换
的原因:
①、基于HTTP协议的Web应用中客户端请求的所有内容都以 文本编码 方式传输到服务器端,服务器端的编程语言却有着丰富的数据类型:
②、Servlet中,类型转换工作由开发者自己完成:
String agestr = request.getParameter("age");
int age = Integer.parseInt(agestr);
struts2提供多种内置类型转换器(自动对客户端传来的数据进行类型转换);
内置类型转换器 | 说 明 |
---|---|
String | 将int、long、double、boolean、String类型的数组或者java.util.Date类型转换为字符串 |
boolean/Boolean | 在字符串和布尔值之间进行转换 |
char/Character | 在字符串和字符之间进行转换 |
int、float、long、double | 在字符串和数值型数据之间进行转换 |
Integer、Float、Long、Double | 在字符串和数值型数据之间进行转换 |
Date | 在字符串和日期类型之间进行转换。具体输入输出格式与当前的Locale相关 |
数组和集合 | 在字符串数组和数组对象、集合对象间进行转换 |
自定义类型转换器
类型转换:由拦截器实现,将表单中获取的String类型转为Action中所需要的类型
特定类型转换为字符串类型:重写toString()方法;
字符串类型转换为特定类型:一般的特定类型struts2都已经解决,特殊的特定类型需要自定义类型转换器,
如:
Date传值时必须写成1999-01-01才会自动转换类型,若写为19990101则不转
Point传参应该是p.x=1&p.y=2,但写成p=1,2则不转
1、局部类型转换器:
过程:找不到特殊类型的转换之后,struts2会找action对应的包下面的转换文件,查看里面的成员变量里有没有对应的转换器,如果找到,就会尝试把接收到的参数传给转换器“转换方法(convertValue)”中的形参value,把要转换的类型传给toType。最后“转换方法”执行得到一个结果Object,结果就是一个new出来的Point。
//TypeCoverter接口
public interface TypeConberter{
public Object convertValue(Map context,Object target,Member member,String
propertyName,Object value, Class toType);
}
//DefaultTypeConverter实现类
public class UserTypeConvert extends DefaultTypeConverter {
//context 是类型转换环境的上下文
//value 是需要转换的参数
//toType 是转换后的目标类型。
@Override
public Object convertValue(Map<String, Object> context, Object value, Class
toType) {
return null;
}
}
步骤 |
---|
第一步:实现自定义转换器 |
①、实现TypeCoverter 接口或者继承DefaultTypeConverter 实现类(实现TypeCoverter)来实现自己的类型转换器 |
②、重写convertValue方法 |
第二步 配置文件 |
①、在需要生效的Action类的包下放置ActionName-conversion.properties 文件 |
ActionName 是需要转换生效的Action的类名;-conversion 固定。如: LoginAction-conversion.properties |
文件中的内容:待转换的类型 = 类型转换器的全类名 birthday =convert.UserTypeConvert |
//Date类型输入"yyyyMMdd"的自定义转化
public class LoginAction {
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String execute() throws UnsupportedEncodingException{
return "success";
}
}
//转换器继承类:DefaultTypeConverter类
//(由com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter包提供)。
//重写里面的convertValue方法,这个方法会被struts调用。代码如下:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
public class UserTypeConvert extends DefaultTypeConverter{
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType){
SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd");
try{
if(toType == Date.class) {
String [] datevalue = (String [])value;
return dateformat.parse(datevalue[0]);
} else if(toType == String.class) {
Date datevalue = (Date)value;
return dateformat.format(datevalue);
}
} catch (java.text.ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
2、全局类型转换器:对所有action转换类型起作用
配置文件 |
---|
Src下放置xwork-conversion.properties文件,文件名固定。 |
文件中的内容:待转换的类型 = 类型转换器的全类名 。如:java.util.Date = convert.UserTypeConvert |
类型转换器注册的方式有三种(配置文件):
1、注册局部类型转换器:局部类型转换器仅仅对某个Action的属性起作用。
2、注册全局类型转换器:全局类型转换器对所有Action的特定类型的属性都会生效。
3、使用JDK1.5的Annotation来注册类型转换器
向用户输出类型转换错误的前提条件
1、启动StrutsConversionErrorInterceptor拦截器,包含在defaultStack拦截器栈中
2、Action继承ActionSupport类,并实现ValidationAware接口
3、配置input结果映射,页面使用Struts 2表单标签或<s:fielderror>标签
所有类型的转换错误信息
1、在struts.xml中指定资源文件的基名
<constant name="struts.custom.i18n.resources" value="message"/>
2、在src目录下创建资源文件message.properties并修改键值
xwork.default.invalid.fieldvalue=字段“{0}”的值无效
定制特定字段的类型转换错误信息
在Action包下创建RegisterAction.properties,指定键值
invalid.fieldvalue.birthday=生日转换错误
Struts2中文乱码
<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
OGNL(Object Graph Navigation Language) 对象图导航语言
1、Ognl是一个开源项目,取代页面中Java脚本,简化数据访问,和EL同属于表达式语言,但功能更为强大
2、 OGNL表达式的解析都是围绕OGNL上下文进行的,OGNL表达式是一个map对象,其中包含多个java对象,其中有一个对象十分的特殊,这个对象称为根对象!
a.一个OGNL表达式若没有指定目标对象,默认就是从根对象开始查找!
b.若要访问非根对象中的属性,就要在访问根对象的前面需加#前缀!
struts2框架在解析OGNL表达式的时候,OGNL上下文就是ActionContext,而根对象就是Action对象!
OGNL在框架中的作用
表达式语言
将表单或Struts 2标签与特定的Java数据绑定起来,用来将数据移入、移出框架
类型转换
数据进入和流出框架,在页面数据的字符串类型和Java数据类型之间进行转换
执行过程:
表单数据提交时,首先会被装入对应的Java对象,并赋值给相应的属性,在这个过程中会自动执行类型转换。
然后这个对象又会作为Action对象属性而存在,Action位置在值栈中,值栈的位于运行环境中。这部分对应的就是数据流入。
对于数据流出而言,当请求处理完毕后,使用OGNL结合Struts 2标签又可以方便的在页面中访问数据。
OGNL访问值栈
OGNL访问值栈时的顺序,自上而下,如果存在相同名称属性则位于栈顶的属性会被读取。
使用OGNL访问数据
访问Bean的属性
1、Bean的类型必须遵循JavaBean规范
2、必须具有无参构造
3、setter/getter方法符合JavaBean规范
访问集合对象
可以使用属性名[index]的方式访问
列表、数组
可以使用属性名[key]的方式访问
Map对象
使用size或者length获取集合长度
访问JavaBean
public class Address { // 家庭地址
private String country; // 国家
private String city; // 城市
private String street; // 街道
... //省略各个属性的setter和getter方法
}
public class User { //用户类
private String name; //姓名
private int age; //年龄
private Address address; //家庭地址
... //省略各个属性的setter和getter方法
}
//User对象作为Action的属性,其键名为user
//访问name属性:user.name;
//访问country属性:user.address.country;
访问集合
<s:set name="list" value="{'jason','tom','jack'}"/>
<s:property value="#list[0]"/>
<s:property value="#list.size"/>
数组的访问
//定义数组:
new int[]{1,2,3,4}
/*
访问数组:
访问已创建的数组,对象名为array
访问第一个元素:array[0]
获取数组长度:array.length
*/
Map的访问
<--! 定义Map -->
<s:set name="map" value="#{'cn':'China','us':'the United States','fr':'France','jp':'Japan'}" />
<--! 访问已创建的Map,对象名为map 访问“China” -->
<--! 第一种方式:-->
#map["cn"]
<--! 第二种方式:-->
#map.cn
注意: 值栈中内容可以直接访问,访问非值栈对象需添加#前缀
Struts 2将OGNL上下文设置为ActionContext
Struts 2将值栈作为OGNL上下文根对象
ActionContext对象包括:application、session、ValueStack、request、attr、parameters
非值栈对象 | 访问方式 | 等价访问方式 |
---|---|---|
application | #application.username 、#application['username'] | application.getAttribute("username") |
session | #session.username 、#session['username'] | session.getAttribute("userName") |
request | #request.username 、#request['username'] | request.getAttribute("username") |
parameters | #parameters.username 、#parameters['username' ] | request.getParameterValues(“username”) |
attr | #attr.username 、#attr['username'] | pageContext–>request–>session–>application 顺序查找 |
例子:
<s:set name="age" value="10" scope="request"/>
<s:set name="username" value="'Jason'" scope="session"/>
<s:set name="count" value="5" scope="application"/>
#request.age:<s:property value="#request.age"/><br/>
#session.username:<s:property value="#session.username"/><br/>
#application.count:<s:property value="#application.count"/><br/>
#attr.count:<s:property value="#attr.count" /><br />
<s:set name="country1" value="China"/>
<s:set name="country2" value="'China'"/>
#country1:<s:property value="#country1"/><br/>
#country2:<s:property value="#country2"/><br/>
#request.country2:<s:property value="#request.country2"/><br/>
值栈(ValueStack):
由 Struts 2 框架创建的存储区域,具有栈的特点(先进先出),Action的实例会被存放到值栈中
1、valueStack是值栈的对外接口,实际对应的类是OgnlValueStack,OgnlValueStack对象中包含了一个ArrayList集合来作为栈,默认action对象位置值栈的栈顶位置。
a.void push(Objext o) 可用来将一个对象数据压入栈顶.
b.set(String key,Objext obj) 则是将数据放入Map对象当中,并将Map对象压入栈顶位置!
2、 OGNL表达式在取数据的时候,其规则是先从栈的栈顶(action对象)中开始查找,先判断是否有Map对象,根据key取值;不是Map对象,则寻找该对象的getKey()方法,得到其值,若没有方法,则查找key变量(要求必须是public修饰)均为找到,就去第二个对象中向下查找!
ActionContext
重要的文字,写三遍;
struts2框架在解析OGNL表达式的时候,OGNL上下文就是ActionContext,而根对象就是Action对象!
ActionContext的组成:值栈-ValueStack、非值栈-Stack Context
客户端发送的每一次请求,struts2框架都会自动的创建一个ActionContext和值栈对象,请求处理完毕以后这两个对象会自动的销毁!
ActionContext对象相当于一个大大的容器,里面包含了application、session、parameters、valueSatck、attr属性。(其中valueStack对象就是值栈对象)
注意:
1、ActionContext中的application、session、parameters等对象都是非根对象,在OGNL表达式中要访问他们,需要在表达式前面加上#前缀!
2、<s:debug/>标签可以查看ActionContext对象
总结:
Struts 2提供了非常强大的类型转换功能,提供了多种内置类型转换器,也支持开发自定义类型转换器
Struts 2框架使用OGNL作为默认的表达式语言
ActionContext中包含多个对象。如果使用OGNL访问根对象,可直接书写对象的属性,而要使用其他对象必须使用“#key”前缀来访问
使用Struts 2日期标签可以实现日期输出的格式化显示,使用URL标签可以构建一个超链接