Struts2(传智播客笔记7)

OGNL表达式语言
OGNL是Object Graphic Navigation Lanaguage(对象图导航语言)的缩写,它是一个开源项目。Struts2框架使用OGNL作为默认的表达式语言。
相对EL表达式,它提供了平时我们需要的一些功能,如:
1、支持对象方法调用
2、支持类静态方法调用和值访问,表达式的格式为
@[类全名(包括包路径)]@[方法名|值名],例如:java.lang.String@format('foo %s','bar')
3、操作集合对象

Ognl有一个上下文(Context)概念,就是一个MAP结构,它实现了java.util.Map接口,在Struts2中上下文(Context)的实现为ActionContext。
当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。
访问上下文(Context)中的对象需要使用#符号标注命名空间,如#application、#session。
另外OGNL会设定一个根对象(root对象),在Struts2中根对象就是ValueStack(值栈)。如果要访问根对象(即ValueStack)中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。
在Struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是我们想像的只存放单个值,而是存放一组对象。在OnglValueStack类里有一个List类型的root变量,就是使用它存放一组对象。
在root变量中处于第一位的对象叫做栈顶对象。通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。
注意:Struts2中,OGNL表达式需要配合Struts标签才可以使用。
为何使用EL表达式能够访问valueStack中对象的属性
原因是Struts2对HttpServletRequest作了进一步的封装。简略代码如下:
public class StrutsRequestWrapper extends HttpServletRequestWrapper{
    public StrutsRequestWrapper(HttpServletRequest req){
        super(req);
    }
    public Object getAttribute(String s){
        ...
        ActionContext ctx =  ActionContext.getContext();
        Object attribute = super.getAttribute(s);//先从request范围获取属性值
        if(ctx != null){
            if(attribute == null){//如果从request范围没有找到属性值,即从ValueStack中查找对象的属性值
                ...
                ValueStack stack = ctx.getValueStack();
                attribute = stack.findValue(s);
                ...
            }
        }
        return attribute;
    }
}
采用OGNL表达式创建List/Map集合对象
如果需要一个集合元素的时候(例如List对象或者Map对象),可以使用OGNL中同集合相关的表达式。
使用如下代码直接生成一个List对象:
<s:set var="list" value="{'第一个','第二个','第三个'}"/>
<s:iterator value="#request.list">
    <s:property/><br/>
</s:iterator>
Set标签用于将某个值放入指定范围
scope:指定变量被放置的范围,该属性可以接受application、session、request、page或action。如果没有设置该属性,则 默认放置在OGNL Context中。
value:赋给变量的值,如果没有设置该属性,则将ValueStack栈顶的值赋给变量。
生成一个Map对象:
<s:set var="maps" value="#{'key1':90,'key2':35,'key3':12}"/>
<s:iterator value="#maps">
    <s:property value="key"/> = <s:property value="value"/><br/>
</s:iterator>
OGNL表达式的投影功能
允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。
?:获得所有符合逻辑的元素
^:获得符合逻辑的第一个元素
$:获得符合逻辑的最后一个元素
例如代码:
<s:iterator value="books.{?#this.price > 35}">
    <s:property value="title"/> - $<s:property value="price"/>
</s:iterator>
在上面代码中,直接在集合后紧跟.{}运算符表明用于取出该集合的子集,{}内的表达式用于获取符合条件的元素,this指的是为了从大集合books筛选数据到小集合,需要对大集合books进行迭代,this代表当前迭代的元素。本例的表达式用于获取集合中价格大于35的书集合。
property标签
property标签用于输出指定值:
<s:set name="name" value="value"/>
<s:property value="#name"/>
default:可选属性,如果需要输出的属性值为null,则显示该属性指定的值
escape:可选属性,指定是否格式化HTML代码
value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出ValueStack栈顶的值
id:可选属性,指定该元素的标识
iterator标签
iterator标签用于对集合进行迭代,这里的集合包含List、Set和数组。
<s:set var="list" value="{'第一个','第二个','第三个'}"/>
<s:iterator value="#request.list" status="status">
    <font color='<s:if test="#request.status.isOdd()">red</s:if><s:else>blue</s:else>'>
    <s:property/></font><br/>
