本文讨论的内容仅针对小型项目或个人独立开发的项目,对于大型及团队合作的项目恐怕不适合。
因接触到的项目多数都是内部使用,而且所有项目几乎都是单兵作战(从最初的项目需求分析到最终的上线验收),所以也形成了自己的一个模式。
看过JFinal-demo代码的朋友都知道,注释一栏中非常醒目的提示SQL语句的存放规则,建议都在Service中进行管理,或者放到SQL的模板中。
在实际的开发过程中发现(并非只在JFinal的环境),Model+Service+Controller的模式,可以缩略为Model+Controller,本人把Service直接融入到Model中。在使用JFinal时,也并没采用其ActiveRecord中的Model,而是完全采用其Db+Record的模式(个人认为灵活性更强)。
或许会有疑问,为什么把Service融入到Model中,恐怕不太符合规范,接下来就解释一下原因(基于一个房地产项目)。
首先,我们会遇到这样一种情况,比如某个地产项目,大体结构包括了项目、预销售许可证、楼栋、房屋,依次都是1:N的关系。那么在加载项目时会有一个已获批许可证数量的属性,以及楼栋中会有一个房屋数量的属性,并且房屋中有部分属性是通过其它的数据表中进行计算后得到的。相当于在加载某个对象时仅通过一个SELCET从对应的数据表中去取数据是满足不了的,必要时需要使用多条SELECT从若干个其它数据表中去取值并计算后才可得到结果。
针对上面的问题,我的解决思路是在Model时就一次性把需要的属性加载完成,示例代码如下
public Project{ private int PJID; private String PJName; private int PJType; //项目类型(这里采用数据字典形式) private String PJLocation; private int CertCount; //获批许可证数量 private int HouseCount; //当前项目下所有获批的房屋总数 //这里是其它类似的需要通过计算其它数据表才能得出的属性 //因为多数情况下不能改动数据库的任何参数,所以增加自定义函数或存储过程的方法行不通。 public Project(){} public Project(int id){ Record rs = Db.findFirst("SELECT * FROM Project WHERE ID="+id); if(rs!=null){ this.PJID = rs.getInt("PJID"); this.PJName = rs.getStr("PJName"); this.PJLocation = rs.getStr("PJLocation"); } rs = Db.findFirst("SELECT COUNT(*) AS HouseCount FROM House WHERE PJID="+id); if(rs!=null){ this.HouseCount = rs.getInt("HouseCount"); } } public Page getPageList(){ //这里是用于分页的方法 } public List<> getList(Project project){ //这里是根据实际需求单独的List } //这里是geter和seter方法,但有一个比较特殊的地方,因为数据字典相对比较固定,字典的对应信息以XML形式存储, //这样可以避免频繁的数据库读取,同时又支持热编辑。 public getPJType(){ return this.PJType; } public getPJTypeName(){ return ComKits("PJTYPE", this.PJType).getValue(); //这里是通过一个自定义的方法把数据字典对应的文字描述加载出来,比如数据库中PJType的值为1,这里按字典值就可以显示为“纯住宅”类似的值。 //在View时只要通过如${project.PJTypeName}这样的形式即可显示到页面。 } }
以上代码都归在了Model中,这样在Controller中调用,效果与Service其实并没什么太大的区别。好处是,Model中任何属性都可完全掌控自如,缺点是自己动手写的代码量会大幅增多。
因为实际开发中对JFinal自动生成的Model改动还是比较大的,故干脆就改用了上面这种模式,结合IDE工具的部分自动化代码,工作量差异并不大。说实话,形成了固有的模式,不论代码量是多是少,反倒是上手最快的。
本人搞编程算是半路出道,JFinal算是自学的最正规的一个框架,并已经运用到了实践中,原先除了一个Struts几乎不用什么框架,感觉框架就是累赘,很多时候都是被牵着鼻子走,而且如今的框架都是越来越庞大,开发阶段经常出现依赖包的异常排查。只在遇到JFinal后,才发现jar包的清爽真的不是一丁半点,至于本人上述的这种模式,是否合理,或存在哪些不足,还望各位看过后留下些自己的看法和指教。
首先添加一个业务层是顺手的事情,并没有多少工作量,因为 jfinal 的业务层在不需要抽象的时候,不建议创建接口抽象类之类的东东,十分轻量级
其次,业务层在添加之初你可能并没有感到什么好处,甚至会感到工作量反而增加,但是随着开发的推进,你会发现后续的开发工作可以不断调用以前开发好的业务层的 API 来组合式实现功能。从而大大减少工作量,提升开发效率
最后,数据结构是应用的底层核心,业务层是应用的上层核心,而应用其它的部分全都只是辅助作用,包括 model 也只是起一个承载数据的作用。所以当业务发生变化时,业务层的存在可以提升可维护性