`
allwefantasy
  • 浏览: 45800 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Struts2 与 OGNL ( 投影 过滤 ) 以及pojo依赖注入的方法

阅读更多
   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层有点瘦客户端的感觉,有时也可以让他胖起来!(*^__^*) 嘻嘻……
分享到:
评论
1 楼 wenxiang_tune 2011-01-20  
给力!这文章好,不过我想知道Map<String,List<xxx>> 中如果投影的话怎么判断xxx中的值,怎么写?因为我要在每次循环之前就判断一下xxx中的某个属性是否。。。

相关推荐

    天然气汽车供气系统减压装置毕业设计(cad+设计方案).zip

    天然气汽车供气系统减压装置毕业设计(cad+设计方案)

    PHP+SQL考勤系统安全性实现(源代码+论文+答辩PPT+指导书)

    PHP+SQL考勤系统安全性实现(源代码+论文+答辩PPT+指导书)

    NumPy 的用途是什么

    NumPy 的用途是什么

    毕业设计 基于javaweb的在线答题平台

    毕业设计 基于javaweb的在线答题平台

    基于MATLAB的pca人脸识别.zip

    基于MATLAB的pca人脸识别.zip

    课设毕设基于SSM的信息类课程教学知识管理系统LW+源码可运行.zip

    课设毕设基于SSM的系统源码可运行

    JAVAWML信息查询与后端信息发布系统实现-WML信息查询设计(源代码+LW).zip

    JAVAWML信息查询与后端信息发布系统实现——WML信息查询设计(源代码+LW)

    毕业设计[整站程序]情感家园站 v3.0 For 个人版_qgweb30fp.zip

    毕业设计[整站程序]情感家园站 v3.0 For 个人版_qgweb30fp.zip

    熊猫脚本助手V1.8.zip

    可以自动刷课,执行重复的脚本工作,内有详细操作教程。支持WIN7---WIN10系统。

    Java项目之实验室计算机故障报修系统(源码)

    Java项目之实验室计算机故障报修系统(源码) 开发语言:Java 框架:ssm 技术:JSP JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9

    使用hapi框架搭建 基于协同过滤的美食推荐系统——后台.zip

    协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。

    JAVAWEB校园二手平台项目.zip

    JAVAWEB校园二手平台项目,基本功能包括:个人信息、商品管理;交易商品板块管理等。本系统结构如下: (1)本月推荐交易板块: 电脑及配件:实现对该类商品的查询、用户留言功能 通讯器材:实现对该类商品的查询、用户留言功能 视听设备:实现对该类商品的查询、用户留言功能 书籍报刊:实现对该类商品的查询、用户留言功能 生活服务:实现对该类商品的查询、用户留言功能 房屋信息:实现对该类商品的查询、用户留言功能 交通工具:实现对该类商品的查询、用户留言功能 其他商品:实现对该类商品的查询、用户留言功能 (2)载入个人用户: 用户登陆 用户注册 (3)个人平台: 信息管理:实现对商品的删除、修改、查询功能 添加二手信息:实现对新商品的添加 修改个人资料:实现对用户个人信息的修改 注销

    基于协同过滤和SVD算法的音乐推荐系统.zip

    协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。

    Java游戏设计打飞机程序(源代码+LW).zip

    Java游戏设计打飞机程序(源代码+LW)

    Matlab实现CoMP多用户注水算法在最最基础的注水算法的基础上,

    Matlab实现CoMP多用户注水算法在最最基础的注水算法的基础上,实现了在功率受限速率受限的情况下CoMP多用户的功率分配.zip

    利用PCA算法的 Eigenface 人脸识别的训练与识别

    自己写代码实现 Eigenface 人脸识别的训练与识别过程,纯手工实现 假设每张人脸图像只有一张人脸,且两只眼睛位置已知(即可人工标注给出)。每张图像的眼睛位置存在相应目录下的一个与图像文件名相同但后缀名为 txt 的文本文件里,文本文件中用一行、以空格分隔的 4 个数字表示,分别对应于两只眼睛中心在图像中的位置; 实现两个程序过程(两个执行文件),分别对应训练与识别; 自己构建一个人脸库(至少 40 人,包括自己),课程主页提供一个人脸库可选用; 不能直接调用 OpenCV 里面与 Eigenface 相关的一些函数,特征值与特征向量求解函数可以调用;只能用 C/C++/Python,不能用其他编程语言;GUI 只能用 OpenCV 自带的 HighGUI,不能用 QT 或其他的;平台可以用 Win/Linux/MacOS,建议 Win 优先;

    有源电力滤波器的控制在MATLAB下的发展。三相电源电压是基于hysterezis正弦电流调节器.zip

    有源电力滤波器的控制在MATLAB下的发展。三相电源电压是基于hysterezis正弦电流调节器.zip

    BCH码的MATLAB程序源代码.zip

    BCH码的MATLAB程序源代码.zip

    基于java的一个简单的即时通讯工具的设计与开发(源代码+LW).zip

    基于java的一个简单的即时通讯工具的设计与开发(源代码+LW)

    蓝桥杯-基础题C++: 其压缩包中为C++ code

    参加比赛的一些心得:感觉把比赛得那一门语言基础学会,输入输出([我写的python输入输出](https://blog.csdn.net/qq_41392228/article/details/123614298)),([C++的STL](https://blog.csdn.net/qq_41392228/article/details/124825895)),熟练里面的数据结构,如数组,map等,==主要还是基础==。熟悉了后,可以在刷一下基础题,巩固哈学了的基础知识。把基础学好了,拿个奖是没问题的,正常发挥即可。想那个好的名词,就要看看相关的算法了,主要就是暴力的+优化,BFS,DFS,比较难的就是动态规划,得找转换方程。 python版本的可见:https://blog.csdn.net/qq_41392228/article/details/123616441

Global site tag (gtag.js) - Google Analytics