</s:iterator>
value:可选属性,指定被迭代的集合,如果没有设置该属性,则使用ValueStack栈顶的集合
id:可选属性,指定集合里元素的id(已被标注为过时)
status:可选属性,该属性指定迭代时的IteratorStatus实例。该实例包括如下几个方法:
int getCount():返回当前迭代了几个元素
int getIndex():返回当前迭代元素的索引
boolean isEven():返回当前被迭代元素的索引是否是偶数
boolean isOdd():返回当前被迭代元素的索引是否是奇数
boolean isFirst():返回当前被迭代元素是否是第一个元素
boolean isLast():返回当前被迭代元素是否是最后一个元素
url标签
<s:url action="helloworld_add" namespace="/test">
    <s:param name="personid" value="23"/>
</s:url>
生成类似如下路径:
/Struts2/test/helloworld_add.action?personid=23
当标签的属性值作为字符串类型处理时,"%"符号的用途是计算OGNL表达式的值。
<s:set name="myurl" value="'http://www.foshanshop.net'"/>
<s:url value="#myurl"/><br/>
<s:url value="%{#myurl}"/>
输出结果:
#myurl
http://www.foshanshop.net
表单标签checkboxlist复选框
如果集合为list
<s:set name="myurl" value="'http://www.foshanshop.net'"/>
<s:url value="#myurl"/><br/>
<s:url value="%{#myurl}"/>
如果集合为Map
<s:checkboxlist name="map" list="#{1:'瑜珈用品',2:'户外用品',3:'球类',4:'自行车'}" listKey="key" listValue="value" value="{1,2,3}"/>
如果集合里存放的是JavaBean
<%
    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person(1,"电视"));
    persons.add(new Person(2,"电脑"));
    persons.add(new Person(3,"洗衣机"));
    request.setAttribute("persons",persons);
%>
<s:checkboxlist name="persons" list="#request.persons" value="{3}" listKey="id" listValue="name"/><br/>
id和name为Person的属性
表单标签radio单选框
该标签的使用和checkboxlist复选框相同。
如果集合里存放的是JavaBean(id和name为Person的属性)
<s:radio name="beans" list="#request.persons" listKey="id" listValue="name"/>
如果集合为Map
<s:radio name="map" list="#{1:'瑜珈用品',2:'户外用品',3:'球类',4:'自行车'}" listKey="key" listValue="value" value="1"/>
如果集合为list
<s:radio name="list" list="{'Java','Net'}" value="'Java'"/>
表单标签select下拉选择框
<s:select name="list" list="{'Java','Net'}" value="'Java'"/>
<s:select name="beans" list="#request.persons" listKey="id" listValue="name"/>
<s:select name="map" list="1:'瑜珈用品',2:'户外用品',3:'球类',4:'自行车'" listKey="key" listValue="value" value="1"/>
JavaWeb表单重复提交的原理
1、指定jsp页面
    生成一个隐藏域,产生一个唯一的永不重复的字符串
    同时,把该字符串放入到session中一份
2、点击按钮提交时
    获取隐藏域的值
    String token.html = request.getParameter("token.html");
    获取session中存放的值
    String token.key = session.getAttribute("token.key");
    对比隐藏域的值和session中存放的值
    如果相等,保存数据
    如果不相等,表单重复提交
Struts2表单重复提交解决方案
<s:token/>标签防止重复提交,用法如下:
第一步:在表单中加入<s:token/>
第二步:在struts.xml配置文件的action内添加
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="token"/>
<result name="invalid.token">/WEB-INF/page/message.jsp</result>
以上配置加入了"token"拦截器和"invalid.token"结果,因为"token"拦截器在会话的token与请求的token不一致时,将会直接返回"invalid.token"结果。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值