`
sanfran_qi
  • 浏览: 11931 次
  • 性别: Icon_minigender_1
  • 来自: 福州
文章分类
社区版块
存档分类
最新评论

Struts2中#、%和$这三个符号的使用方法

 
阅读更多

要谈OGNL在Struts2中的应用,首先得明白OGNL到底是什么


OGNL 的历史

OGNL 最初是为了能够使用对象的属性名来建立 UI 组件 (component) 和 控制器 (controllers) 之间的联系,简单来说就是:视图 与 控制器 之间数据的联系。后来为了应付更加复杂的数据关系,Drew Davidson 发明了一个被他称为 KVCL(Key-Value Coding Language) 的语言。 Luke 参与进来后,用 ANTLR 来实现了该语言,并给它取了这个新名字,他后来又使用 JavaCC 重新实现了该语言。目前 OGNL 由 Drew 来负责维护。目前很多项目中都用到了 OGNL,其中不乏为大家所熟知的,例如几个流行的 web 应用框架:WebWork【当然struts2也可以说是WebWork升级版】,Tapestry 等。


什么是 OGNL?

OGNL 是 Object-Graph Navigation Language 的缩写,从语言角度来说:它是一个功能强大的表达式语言,用来获取和设置 java 对象的属性 , 它旨在提供一个更高抽象度语法来对 java 对象图进行导航,OGNL 在许多的地方都有应用,例如:

1)作为 GUI 元素(textfield,combobox, 等)到模型对象的绑定语言。

2)数据库表到 Swing 的 TableModel 的数据源语言。

3)web 组件和后台 Model 对象的绑定语言 (WebOGNL,Tapestry,WebWork,WebObjects) 。

4)作为 Jakarata Commons BeanUtils 或者 JSTL 的表达式语言的一个更具表达力的替代语言。


另外,java 中很多可以做的事情,也可以使用 OGNL 来完成,例如:列表映射和选择。对于开发者来说,使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说:通过一个“路径”来完成对象信息的导航,这个“路径”可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成



OGNL 的基本语法

OGNL 表达式一般都很简单。虽然 OGNL 语言本身已经变得更加丰富了也更强大了,但是一般来说那些比较复杂的语言特性并未影响到 OGNL 的简洁:简单的部分还是依然那么简单。比如要获取一个对象的 name 属性,OGNL 表达式就是 name, 要获取一个对象的 headline 属性的 text 属性,OGNL 表达式就是 headline.text 。 OGNL 表达式的基本单位是“导航链”,往往简称为“链”。最简单的链包含如下部分:

表达式组成部分 示例

属性名称 如上述示例中的 name 和 headline.text

方法调用 hashCode() 返回当前对象的哈希码。

数组元素 listeners[0] 返回当前对象的监听器列表中的第一个元素。


所有的 OGNL 表达式都基于当前对象的上下文来完成求值运算,链的前面部分的结果将作为后面求值的上下文。你的链可以写得很长,例如:

name.toCharArray()[0].numericValue.toString()


上面的表达式的求值步骤:

提取根 (root) 对象的 name 属性。

调用上一步返回的结果字符串的 toCharArray() 方法。

提取返回的结果数组的第一个字符。

获取字符的 numericValue 属性,该字符是一个 Character 对象,Character 类有一个 getNumericValue() 方法。

调用结果 Integer 对象的 toString() 方法。

上面的例子只是用来得到一个对象的值,OGNL 也可以用来去设置对象的值。当把上面的表达式传入 Ognl.setValue() 方法将导致 InappropriateExpressionException,因为链的最后的部分(toString())既不是一个属性的名字也不是数组的某个元素。了解了上面的语法基本上可以完成绝大部分工作了。


OGNL 表达式

1)常量:字符串:“ hello ” 字符:‘ h ’ 数字:除了像 java 的内置类型 int,long,float 和 double,Ognl 还有如例:

0.01B,相当于 java.math.BigDecimal,使用’ b ’或者’ B ’后缀。 100000H,相当于 java.math.BigInteger,使用’ h ’ 或 ’ H ’ 后缀。

2)属性的引用例如:user.name

3)变量的引用例如:#name

4)静态变量的访问使用 @class@field

5)静态方法的调用使用 @class@method(args), 如果没有指定 class 那么默认就使用 java.lang.Math.

6)构造函数的调用例如:new java.util.ArrayList();

其它的 Ognl 的表达式可以参考 Ognl 的语言手册。



OGNL的性能


OGNL,或者说表达式语言的性能主要又两方面来决定,一个就是对表达式的解析 (Parser),另一个是表达式的执行,OGNL 采用 javaCC 来完成 parser 的实现,在 OGNL 2.7 中又对 OGNL 的执行部分进行了加强,使用 javasisit 来 JIT(Just-In-Time) 的生成 byte code 来完成表达式的执行。 Ognl 给这个功能的名字是:OGNL Expression Compilation 。基本的使用方法是:

SimpleObject root = new SimpleObject();

OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null);

Node node = (Node) Ognl.compileExpression(context, root, "user.name");

String userName = (String)node.getAccessor().get(context, root);

实践证明:OGNL 非常接近 java 直接调用的时间。



表达式语言主要有以下几大好处:

1)避免(MyType) request.getAttribute()和myBean.getMyProperty()之类的语句,使页面更简洁;

2)支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能;

3)简单明了地表达代码逻辑,使用代码更可读与便于维护。


Struts 2中的表达式语言

Struts 2支持以下几种表达式语言:

1)OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;

2)JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;

3)Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;

4)Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。


Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:

支持对象方法调用,如xxx.doSomeSpecial();

支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;

支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;

访问OGNL上下文(OGNL context)和ActionContext;

操作集合对象。



一、"#"的用法

1、 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:

parameters 包含当前HTTP请求参数的Map #parameters.id[0]作用相当于request.getParameter("id")

request 包含当前HttpServletRequest的属性(attribute)的Map #request.userName相当于request.getAttribute("userName")

session 包含当前HttpSession的属性(attribute)的Map #session.userName相当于session.getAttribute("userName")

application 包含当前应用的ServletContext的属性(attribute)的Map #application.userName相当于application.getAttribute("userName")

attr 用于按request > session > application顺序访问其属性(attribute) #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止

2、用于过滤和投影(projecting)集合,如books.{?#this.price<100};

3、构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。


二、"%"的用法

“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:

<h3>%的用途</h3>

<p><s:url value="#foobar['foo1']" /></p>

<p><s:url value="%{#foobar['foo1']}" /></p>


三、"$"的用法

1、用于在国际化资源文件中,引用OGNL表达式

2、在Struts 2配置文件中,引用OGNL表达式

例如:

<action name="AddPhoto" class="addPhoto">

<interceptor-ref name="fileUploadStack" />

<result type="redirect">ListPhotos.action? albumId=${albumId}</result>

</action>

Struts2的标签,valueStack,$ ,# ,% 的问题

struts2的标签是使用OGNL表达式语言访问数据,OGNL使用的是Context包含对象,而Context的根对象就是ValueStack,所以对于ValueStack中的
属性可以直接访问。如下:
ValueStack中有属性name,则访问形式为:${name},或使用struts2标签:<s:propertyvalue="name"/>
但这种形式是不行的:<s:propertyvalue="${name}"/>,将报错:AccordingtoTLDorattributedirectiveintagfile,attributevaluedoesnotacceptanyexpressions
这是因为struts2标签将其认为是el标签,而struts2标签不接受el标签。
对于这种形式:<s:textfieldname="name"value="%{name}"></s:textfield& gt;value属性获取值name值时用到了%{name},这是因为不加%{}他就认为value的值就是"name"了,而不是name属性的值
加了%{}后struts2标签才会认出是要name属性的值。其实我们可以直接这样写,而不用value属性<s:textfieldname="name"></s:textfield>
对于不是栈顶的对象的访问要使用#,看下面的例子:
publicclassTestActionextendsActionSupport{
privateStringname;
privateExamTypeexamType;
publicStringexecute(){
this.setName("xian");
ExamTypeet=newExamType();
et.setExam_Type("考试课");
et.setExamT_Id(12l);
et.setComments("考试课是要考试的");
this.setExamType(et);
Mapmap=ActionContext.getContext().getSession();
map.put("str","yesyesyes");
returnSUCCESS;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicExamTypegetExamType(){
returnexamType;
}
publicvoidsetExamType(ExamTypeexamType){
this.examType=examType;
}

}
页面的body部分
<body>
<s:debug></s:debug>//struts2的调试标签,很有用,能看到Context中的内容
<s:textfieldname="name"></s:textfield><br>
<s:textfieldname="examType.exam_Type"></s:textfield><br>
<s:propertyvalue="examType.exam_Type"/><br>
<s:propertyvalue="name"/><br>
<inputtype="text"value="${examType.exam_Type}">
${str}<br>
<s:propertyvalue="#session.str"/><br>
</body>
打开debug后,可以看到下面这些信息
Struts2的标签,valueStack, , , 的问题 - xian_zx@126 - xian_zx@126的博客

这里的属性就是属于根对象ValueStack的,可以直接访问,如<s:textfieldname="name"></s:textfield><br>
Struts2的标签,valueStack, , , 的问题 - xian_zx@126 - xian_zx@126的博客
Struts2的标签,valueStack, , , 的问题 - xian_zx@126 - xian_zx@126的博客
这里的是不是根对象的属性,使用#访问,如<s:propertyvalue="#session.str"/><br>即#key.proName
若这样访问${str}也行,因为属性值是从栈顶一直向下比较而得出值来的

分享到:
评论

相关推荐

    Struts2_OGNL 笔记

    大家经常遇到的问题是#、%和$这三个符号的使用。下面我想通过例子讲述这个问题: 首先新建名为Struts2_OGNL的Web工程,配置开发环境。之前很多朋友在使用Struts 2的过程中都遇到乱码问题。当然乱码问题由来已久,...

    ognl表达式java使用案例详解(测试通过)

    本案例提供ognl使用详解,测试通过,只需解压放入自己WEB项目中,执行struts_ognl包内java文件即可(未提供jia包,若需要可以联系留言发至邮箱),若测试不好可以联系本人提供指导. ...主要是#、%和$这三个符号的使用;

    struts2 标签库 帮助文档

    struts2框架的标签库分为三类: 用户标签:生成HTML元素 非用户标签:数据访问、逻辑控制等。 AJAX标签:支持AJAX技术。 用户界面标签又分两类: 表单标签:生成HTML页面的from元素 非表单标签:生成页面上的...

    ssh2(struts2+spring2.5+hibernate3.3)自动生成模版

    generator\template\src\conf\${subpackage}\目录下有8个xml文件,4个配置文件中是带有xml文件头信息的,4个配置文件不带头文件信息,也就是说这4个文件是标准的配置文件,还有4个是非标准的(文件名中带有-insert的)。...

    java面试宝典

    156、在jsp:useBean语法中使用beanName有何好处? 37 157、当我使用时,在浏览器的地址栏没有改变? 37 158、如何转换JSP 0.9版本的文件到JSP1.1? 37 160、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么...

    freemarker总结

    可以看到例子中使用的两个同名变量并没有冲突,因为它们位于不同的名字空间 l 可以使用assign指令在导入的名字空间中创建或替代变量,下面是一个例子: &lt;#import "/lib/my_test.ftl" as my&gt; ${my.mail} &lt;#...

    FreeMark学习笔记

    ${week[2]} //输出第三个集合元素 此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法: week[3..5] //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素 3,输出Map...

    Quartz-Job-Scheduling-Framework-中文版-V0.9.1.zip

    内容提要:开始介绍 Quartz 插件,以及它要实现的接口和其中的三个接口方法的使用时机和用途。 第八章. 使用 Quartz 插件 (第二部分) 内容提要:讲述如何创建 Quartz 插件,并用一个从指定目录中加载所有 Job 文件...

    千方百计笔试题大全

    156、在jsp:useBean语法中使用beanName有何好处? 37 157、当我使用时,在浏览器的地址栏没有改变? 37 158、如何转换JSP 0.9版本的文件到JSP1.1? 37 160、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么...

    整理后java开发全套达内学习笔记(含练习)

    进行高精度运算可以用java.math包中BigDecimal类中的方法。 自动类型提升又称作隐式类型转换。 强制类型转换:int ti; (byte) ti ; 强制转换,丢弃高位 宣告变量名称的同时,加上“final”关键词来限定,这个...

    react-native-emoji-input:一个功能齐全的表情符号键盘:keyboard:,用于React Native:atom_symbol:

    专为制造和使用。 安装 npm install --save react-native-emoji-input 要么 yarn add react-native-emoji-input 如果更改了表情符号同义词文件,则需要重新编译数据源。 要编译表情符号数据集,请运行: npx ...

    UML和模式应用(架构师必备).part06.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part01.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part07.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part02.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part03.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part04.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part08.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    UML和模式应用(架构师必备).part05.rar

    16.5 注解符号:注解、注释、约束和方法体 16.6 操作和方法 16.7 关键字 16.8 构造型、简档和标记 16.9 UML特性和特性字符串 16.10 泛化、抽象类、抽象操作 16.11 依赖 16.12 接口 16.13 组合优于聚合 ...

    技术路线图上的企业品牌:索尼-研究论文

    设计/方法/方法:索尼的年度报告和CEO声明中出现的四页声明是使用五阶段符号方法进行解构的。 结果:本研究的结果说明了对国际技术路线图的追求如何引发了三个公司协会/神话的出现,即绩效,创新和企业家精神。 ...

Global site tag (gtag.js) - Google Analytics