【问题标题】:Can use @Service objects as @Controllers?可以将@Service 对象用作@Controllers 吗?
【发布时间】:2014-07-03 18:27:48
【问题描述】:

我有一个主要提供 JSON API 的服务器。目前我们有@Controllers,可以直接将REST端点委托给@Service类中的方法。

这导致了很多不必要的样板代码。如果我只是用 @Controller 和 @RequestMapping 注释来注释我的 @Service 类,我可能会遇到问题(例如,搞砸事务调用?服务之间的依赖关系问题?)

【问题讨论】:

    标签: spring spring-mvc


    【解决方案1】:

    如果您在同一个 bean 上同时使用 @Service@Controller,那么您很有可能会为一个类创建两个 bean,这通常不是您想要的。

    发生这种情况是因为@Controller 通常加载到子上下文(调度程序 servlet)中。

    如果你所有的 bean 都加载到调度器 servlet 上下文中,你会没事的。

    编辑:我在 iPhone 上回答了这个问题,所以我无法详细说明。

    我说很有可能这将是一个问题,因为它实际上与您使用的注释类型无关,而是组件扫描以及组件扫描如何分配给应用程序上下文。

    大多数人所做的是扫描带有@Service 的组件,以由根WebApplicationContext 加载,这可以与调度程序servlet 上下文相同,但通常不是。

    让我举个例子:

    通常您会看到一个 applicationContext.xml,其中包含以下内容:

    <context:component-scan base-package="com.blah">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
    

    随后是调度 servlet 上下文 XML,其内容如下:

    <context:component-scan base-package="com.blah" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
    

    注意第一个如何排除 @Controller 而第二个明确包含。

    也就是说,如果您只有一个 WebApplicationContext 并且它与调度程序 servlet 共享,那么您可以使用 @RequestMapping 注释 @Service,它应该可以正常工作,我不建议这样做。

    【讨论】:

    • 我怎么知道 spring 是否创建了 2 个重复的 bean?我什么时候可以看到他们?
    • 用 2 个 @Component 特化注解类型本身并不会创建两个 bean。
    • 这实际上与他使用的注释类型无关,而是组件扫描以及组件扫描如何分配给应用程序上下文。
    • 有用的解释@AdamGent
    【解决方案2】:

    MVC 模式的存在是有充分理由的,让每一层都各司其职,并且它们之间的耦合度很低。每个刻板印象也都有存在的理由。

    您在谈论什么样的样板代码? @Controller 和 @RequestMapping 很简单。

    【讨论】:

    • 假设我有 10 个服务类,每个服务类有 10 个方法要向 REST API 公开。我不需要实现每个服务类并注释方法以导出为 REST API,而是需要创建额外的 10 个控制器类,每个控制器类有 10 个方法,每个方法的主体只是返回 service.method(param1,param2)。我现在有两块代码需要保持同步——其中一个的任何更改都需要另一个的更改(=高耦合)。如果 service=controller,控制器的依赖仍然与服务的实现和非@RequestMapping 方法解耦。
    • 关键是您可以在不更改 REST 层的情况下更改服务层,您可以在服务层中处理一些默认情况。您的建议基本上是为了不便而放弃一个好的架构(将您的应用程序的核心与外部使用分开)。此外,当您需要更改您的服务层时,这在您更改应用程序的核心时应该很困难。
    【解决方案3】:

    如果我只是注释我的@Service,我可能会遇到问题吗? 带有@Controller@RequestMapping 注释的类

    如果类型使用@Service 进行注释,则不需要使用@Controller 进行注释。只需确保 type 具有 @RequestMapping 注释即可。处理映射控制器处理程序方法的RequestMappingHandlerMapping 在类型级别检查@Controller@RequestMapping 注释。你也需要。

    除此之外,这只是设计和关注点分离的问题。在技​​术 Spring 级别上,您不会有任何其他问题。

    (请注意,您必须通过DispatcherServletWebApplicationContext 加载bean,以便RequestMappingHandlerMapping 将其拾取。)

    【讨论】:

      【解决方案4】:

      @Controllers 将入口和终点委托给一个请求/响应。

      @Service 是为那些@Controllers 提供逻辑,@Controllers 必须不知道的逻辑。

      在@Controllers 中你必须@Autowired 你的@Services 依赖。在您的 @Services 中,您的其他逻辑依赖项(如 DAO 等)...

      一个典型的 Rest @Controller 可能如下所示:

      @Controller
      public class UserWSController {
      
          @Autowired
          private UserService userService;
      
          @RequestMapping(value = "/{userId}")
          @ResponseBody
          public User getUserPublicInfo(@PathVariable int userId) {
      
              return this.userService.getUserById(userId);
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-06-07
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-04
        相关资源
        最近更新 更多