mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面。

mvc模式是web开发中的基础模式,采用的是分层设计,各层之间职责分明。然而事与愿违,当我们日积月累的基于mvc模式开发之后,会逐渐的感受到层与层之间存在粘连和职责模棱两可的地方,这就是service层出现的重要原因。

问题是什么

要提出解决方案,重要的是发现问题的本质。mvc模式在实践过程中,主要面临下面几个难受的问题:

  • 在C层直接实现业务逻辑,这将导致:

    • 不同的controller之间,无法共享通用的业务逻辑,比如:折扣计算,反作弊判定,这必然是不合理的。
    • 业务逻辑升级,需直接在原代码上做修改兼容,导致controller代码不断膨胀复杂。
    • 远程服务协议或者调用方式升级,需要找到所有controller里的调用点,逐一修改。
    • DAO发生替换(比如从oracle迁移mysql),需要找到所有controller里的调用点,逐一修改。
  • 在M层(DAO+model或者ActiveRecord,下面以model泛指)里实现业务逻辑,这将导致:
    • model承担了过多的业务逻辑,导致业务逻辑升级需要修改model,然而model的职责并不是业务,这是很矛盾的。
    • 调用1个model中的业务代码没有问题,但是遇到跨表事务又该由哪个model管理呢?
    • 业务逻辑实现在model中,如果model发生变更,那么里面写的业务逻辑也得粘贴复制到新的model中,这就是耦合的代价。

我仔细的回想了一下之前的MVC开发模式,上面的问题我几乎都遇到过并且试图解决过,比如:

  • 为了提升代码复用,我会把一些通用的功能实现为单独的工具类(校验登录),并在controller中提供调用。
  • 为了给controller提供业务相关的数据,我在ActiveRecord里实现了业务相关的增删改查方法供controller调用,更有意思的是:每次表变更字段,我通过工具gii重新生成ActiveRecord都会把我实现的方法覆盖,这就是耦合的代价。

问题的本质是:业务逻辑粘连了C层和M层,应该从C层&M层解耦出来,成为独立的Service层。由此,在C层可以灵活的替换Service保持高度的简洁,而M层保持职责单一仅仅为Service提供数据,Service层则实现所有复杂的业务逻辑与通用的业务逻辑。

Service层的职责

根据上面的分析,Service夹在C层和M层中间,从逻辑上大致划分为3大类:

  1. model侧的Service:也就是封装每个model与业务相关的通用数据接口比如:查询订单。(我认为:访问远程服务获取数据也应该归属于这一类Service)
  2. 中间的Service:封装通用的业务逻辑,比如:计算订单折扣(会用到1中的Service)。
  3. controller侧的Service:基于1、2中的Service进一步封装对外接口的用户业务逻辑,当然也不排斥直接访问DAO而不使用上述2个Service(不建议)。

在实践中,应该会很自然的用到这三类Service,在了解了这些概念之后再进行代码设计,就不会对Service的职责产生困惑了,自然也对MVC有了新的认识。

关于抽象

Controller里调用"controller侧的Service"直接完成业务处理,意味着Controller依赖了具体是哪个Service类。

Service里调用"DAO/AR"实现数据库的访问,意味着Service依赖了具体是拿个"DAO/AR"类。

Service里调用Service,意味着Service依赖了具体是拿个Service类。

为了解除这种耦合,在Web领域一般采用的都是IOC依赖注入来实现"依赖反转",JAVA和PHP都可以基于反射实现这个能力,各个mvc框架都有相似的实现。

Service层是否必要呢?

见仁见智,我认为长时间维护的大型项目通过更精细的分层,更加有利于功能的迭代升级。

而对于中小项目,多一层就意味着更多的代码,而且在设计时还要考虑通用性以及通用性的粒度问题,还不如少动点脑子多写点冗余代码了。

更多博客请直接访问鱼儿的博客

谈谈service层在mvc框架中的意义和职责的更多相关文章

  1. Java Web学习总结(30)——Service层在MVC框架中的意义和职责

    mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层设计, ...

  2. Service层在MVC框架中的意义和职责

    https://blog.csdn.net/u012562943/article/details/53462157 mvc框架由model,view,controller组成,执行流程一般是:在con ...

  3. [原]命令模式在MVC框架中的应用

    其实在项目开发中,我们使用了大量的设计模式,只是这些设计模式都封装在框架中了,如果你想要不仅仅局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之一就是命令模式,先来看看模式是如何 ...

  4. 命令模式在MVC框架中的应用

    事实上在项目开发中,我们使用了大量的设计模式,不过这些设计模式都封装在框架中了,假设你想要不只局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之中的一个就是命令模式,先来看看模式 ...

  5. 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用Filter实现(Struts2采用这种方式),也可以使用Servlet来实现(spring MVC框架)。

    本文转自http://www.cnblogs.com/davidwang456/p/4090058.html 感谢作者 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并 ...

  6. 找到MVC框架中前端URL与后端同步的解决方案

    基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...

  7. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析

    下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...

  8. 在ASP.NET MVC 框架中调用 html文件及解析get请求中的参数值

    在ASP.NET MVC 框架中调用 html文件: public ActionResult Index() { using (StreamReader sr = new StreamReader(P ...

  9. MVC框架中的值提供机制(三)

    在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然 ...

随机推荐

  1. 第二天ci项目规划 数据库设计

    第二天ci项目规划 数据库设计 商品 + 用户 + 订单 数据库设计思想和方法 关于商品品牌 ,分类 ,属性 如何表示 用一个字段 还是再设计一张表 品牌和商品 是一种信息 还是两种信息 一张表一般只 ...

  2. Unity3D 脚本编译器无法关联VisualStudio2012解决办法

    开发环境:Win8 + Unity 4.34f1 +Visual Studio2012 旗舰版 解决办法:   1.创建一个start.bat文件,内容为:[start "" %* ...

  3. storm学习好文链接

    大圆的那些事:http://www.cnblogs.com/panfeng412/tag/Storm/ xcc的博客:http://blog.csdn.net/damacheng/article/ca ...

  4. java 的各种实用类库(jar包)

    总列表:# dom4j # org.json # pinyin4j # sqlite-jdbc # JavaMail # JLayer # dom4j 介绍:处理 xml 的类库.采用了 Java 集 ...

  5. eclipse常见问题

    使用eclipse进入断点,当弹出"Confir Perspective Switch"视图时,选择"Yes".之后每次进入断点都会自动切换到debug视图. ...

  6. web常见错误提示总结

    在写web程序的时候,经常会出现一些网页错误的数字提示,如果能够明白这些提示的含义,那对于调试程序是有极大帮助的.网上有很多这方面的总结,但为了适应自己的阅读习惯,以及日后的查找方便,就做了一些修改并 ...

  7. Debian 8 jessie, OpenSSH ssh connection server responded Algorithm negotiation failed

    安装了debian 8.5 就出问题了. root@debian8:~# lsb_release -aNo LSB modules are available.Distributor ID: Debi ...

  8. HUD--递增数

    递增数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  9. JDBC的连接和增删改和查找

    package Test2;import java.sql.*;import java.sql.DriverManager;import java.sql.SQLException;public cl ...

  10. android——数据库版本升/降级问题

    数据库版本升级 在开发android应用程序的时候,一般由于在我们开发的时候我们不知道以后会后什么新功能,也有可能增加业务逻辑(也就是更新),可想而知我们原来的数据库结构可能不适用已更新的应用,那么应 ...