【发布时间】:2014-07-03 18:27:48
【问题描述】:
我有一个主要提供 JSON API 的服务器。目前我们有@Controllers,可以直接将REST端点委托给@Service类中的方法。
这导致了很多不必要的样板代码。如果我只是用 @Controller 和 @RequestMapping 注释来注释我的 @Service 类,我可能会遇到问题(例如,搞砸事务调用?服务之间的依赖关系问题?)
【问题讨论】:
标签: spring spring-mvc
我有一个主要提供 JSON API 的服务器。目前我们有@Controllers,可以直接将REST端点委托给@Service类中的方法。
这导致了很多不必要的样板代码。如果我只是用 @Controller 和 @RequestMapping 注释来注释我的 @Service 类,我可能会遇到问题(例如,搞砸事务调用?服务之间的依赖关系问题?)
【问题讨论】:
标签: spring spring-mvc
如果您在同一个 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,它应该可以正常工作,我不建议这样做。
【讨论】:
@Component 特化注解类型本身并不会创建两个 bean。
MVC 模式的存在是有充分理由的,让每一层都各司其职,并且它们之间的耦合度很低。每个刻板印象也都有存在的理由。
您在谈论什么样的样板代码? @Controller 和 @RequestMapping 很简单。
【讨论】:
如果我只是注释我的
@Service,我可能会遇到问题吗? 带有@Controller和@RequestMapping注释的类
如果类型使用@Service 进行注释,则不需要使用@Controller 进行注释。只需确保 type 具有 @RequestMapping 注释即可。处理映射控制器处理程序方法的RequestMappingHandlerMapping 在类型级别检查@Controller 和@RequestMapping 注释。你也需要。
除此之外,这只是设计和关注点分离的问题。在技术 Spring 级别上,您不会有任何其他问题。
(请注意,您必须通过DispatcherServlet 的WebApplicationContext 加载bean,以便RequestMappingHandlerMapping 将其拾取。)
【讨论】:
@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);
}
}
【讨论】: