一、 值栈简介(ActionContext[广义的值栈])
l 简单的说,值栈是对应每一个请求对象的轻量级的数据存储中心,在这里统一管理着数据,供Action、Result、Interceptor等Struts2的其他部分使用。
l 当有请求的时候,Struts2会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的,不同的请求,值栈也不一样,而值栈封装了一次请求所有需要操作的相关的数据(action中的全局的属性)。所以也可以说值栈的生命周期是一次请求。请求完成后对应的值栈也就完成了他的使命,同时会被销毁。
l 正是因为值栈和请求的对应关系,因此值栈能保证线程安全的为每个请求提供公共的数据存取服务
1、 ValueStack对象(狭义的值栈):
通常是指com.opensymphony.xwork2.util.ValueStack接口的对象,struts2的默认实现是com.opensymphony.xwork2.ognl.OgnlValueStack对象。
值栈中存放action的实例,这样在jsp页面就可以通过表达式语言来访问Action实例中属性的值了。
二、 Ognl表达式(类似于EL)
1. ognl简介
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts 2框架使用OGNL作为默认的表达式语言。
【注意:导航的目的,是为了获取某个对象的值或设置某个对象的值或调用某个对象的方法!】
【注意:OGNL表达式语言的真正目的,是为了在那些不能写JAVA代码的地方执行JAVA代码,或者是为了更方便地执行JAVA代码,更快速的找到他。】
【注意】:用户完全可以不清楚上下文的对象的结构
相对EL表达式,它提供了平时我们需要的一些功能,如:
l 支持对象方法调用,如xxx.sayHello();
l 支持类静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名| 值名]【必须包含包名】
例如:访问静态属性@com.itjob.struts.constant.Constant@NAME;
package com.itjob.struts.constant;
public class Constant {
public static final String NAME="itjob";
}
访问静态方法
"@java.lang.String@format('welcome %s','strutstag')" 该方法第一个参数中的%s表示占位符将第二个参数的值替换到%s处
l 操作集合对象
使用struts2标签与ognl定义一个集合
<s:set id="a" value='{"1","2","3"}'></s:set>
使用struts2标签与ognl定义一个map
<s:set id="a" value=”#{‘m’:’1’,’n’:’2’}”></s:set>
Jsp <s:property value=”’我们是%{#request.name}’”/>
标准的OGNL会设定一个根对象(root对象)。假设使用标准OGNL表达式来求值(不使用Struts 2的OGNL表达式),如果OGNL上下文(OgnlContext Map类型)有两个对象:request对象,在OgnlContext中名称为request;session对象,在OgnlContext中名称为session。同时request对象被设置为根对象(root)。则利用下面的OGNL表达式求值:
request.name // 返回request.getName()
session.name //返回session.getName()
name //返回request.getName(),因为request为根对象
访问Ognl Context中的对象需要使用#符号标注命名空间,如#session.name,如果要访问的属性属于根对象,则可以省略命名空间,直接访问该属性,如request.name。
字符串中引用OGNL表达式:在标签的属性值被理解为字符串类型时,告诉执行环境%{}里的是OGNL表达式
2. 代码示例
[注意]:要使用ognl需要引入ognl-3.0.6.jar和javassist-3.11.0.GA.jar包,因为struts2的默认表达式语言是ognl所以struts2依赖的jar文件中包含这个文件。
3. Ognl与struts2
Ognl 有个上下文的概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map接口,在Struts2中上下文(Context的实现为ActionContext,下面是上下文(Context)的结构示意图
|--request (包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute("userName"))
|--application
|--ValueStack (root)
|--session
|--attr (用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止) #attr.username Attr.getUsername();
|--parameters(包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameterValues("id").get(0);) #parameters.Username Ognl.getValue(‘username’);
|--context表示pageContext
l 注意:Struts2框架总是把Action实例放在ValueStack的顶部。因为Action在ValueStack中,而ValueStack又是OGNL中的根,所以引用Action的属性可以省略“#”标记,所以我们在结果页面中可以直接访问Action的属性。
l struts2中ognl需要与struts2的标签配合使用。如:<s:property value=“”/> 注意:name接收的是OGNL表达式。
三、 Struts2标签库
Struts2的标签库大大简化了数据的输出,也提供了大量标签来生成页面效果。与strut1的标签库相比,struts2的标签库功能更加强大。而且更加简单易用。Struts2标签分类:
Struts 标签库常用标签包含控制标签、数据标签、UI标签,下面对一些常用的标签进行详细说明。
在jsp中使用struts2的标签库
1、 导入struts2的jar包,
2、 需要在jsp页面通过taglib jsp指令引入进来。
<%@taglib prefix="s" uri="/struts-tags" %>
引入进来之就表示我们的jsp页面可以通过<s: 来使用struts2的标签。
1. Data tags(数据标签)
Set标签:
set标签赋予变量一个特定范围内的值. 当希望给一个变量赋一个复杂的表达式,每次访问该变量而不是复杂的表达式时用到.其在两种情况下非常有用: 复杂的表达式很耗时 (性能提升) 或者很难理解 (代码可读性提高).
主要属性:
Var:变量的名称
Value:变量的值.ognl表达式,如果是字符串一定要加上单引号.
Scope:表示将变量设置到哪一个作用域可以为application, session, request, page, 或action.默认是action
<ww:set name="personName" value="person.name"/>
表示向action中保存personName;
Property标签:
得到'value'的属性,如果value没提供,默认为堆栈顶端的元素.
主要属性:
Default:如果属性为空就显示默认值。
Value:指向一个ognl表达式,如果没有指定value属性默认是显示栈顶的值。
<s:property value=”#session.name”/>
上例表示从session作用域中找name属性,
Bean:
实例化一个符合JavaBeans规范的class,标签体内可以包含几个Param元素,用于调用setter方法给此class的属性赋值.如果是定了id属性,则该实例将会放到stack的context中.
主要属性:
Name: 要被实例化的class名字(必须符合JavaBeans规范)(必须);
Id: 标识该元素,就是说可以通过ID 来使用这个Bean.
Param:有name和value两上属性 name表示会调用对应的set方法,value指定设置的值。
<s:bean name=”com.itjob.User” id=”user”>
<s:param name=”username” value=”’itjob’”></param>
</s:bean>
上例中实例化了一个user对象 并设置userName为itjob 并且保存到pagecontext,和pageContext中。
Debug标签
在开发过程中可以使用debug标签进行页面数据跟踪,调试。用于显示值栈中的信息
<s:debug/>
url 标签
动态的生成一个url。。
主要参数:
Action:用于指定url请求的action,如果不指定使用当前action会自动加上.action后缀
Value:不会自动加上.action后缀。
Method:用于指定请求action中的方法,,注意使用这种方式的话需要struts2打开动态方法调用的开关。会己action!method的方式进行请求。
Namespace:对应package中的namespace的值
<s:url action="point" method="add"/>
如上的标签请生成: /部署的项目名/namespace/point!add.action
<s:url action="point" method="add"/>
将生成: /部署的项目名/point.action
Include标签:
包含servlet的输出(servlet或JSP页面)。
属性:
Value: 包含的jsp或servlet
<s:include value="myJsp.jsp" />包含一个jsp页面
<s:include value="myJsp.jsp">
<s:param name="param1" value="value2" />
<s:param name="param2" value="value2" />
</s:include>
包含一个jsp页面并且传入两个参数,参数在jsp页面可以通过request.getParamter();得到。
I18n
将某个特定resource bundle放入value stack. 然后通过text标签拿到相应message, 而不是仅限于绑定到当前action的bundle.一个bundle其实就是一个java类用于读取properties文件,当前这个properties文件必须自己定义,这个标签使用并不多,因为struts2对国际化有自己的一套封装,不推荐再自己写bundle来读取资源文件。
常用的属性:
Name:要使用的bundle的类名
Text
支持国际化信息的标签
国际化信息必须放在一个和当前action同名的resource bundle中,如果没有找到相应message,tag body将被当作默认message,如果没有tag body,message的name会被作为默认message
属性:
Name:资源属性名称。就是指定properties文件中的key..
<s:text name="format.money"/>
表示从properties文件中获取key=format.money的值
3. Control tags控制标签
If elseif else标签
Struts2的流程控制标签.'If'标签可单独使用也可以和一个或多个'Else If'标签和'Else'一起使用,如果test属性指定的表达式返回true就在界面显示本体内容
属性列表
属性名 | 是否必填 | 缺省值 | 类型 | 描述 |
Test | 是 |
| Boolean | 一个ognl表达式必须返回boolean值 |
示例代码:
<s:if test="false">
if
</s:if>
<s:elseif test="true">
else if
</s:elseif>
<s:else>else</s:else>
Iterator标签
对集合类型迭代输出
属性名 | 是否必需 | 默认值 | 类型 | 描述 |
Status | False | False | Boolean | 如果提供该属性 每次迭代时候将生成一个IteratorStatus实例并放入堆栈中可通过#context.XXX的形式获取,常用对象如下: #status.odd 是否单数行 返回bool值 #status.even 是否双数行 返回bool #status.index 当前行的序号,从0开始 返回int #status.first 是否第一行 返回bool值 #status.last 是否最后一行 返回bool值 #status.count 第几行从1开始,返回int |
Value | False |
| Object/String | 迭代源, 或者一个对象被放入最新创建的List |
代码示例:
<s:set id="l1" value="{11,12,13}" />
<s:set id="l2" value="{14,15,16}" />
<s:append id='l3'>
<s:param value="#l1" />
<s:param value="#l2" />
</s:append>
<s:iterator value="#context.l3" status="sss" var="l">
<s:if test="#sss.first">开始循环</s:if>
<s:property value="#l" />
当前下标:<s:property value="#sss.index" />
<s:if test='#sss.even'>双数行</s:if>
<s:if test='#sss.odd'>单数行</s:if>
<s:if test="#sss.last">结束了</s:if>
<s:if test="#sss.count % 3 == 0">被3整除</s:if>
<br>
</s:iterator>
此列显示结果为:
开始循环 11 当前下标:0 单数行
12 当前下标:1 双数行
13 当前下标:2 单数行 被3整除
14 当前下标:3 双数行
15 当前下标:4 单数行
16 当前下标:5 双数行 结束了 被3整除
【注意】此例中集合的定义语法同map的定义,但是没有#号,
Append标签:
常和Iterator标签一起使用, 功能就是将不同的迭代器组合在一起,使一个迭代器迭代完成后转移到下一个迭代器中继续迭代.
参数说明:
Id: 标明新产生的迭代器在context中的名字,所以在其它地方使用的时候需要以#context.的方式.【必须】
<s:set id="m1" value="#{'a':1,'b':2 }"></s:set>
<s:set id="m2" value="#{'c':1,'d':2 }"></s:set>
<s:append id="m4">
<s:param value="m1" />
<s:param value="m2" />
</s:append>
<s:property value="#context.m4"/>
<s:iterator value="#context.m4" var="m">
<s:property value="#m.key"/>
</s:iterator>
上例中显示结果为:a b c d 表示将m1,m2组合后打印出所有的key,打印顺序为m1所有的key然后再打印m2所有的key .顺序是 append标签中param添加的顺序,本例中先添加的m1然后添加的m2所以先打印m1.
【注意】此例中 m1与m2的定义 ,分别定义了一个map
定义语法:#{‘key’:’value’,’key’:’value’} #{}表示产生一个map集合,键与值之间以’:’分割,元素之前以’,’逗号分割。
4. 表单标签详解
struts2的表单标签可分为两类:form标签本身和包装HTML表单元素的其他标签。form标签本身的行为不同于它内部的元素,html标签主要是一些表单元素如input radio checkbox等。
struts2表单标签包括:
form、textfield、password、radio、checkbox、checkboxlist、select、doubleselect、combobox、optiontransferselect、optgroup、updownselect、textaarea、hidden、file、label、submit、token、head
常用标签讲解:
Form:
类似于html的form表单元素,对其进行了封装。
常用属性:
Action:设置表彰提交的 url.
Method:设置表单提交方式 get post
Enctype:设置表彰提交格式
Onsubmit:表单提交事件,表示在表彰提交之前会调用某个方法。如果方法返回真,就将表彰提交到后台处理,否则不提交