最小化控制器责任

时间:2012-09-24 17:21:09

标签: java spring-mvc

理想情况下,Spring MVC应用程序中的控制器必须接收请求,将请求发送到API,将(调用的)结果加载到模型上(对于视图随后呈现它)并转发到视图。他们不应该再做了。

我的控制器的功能远不止今天,我希望将某些功能从控制器转移到其他API。我今天的应用程序设计(非常典型):

controller <-> Service API <-> DAO <-> DB

今天的控制器填补了Web应用程序需要的内容和Service API提供的内容之间的差异。 我想在控制器和服务API之间放置额外的层/层,以便在此delta处进行咀嚼。我的问题是这些层应该是什么层以及这些新层的责任应该是什么?

我目前的想法如下

controller <-> controller helper <-> Business API <-> Service API <-> DAO <-> DB

Controller helper(Web上下文感知 - 将依赖于Model,HttpServlet和其他Web上下文类):

  1. 将实体转换为DTO对象(双向)
  2. 将ID解析为实体。例如。控制器查找学生i.d. (使用密钥)并将其转换为学生实体。
  3. Business API(没有Web上下文依赖 - 可以通过JUnit测试):

    1. 充当门面。调用多个服务API来实现一个 业务请求。
    2. 提供专门用于网络应用的API。
    3. 你会以不同的方式解决这个问题吗?是否有与此特定问题相关的资源(书籍,文章等)?

      之前的一些的讨论回答了我的问题:

      Designing mvc controller layer

      Service layer = Application layer = GRASP Controller layer

      Moving Validation, Html Helpers to Service Layer in MVC

      谢谢, 维杰

2 个答案:

答案 0 :(得分:1)

服务包含应用程序的一般业务逻辑。它们几乎是控制器和DAO / DB之间的任何东西。

您的“业务层”和“控制器助手”只是更多服务。为了简单起见,我会保留经典设计:

Controllers <-> possible Services <-> possible DAOs <-> DB

如果我有很多服务(我通常不会)碰巧执行相同类型的逻辑,我自然会将它们分成子包。例如:

  • services.facade或services.business
  • 用于DTO的services.adapter(除非您使用简单的类来完成此工作)

外观服务由控制器调用,如:someFacade.someMethod(SomeDTO someDto)。然后外立面处理DTO&lt; - &gt;由于其他服务(或简单的类),实体转换。

这就是我在你的背景下会做的事情。在一个理想的世界(没有遗留系统,或从头开始的项目),我会直接使用实体作为表单对象(而不是DTO),我的大多数服务都是外观(其余的将是简单的类,如果可能的话) )。

答案 1 :(得分:0)

我是Spring MVC的新手,也面临着这种困境。虽然Spring对我来说很陌生,但我已经和MVC合作了好几年了。我同意控制器应该只接受请求,发送它们,并以正确的格式呈现结果。我认为服务不一定是帮助抽象存在的最佳位置。我相信一个服务应该封装一个特定的API而不再做任何事情。我觉得创造许多“类型”的服务使这种模式更加令人厌恶,并且不清楚责任落在何处。

我相信帮助者更适合作为服务的兄弟姐妹;它们应该用@Component而不是@Service来修饰。它们的作用是充当底层API的外观,这些API是在通过端点公开的模型上转换状态所需的。 Controller-&gt; Helper-&gt; [Services]模式促进了关注点的清晰分离,代码可重用性,并且是高度可测试的。这种模式的本质是防止控制器膨胀,因此你最终得到的超薄控制器除了调度请求和呈现响应之外什么都不做。