论坛首页 Java企业应用论坛

在多层框架中分页处理的问题(主要是设计方面)

浏览 13900 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-06-09  
恩。现在我们这个系统采用的是facade->bo(mgr)->dao->db
这么过来的,o/r mapping 采用的是hibernate
分页是后台分页,前台写了一个taglib。

问题:
因为分页的代码在后台基本上是一样的,唯一的区别是class参数不同(hibernate list 函数的参数)
所以我想如果每个流程都按
facade->bo->dao
上添加翻页的功能,觉得代码重用上做的非常不好,
但如果给facade,bo,dao每一层都添加接口(然后使用骨架类)然后各层都继承各自的骨架类,并层层的把查询条件和分页条件传递下来,我觉得也是比较累赘。(代码可以写自动生成器,主要是结构看起来不太舒服)

其实很简单的方法就是在taglib中直接调用DAO,(就分页这一块这么做)
通用的taglib+通用的分页代码,和功能模块,这样实现起来是最简单的。
不过这样就跳过了统一的facade接口,又违反了分层体系的原则,也不是我所愿意见到的。。。

我无法作出比较好的权衡判断(请大家给我一些意见)
ps:我的技术总监倾向于结构清晰>代码量减轻。
   发表时间:2004-06-09  
补充一点
dlee提出的xmlhttp方法这次因为没有人会,所以不会使用,等项目完了,我自己去研究一下,很有兴趣。
0 请登录后投票
   发表时间:2004-06-09  
我在项目中的做法是
做个pageCtrl class,封装所有分页操作. 使得对于 WEB层的人员来说,不需要知道分批次取数据的逻辑,就好象一次性取得了所有结果.


定义pageCtrl同时,定义符合分页操作的 Dao Interface. Dao Interface的实例作为PageCtrl的构造参数.  
Dao和pageCtrl实例的Facade层生成组装.

web taglib只负责纯显示职责.

目前使用下来,达到效果.
0 请登录后投票
   发表时间:2004-06-09  
那你的分页是直接调用dao
虽然我也觉得最这么调用最直接,也最方便,不过因为已有的系统统一使用facade接口,如果跳过这一接口,直接使用dao,是不是会打乱系统的统一性?
0 请登录后投票
   发表时间:2004-06-09  
DAO已经隐含在pageCtrl中了,对于DAO的操作,是由pageCtrl调用的.
我认为在实际使用也是符合分层原则的.
facade重要性的是对外提供简单接口, 而不是要求每调用一次数据库操作,都必须->facade->X->dao.

如果WEB层的开发人员,需要知道 上一页,下一页,是怎么样调用Facade层的话,那么才是 facade层的失败.

目前项目中的设计主要由以下几个部分
pageCtrl  知道所有分页操作逻辑
InfPgDao 分页数据取得的操作接口
facade     知道业务逻辑, 哪个查询对应哪个DAO实现,facade 起到的业务逻辑的组织作用.
Dao         具体数据库查询逻辑的实现
web        1.新的查询 和 facade交互,取得pagectrl实例. session中保存.<--体现了业务逻辑
               2.分页操作, 只需要操做session中的pageCtrl实例.<--显示性操作,与业务逻辑无关.

这样做的目标是, WEB开发人员不需要了解分页的实现细节. 只需要调用 上一页,下一页, 设置当前页 ,取得当前页数据的显示逻辑即可.

其实我最初也是有"破坏分层"的担心, 但随着逐步的实现,觉得这样还是符合分层的.
0 请登录后投票
   发表时间:2004-06-09  
tuti 写道
DAO已经隐含在pageCtrl中了,对于DAO的操作,是由pageCtrl调用的.
我认为在实际使用也是符合分层原则的.
facade重要性的是对外提供简单接口, 而不是要求每调用一次数据库操作,都必须->facade->X->dao.

如果WEB层的开发人员,需要知道 上一页,下一页,是怎么样调用Facade层的话,那么才是 facade层的失败.

目前项目中的设计主要由以下几个部分
pageCtrl  知道所有分页操作逻辑
InfPgDao 分页数据取得的操作接口
facade     知道业务逻辑, 哪个查询对应哪个DAO实现,facade 起到的业务逻辑的组织作用.
Dao         具体数据库查询逻辑的实现
web        1.新的查询 和 facade交互,取得pagectrl实例. session中保存.<--体现了业务逻辑
               2.分页操作, 只需要操做session中的pageCtrl实例.<--显示性操作,与业务逻辑无关.

这样做的目标是, WEB开发人员不需要了解分页的实现细节. 只需要调用 上一页,下一页, 设置当前页 ,取得当前页数据的显示逻辑即可.

