ORM(这里我们以hibernate为例子)的对象关联使得对象之间的导航变得十分清晰与明了。对开发员而言,感觉到的是优雅与实用。
想下通过Orm的关联,我们不用再和sql打交道(这个也不一定,我的看法是绝不勉强用哪一个,哪一个合适,就用哪一个),
我们可以相当的方便拿到与之相关的对象。当然取出来的数据还是要显示在页面上给用户看的。这里便是Ognl显神通的地方了。
Ognl是个脚本语言,弱类型,可以运行时判断对象类型。和Struts2标签结合相当不错。之前 javaeye有个struts2系列教程,作者对Ognl的介绍就很不错。有空大家可以看看。
今天我们研究一个案例。
有个站内信类,我们叫它Message,如下:
public class Message implements java.io.Serializable
{
// Fields
private Integer id;
private User user;//收件人
private Integer fromId;//发信人Id
}
由于信件Message和User类有两个关联,但是当时设计的话只是用了一次一对多关联,发信人则直接使用其Id,这就丧失了导航的优势
但我在页面显示相关信息的时候 比如我想显示发件人的头像 headIcon,姓名等,但Message并没有这个字段,同时也无法通过 getUser()之类的导航来得到,,也就是我们必须通过显示连接查询获得fromId对象。
于是我想到了另外一个解决方案
也就是在页面通过Message中的fromId取得会员对象,通过加载的User对象取得headIcon.
这时我写了一个新的类,我们称之为PageHelper 代码如下:
package com.snail.commons.util;
import org.apache.log4j.Logger;
import com.snail.commons.basedao.IBaseDAO;
public class PageHelper
{
private IBaseDAO baseDAO;//一个负责持久层的对象
public PageHelper(IBaseDAO baseDAO)
{
this.baseDAO=baseDAO;
}
private final static Logger logger=Logger.getLogger(PageHelper.class);
/*
clz:String 类的全名(包括包名,例如import com.snail.commons.beans.User)
id :integer 需要加载的id
*/
public Object loadEntity(String clz,Integer id)
{
Class temClz=null;
try {
temClz=Class.forName(clz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object obj=baseDAO.findEntity(temClz, id);
return obj;
}
}
通过这个类,我们就能动态加载需要的类,并且取得相应的持久化对象。
我们看下在页面如何调用:
<s:property value="(new com.snail.commons.util.PageHelper(baseDAO)).loadEntity('com.snail.component.beans.User',fromId).headPic"/>
我们首先实例化PageHelper类,需要注意的是,在Ognl表达式中,必须使用全类名,接着直接调用其方法。
当然也可以将loadEntity定义为静态方法,相应的,你应该改成
<s:property value="@com.snail.commons.util.PageHelper@loadEntity('com.snail.component.beans.User',fromId).headPic"/>
当然对于上面的案例来说,我们可以通过构造方法传入baseDAO对象(第一种调用方法),也可以通过(参数传递baseDAO,不过这里的例子没有体现)我这里只是作为Ognl静态方法调用的一个示例。
(个人感觉上面的方案破坏了MVC的封层,这相当于数据库经过Service层直接到了展示层。同事效率也大了折扣,假设我要显示一百条信息,必须调用一百次Sql操作才能取出
相应的User对象。有点像n+1问题);
Rails 里面有个ApplicationHelper 帮助程序,我觉得很好,加强了页面的表现能力,我们可以在页面调用ApplicationHelper中的任何公开方法,比如实现一些截取规定长度字符等功能,当然在struts中我们可以通过标签实现,或者通过已有标签组合实现类似功能,不过都比较麻烦,哪有调用一个静态方法来得爽?
ognl就为我们提供了类似于ApplicationHelper 的实用类。
比如我们可以新建一个类假设叫PageHelper:里面有个静态方法==》
public static String substring(String str,List params)
{
if(params.size()==1)
{
Integer end=(Integer)params.get(0);
return str.substring(0,end<=str.length()?end:str.length());
}
else if(params.size()==2)
{
Integer start=(Integer)params.get(0);
Integer end=(Integer)params.get(1);
return str.substring(start,end<=str.length()?end:str.length() );
}
return str;
}
然后我们可以直接在页面上调用
<s:property value="@com.snail.commons.util.PageHelper@sustring('abc',{})"/>
这样便实现了字符截取功能。另外上面代码中的"{}",代表新建的一个List对象,很简洁吧,恩 ognl具有很多动态语言的特性。
另外我很想知道的是,如何在一个普通的Pojo类中拿到spring的bean,而且该类是我们自己直接实例化的。如果哪位大大知道的话,不妨告知一声。([color=orange]后来才理清头绪,如果解决了这个问题,也就解决了富领域模型的问题。
关于富领域模型问题,javaeye讨论了很多,到hibernate模块有很多精华好贴。我这里不讨论其优劣,只是提几句实现的方案:
第一种:
ps:也是最好的方案
在spring2.0之后,已经通过aspectj支持静态织入持久化工具类,我这里不展开,大家可以参看spring文档(或许我会另起一文详细说说步骤),不过唯一不爽的是要个什么
设置 javaagent=aspectj jar包路径
第二种:
ps:比较繁琐,但对于新新项目也是比较保险,可控性高一点的
在pojo类设置一个set方法,每次使用该pojo之前,给它set一个持久化工具类,之后pojo类里面的方法就具有了持久化功能,或者严格点,给每个Pojo类用到持久化工具类的方法全部以持久化工具类为其中之一的参数
第三种:
ps:很有技巧性
不管你pojo是谁产生的,你的静态成员总是所有实例共享的吧,我如果给你的静态成员设置上持久化工具类,那所有的pojo实例都可以共享吧。
这种实现方案有两个:
no1 :通过spring拦截pojo在加载时的静态方法,赋值。这样省事,不过
no2 :有三个类,A, B,C, A用spring加载,实现ApplicatioContextAware接口,注入context.类B有一个静态域,该静态域通过set属性注入。这个可能不是很好理解,我们举个例子,
@Component
public class B
{
private static ApplicationContext context;
@Autowired(required = true)
public void setUserAccessor(A a) {
B.context = a.context;
}
}
这样应该容易理解一些
接着在C类中我们可以直接使用B中的静态域,很棒是吧
这样我们就可以将很多东东注入到不归spring管理的的自己实例化的类里面去了。
再次ps:我个人最喜欢这个方案最简洁
第四种:
ps:hibernate自己的解决方案
可以参看https://www.hibernate.org/182.html
这种方案就是通过hibernate拦截器在加载pojo类的时候注入。
当然还有很去哦其他的方案,大家可以google一下。
[/color])
Ognl的另外一个比较重要的用法是投影与过滤。网上好像讲的比较少。我在这里提一下。
第一个示例是 如何迭代一个数字,最简单的比如分页,我的pageSize=7,如何迭代出七个Option呢,如下。
<select>
<s:iterator value="pageSize.{#this}" status="sta">
<option> <s:property value="#sta.index+1"/></option>
</s:iterator>
</select>
上面有个重点: pageSize.{#this} 这是个过滤操作,得到的是一个集合。this指当前正在迭代的对象。前面的#不用说了,是ognl本省语法需要的。
假设我想迭代出大于3的几个数字,
这个时候可以这样pageSize.{#this>3}
结合ongl的过滤与投影操作,可以使得页面也有强大的逻辑操作以及过滤功能。
我们在看一个稍微复杂一点的例子:
三个类
Gequ(歌曲) ,Gequzhuanji(歌曲专辑),Gequgequzhuanji(歌曲歌曲专辑 中间表)。
Gequ=> Gequgequzhuanji 一对多关系
Gequzhuanji=> Gequgequzhuanji 一对多关系
现在我拿到了一个Gequgequzhuanji的集合,对这个集合我想显示出拥有者为master的专辑的名称,而且只要第一个。
下面的代码可以实现:
<s:property value="gequgequzhuanjis.{^#this.gequzhuanji.huiyuan.name eq 'master')}[0].zhuanJiMing" default="单曲"/>
我们来解释一下:
显然gequgequzhuanjis.{}是一个过滤操作。过滤得到的也是一个集合,这个结合需要[n]操作拿到某个元素,最终通过.拿到起属性值。
就这么简单
恩 不知道讲清楚了。大家可以再参考下ognl的官方文档。个人觉得Ognl是个强大的脚本语言。支持常用的一些操作符,比如基本类型使用==等,对象比较可以使用
eq 之类的。在传统的MVC结构中,V层有点瘦客户端的感觉,有时也可以让他胖起来!(*^__^*) 嘻嘻……
分享到:
相关推荐
6. **安全机制**:为了防止OGNL注入攻击,Struts2提供了安全配置,限制可以访问的对象和属性。 源码阅读可以帮助我们了解OGNL的工作原理,如如何解析表达式,如何找到正确的ValueResolver,以及如何处理上下文中的...
7. **表达式过滤器**:为了安全考虑,Struts2允许配置OGNL表达式过滤器,防止潜在的OGNL注入攻击。 8. **异常处理**:当OGNL表达式无法解析时,Struts2会抛出相应的异常,如`ValueExpressionException`,帮助开发者...
Struts2_OGNL Demo 是一个用于演示Struts2框架中OGNL(Object-Graph Navigation Language)表达式语言的实例。这个项目旨在帮助开发者理解和学习如何在Struts2中使用OGNL来操纵对象和数据。OGNL是Struts2中一个重要的...
OGNL(Object-Graph Navigation Language)是Struts2框架中的一个重要组件,用于在Web应用中访问和操作Java对象的属性,调用其方法,以及执行类型转换等操作。 OGNL是对象图导航语言的缩写,它是一种功能强大的...
在 Struts2 中,OGNL 是一个强大的工具,允许开发者访问和操作 ValueStack 中的对象的属性和方法。 一、访问 ValueStack 中的对象属性 在 Struts2 中,可以使用 OGNL 来访问 ValueStack 中的对象属性,例如: ...
struts2 中 OGNL表达式的使用struts2 中 OGNL表达式的使用
在Struts2中,OGNL用于处理动作类的属性到JSP页面的传递,以及用户输入到动作类的绑定。 首先,让我们了解OGNL的基本语法。OGNL表达式通常包含两个部分:对象引用和属性访问。例如,`user.name`表示获取名为`user`...
5. **安全特性**:在Struts2中,OGNL的不当使用可能导致安全漏洞,如著名的Struts2 OGNL注入攻击。源代码中包含了对这种风险的防护措施,如输入过滤和安全配置选项。 深入学习这些源代码,开发者不仅可以了解OGNL的...
因此,在实际应用中,应确保对用户输入进行严格的校验和过滤,或者使用Struts2的安全插件来防止OGNL注入。 五、总结 OGNL在Struts2中扮演着关键角色,它简化了数据绑定和对象交互。然而,开发者也需要注意其潜在的...
在Struts2中,OGNL被广泛用于访问Action中的属性,以及在视图层(如JSP)中绑定和操作数据。 首先,OGNL使得访问对象属性变得非常直观。它支持点符号(.)和方括号([''])两种方式来访问属性。例如,如果在Action...
- Struts2中OGNL与Action、ValueStack的关系。 - OGNL的安全性问题,如OGNL注入攻击,以及如何防范。 在压缩包文件`struts-ognl.asta`中,可能包含了一些示例或测试用例,用于演示Struts2中PropertyAccessor的使用...
在这个主题中,我们将深入探讨Struts2与OGNL的整合以及它们在实际开发中的应用。 **Struts2框架概述** Struts2是Apache软件基金会的开源项目,它是Struts1的升级版,提供了更多的特性和灵活性。Struts2的核心设计...
4. **与Struts2的集成**:OGNL可以无缝集成到Struts2的Action、拦截器等组件中。 5. **动态性**:OGNL表达式可以在运行时动态解析。 #### 二、OGNL在Struts2中的使用方式 OGNL在Struts2中主要用于页面显示数据、...
本文将详细介绍Struts2、Webwork以及Ognl的相关知识点,并提供入门指导。 **Struts2框架** Struts2是在原有的Struts1基础上发展起来的,它整合了Webwork框架的优势,提供了更灵活的控制流和更强大的拦截器机制。...
Struts2是一个流行的Java Web应用程序框架,它极大地简化了MVC(模型-视图-控制器)架构的实现。...在学习过程中,记得关注OGNL表达式的语法、安全问题(如防止OGNL注入攻击)以及性能优化等方面的知识。
Struts2 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,它在Struts2框架中扮演着核心角色,用于数据绑定、控制流程以及动态方法调用。这篇博文可能详细介绍了Struts2框架中OGNL的使用、工作原理...
这篇博客文章"Struts2对Ognl的封装--TypeConverter"探讨了Struts2如何通过TypeConverter机制来增强OGNL的功能。 首先,我们来看一下OGNL。OGNL允许开发者用简洁的语法来获取和设置对象的属性,甚至可以进行复杂的...
这篇文档将深入探讨在Struts2中使用OGNL表达式的实验代码,以及其相关知识点。 首先,了解OGNL的基本概念至关重要。OGNL允许我们直接通过字符串表达式来访问和修改对象的属性。例如,如果我们有一个用户对象`user`...