关于JFinal的service层必要性问题

zeroGray 发布于 2015/11/09 14:36
阅读 3K+
收藏 2

@JFinal 你好,想跟你请教个问题:

我使用JFinal已经将近半年,在之前公司使用它,做了两个项目,慢慢的深入源码,渐渐的体会到了JFinal的精髓和所要表达的思想。

目前到新公司(之前公司就是我强烈建议使用JFinal的)我依旧推行使用JFinal,但是同事提出需要添加service层来管理业务逻辑,否则无论逻辑放在controller里面,还是放到Model里面,都会显得代码层次混乱。

我在论坛和百度上都搜过了,没有太多的关于这个问题的答案。

求大神解答,有这个必要性吗?

加载中
3
JFinal
JFinal

     JFinal 开发提倡使用业务层,Model 中只提供一些简单的与字段有关的逻辑,例如:假定有张表叫 account,对应的 model 为 Account 类,里面有一个 int status 字段,值分别有-1、0、1、分别表示:已锁定、已注册、已激活,Account 类有关这个字段的逻辑代码大致如下:

public class Account extends Model<Account> {
 // 锁定账号
 public static final int STATUS_LOCK_ID = -1;
 // 注册、未激活
 public static final int STATUS_REG = 0;
 // 正常、已激活
 public static final int STATUS_OK = 1;	

 public boolean isStatusOk() {
  return getInt("status") == STATUS_OK;
 }

 public boolean isStatusReg() {
  return getInt("status") == STATUS_REG;
 }

 public boolean isStatusLockId() {
  return getInt("status") == STATUS_LOCK_ID;
 }
}

   类似的,还可以添加其它一些与某个model对象状态有关的逻辑方法,账户要做某事时,先检测账户是否已激活,可以是这种方式:

public class AccountService {
 // 用户创建 topic
 public Ret createTopic(Integer accountId, Topic topic) {
   Account account = Account.dao.findById(accountId);
   if (accout.isStatusLockId())
     return Ret.create("msg", "账户已被锁定");
   if (account.isStatusReg())
     return Ret.create("msg", "账户未激活");
   topic.set("accountId", accountId);
   return Ret.create("isOk", topic.save());
 }
}

     以上代码使用了 AccountService 业务层,在保存 topic 之前先对当前用户的账户进行状态判断,然后将业务执行的结果保存在 Ret 对象之中(jfinal 2.0提供了Ret类支持),在业务层使用Aop详见jfinal 手册:http://www.jfinal.com。当然以上仅是示例,对用户状态的判断通常放在拦截器中能极大缩减整体项目的代码量。

      JFinal 使用业务层非常重要的一点,JFinal 业务层依然提倡极度轻量极,不需要接口,不需要XML,不需要 IOC 容器去装配与注入。只有在切实需要抽象与多态才去使用接口或抽象类,不要再回到SSH时代过度、无休止的 XML、IOC、interface、implements 对抽象的误用之中。

     最后 ActiveRecord 模式核心在于一个 Model 对象利用 ID 唯一对应一张数据表的一条记录,所以 Model 中的逻辑操作方法只适合放一些对数据表中字段简单的逻辑判断或操作,复杂业务逻辑放在独立的 Service 层之中,适用于大型项目,业务可以不断拆分(Model不方便拆分),代码结构更清晰,方便代码重用,可维护性更好,model 中代码更加清爽,也更方便跨 model 的业务操作。

0
酷酷的就
酷酷的就
我觉得有必要的,但不是所有controller和model都需要的, 只是在有公用方法的地方可以适当提取成service来方便业务的统一维护.
小徐同学
小徐同学
感受到了,谢谢波总!
z
zeroGray
回复 @zp-wmhx : 恩恩,为了规范统一,这个也是必要的冗余,呵呵 至少已经少了很多interface,更少了很多xml,我已经很满足了,哈哈哈
酷酷的就
酷酷的就
回复 @zeroGray : 如果你觉得奇怪那么就统一吧, 那么很多service还不是一样多余?
z
zeroGray
那你这个.....同一个controller中某些方法调用的service,某些方法又直接调用的model.dao.XXX()这不是很奇怪么?
0
z
zeroGray

@JFinal 恩恩,我知道了,看来层出业务层还是有必要的,但是接口可以因地制宜。

确实我之前用SSH最烦躁的就是两点:

1.无穷无尽的正括号+反括号+莫名其妙的标签<>(xml)
2.各个层(service,dao)的interface,有很多interfac其实绝对算得上是冗余代码,因为它几乎永远都不会有其他impl。

果断还是作者大神的回复能够在快捷与分层清晰中,两者兼顾~学习了!

谢谢大神解答


0
JFinal
JFinal

引用来自“zeroGray”的评论

@JFinal 恩恩,我知道了,看来层出业务层还是有必要的,但是接口可以因地制宜。

确实我之前用SSH最烦躁的就是两点:

1.无穷无尽的正括号+反括号+莫名其妙的标签<>(xml)
2.各个层(service,dao)的interface,有很多interfac其实绝对算得上是冗余代码,因为它几乎永远都不会有其他impl。

果断还是作者大神的回复能够在快捷与分层清晰中,两者兼顾~学习了!

谢谢大神解答


     SSH 时代漫山遍野都是 interface、impl、XML、annotation,通常为了实现 AOP,早期的 AOP 实现需要利用 JDK 的动态代理 API,该 API 需要有接口才可以代理,另外一个原因是为了在未来切换业务层实现impl,正如楼主所说,所谓未来可能切换 impl 很可能是“永远都不曾发生”。

    传统AOP实现需要引入大量繁杂而多余的概念,例如:Aspect、Advice、Joinpoint、Poincut、Introduction、Weaving、Around等等,并且需要引入IOC容器并配合大量的XML或者annotation来进行组件装配。

    JFinal采用极速化的AOP设计,专注AOP最核心的目标,将概念减少到极致,仅有三个概念:Interceptor、Before、Clear,并且无需引入IOC也无需使用繁杂的XML。只需 Duang.duang(target) 即可实现极速 AOP 开发,详情见:http://www.oschina.net/news/63481/jfinal-2-0

  
JFinal
JFinal
回复 @zeroGray : 感谢你对 jfinal 的支持,jfinal 会越做越好,继续为广大开发者谋福利 ^_^
z
zeroGray
希望JFinal能一直牛b下去,并且推广力度稍微要努力了,哈哈,我现在带的项目成员一说我要用国产框架,而且是他们都没听过的JFinal,就各种反对的声音... 我一定会不畏艰难险阻,继续把JFinal推行下去的(上家公司虽然我已离职,可剩下的人员依然觉得好用,依旧在用) :)
z
zeroGray
哈哈哈,确实是好,能得到作者亲自回答,不胜荣幸啊,哈哈
返回顶部
顶部