其实我最初也是有"破坏分层"的担心, 但随着逐步的实现,觉得这样还是符合分层的.


请问三个问题:
1:list算不算业务逻辑?如果算,应该不应该写在bo里面。
2:你所提到的web开发人员只专门的界面开发吗?包括不包括taglib的开发人员?
3:你的方法中是不是tablig调用你封装好的pageCtrl,
web的开发人员只需在调用taglib向里面传递参数的时候设置dao的类名就可以了。如果是的话,那我使用facade的话,在taglib中调用facade,web开发人员只需要在调用taglib传递想要翻页的vo名就可以了。
这个和你那个有什么区别?而且,我觉得对web开发人员暴露vo的名字比暴露dao名字好的多。

而且我们这个系统有个问题,权限验证都是在facade做的,都有统一的接口,如果直接使用dao的话,会跳过这一机制。
我刚才和师父讨论了一下,觉得还是采用通过facade调用比较好了。。。


恩,针对你的话,我还向提出一个问题,就是,采用这种facade-》bo-》dao的多层体系,是不是所有的前台调用都要这么一层一层的过来,
比如统计这种调用也这么过来吗?

是不是只和显示有关的调用可以扩过bo这一层,直接和dao打交道,比如list,statistic。
0 请登录后投票
   发表时间:2004-06-09  
to tuti:
     我觉得其实没有必要那么复杂。
    我的想法是做一个list/iterator的decorator,将查询出来的页面数据包装一下,然后自己写个taglib显示就行了。
0 请登录后投票
   发表时间:2004-06-09  
引用
1:list算不算业务逻辑?如果算,应该不应该写在bo里面

如果这里的list是指 查询或者统计的话,算是业务逻辑,这类操作常常会包含权限控制,应该写在业务逻辑实现层。

引用
2:你所提到的web开发人员只专门的界面开发吗?包括不包括taglib的开发人员?

我们这个项目使用struts,这里的web开发人员是指负责写formbean,action等逻辑的开发人员,也可以算包括taglib的开发人员。

引用
3:你的方法中是不是tablig调用你封装好的pageCtrl

是在action里调用,taglib只是起显示一些状态,如共几页,现在第几页等。

引用
权限验证都是在facade做的,都有统一的接口

即便是查询,也往往是有权限要求的,这也是业务逻辑。在这里我做了一点简化,即 按“查询”按钮的时候,由facade进行权限检查,判断是否返回pageCtrl实例。而在 翻页操作时,认为只是对结果集合的显示操作,而不进行权限判断。翻页操作时,就好象一次取得10000条记录,放在session里,每页只显示10条的逻辑一样。
0 请登录后投票
   发表时间:2004-06-10  
这个分页问题的封装过程,我是这样来理解的。
首先, 可以设想在facade层一个 一次性返回全部数据Collection的业务接口,这个接口包括权限逻辑检查。

其次, 设想对一次性返回的全部数据,在WEB层session里保存,表现上进行分页显示。所有的分页显示逻辑可以用pageCtrl来封装。

最后,表现层的每一页数据,都是分页取得。这样facade层的接口 从返回Collection 变为了返回pageCtrl。这样对于数据是一次性取得,还是分页取得的逻辑就包含在pageCtrl之中了,对外不可见。

而action的调用程序与step2相比要基本不变。也就是说,aciton里的逻辑,不知道分页数据是一次性返回,还是分页取得,只知道,根据输入条件取得返回结果,上一页,下一页,指定页。

至于“taglib向里面传递参数”等封装方式,目标都是在不破坏分层结构的前提下,尽量使调用者使用方便。多传一个参数,都多增加一份耦合度。设计效果要看client端程序是如何来调用封装出的接口。
0 请登录后投票
   发表时间:2004-06-10  
下面是我所想的分页实现,PaginateList是一个附带了分页信息的List。

对于客户端程序员而言,只需要知道service中的findByXXXX接口,tag的调用也很简单,只需要传递返回的List在pageContext中的名字即可,其他的上页,下页,共几页之类的由tag来解决。

我觉得不爽的是,需要额外进行一次查询来觉得记录总数,虽然对于客户端程序员而言是不可见的。

    public List findByXXXX(String query, Object[] values, int start, int rows); {
		// TODO get the count

		// get the result list
		List result = ............... //取得分页的数据
		
		return new PaginateList(resultList, start, rows, recordsCount);;
	}

  public PagintateList implements List{
  	private List resultList;
  	private int recordsCount;
  	private int rows;
  	private int start;
    
    public PaginateList(List resultList, int start, int rows, int recordsCount);{
      this.resultList = resultList;
      this.start = start;
      this.rows = rows;
      this.recordsCount = recordsCount;
    }
    ...............
  }
 
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics