什么属于Controller层,什么属于Service层?

Posted

技术标签:

【中文标题】什么属于Controller层,什么属于Service层?【英文标题】:What belongs to the Controller-layer, what to the Service-layer? 【发布时间】:2017-08-13 02:51:29 【问题描述】:

我有一个简单的 Spring-Boot Restful 应用程序。我有一个控制器层和一个存储库层,但没有服务层。让我向您展示我的控制器方法之一:

@RequestMapping(value = "users/id", method = RequestMethod.GET)
public Resource<UserResource> get(@PathVariable Long id) throws NotFoundException 
    log.info("Invoked method: get with ID: " + id);
    log.warn("Searching for user with ID " + id);
    User user = userRepository.findOne(id);
    if (user == null)
        log.error("Unexpected error, User with ID " + id + " not found");
        throw new NotFoundException("User with ID " + id + " not found");
    
    log.info("User found. Sending request back. ID of user is " + id);
    return new Resource<UserResource>(getUserResource(user));

由于我没有服务层,我的控制器为我执行业务逻辑。现在我想实现服务层。我的控制器应该/不应该做什么?

我的服务层(我现在要实现的)是否应该完成所有工作而我的控制器只将请求委托给服务层?

【问题讨论】:

不久前,我在一家大型汽车制造商的一个大项目中工作。我们有控制器层、服务层和 DAO 层(数据访问对象 - 用于查询数据库)。逻辑是:控制器接收请求,服务执行操作并在必要时调用 DAO,然后将结果返回给控制器。 DAO 访问数据库并执行查询。控制器层必须非常轻巧,控制器只需委托给服务并加载视图。 DAO 执行查询,而服务使用来自控制器的数据完成所有剩余的工作。 在这个简单的例子中,如果你需要一些业务逻辑,你只需要User user = userService.findOne(id);,你应该像你说的那样实现服务...... 好的。这意味着控制器应该什么都不做,只接收请求并将其发回。谢谢你们两个:) 【参考方案1】:

服务类

public class UserService 
     public User findUser(String id)
          log.info("Invoked method: get with ID: " + id);
          log.warn("Searching for user with ID " + id);
          User user = userRepository.findOne(id);
          if (user == null)
            log.error("Unexpected error, User with ID " + id + " not found");
            throw new NotFoundException("User with ID " + id + " not found");
          
         log.info("User found. Sending request back. ID of user is " + id);
         return user;
     

API 类

    @RequestMapping(value = "users/id", method = RequestMethod.GET)
    public Resource<UserResource> get(@PathVariable Long id) throws    NotFoundException 
          return new Resource<UserResource>(userService.findUser(id));
    

添加通用异常处理程序 NotFoundException 以重定向到正确的错误页面。

【讨论】:

我不同意服务层设置if(user == null) ... ,因为有时您需要接收用户空值(我不知道整个上下文),您应该在控制器中进行此控制层。【参考方案2】:

问问自己:如果我想为不同的视图/传输/协议呈现结果,需要改变什么?这属于控制器。

Controller 层中的代码应仅与将 Service 层之间的业务输入/输出映射到视图/传输/协议(视情况而定)有关。这可能(也可能不)包括将业务数据映射到 JSON(您的业务/服务层直接使用 JSON 或类似文件并非不合理)、XML、html 或任何您的内容类型(对于 HTTP)。

虽然您的控制器可能感觉很轻巧,但请记住 Spring 对控制器的支持完成了大部分工作 - 将这样一个“简单”控制器视为您的框架识别并挂起所有较重的、锅炉的锚点 -板,代码关闭,对您有利。

【讨论】:

【参考方案3】:
 public class UserService

     public User findUser(String id)
          log.info("Invoked method: get with ID: " + id);
          log.warn("Searching for user with ID " + id);
          User user = userRepository.findOne(id); 
          log.info("User found. Sending request back. ID of user is " + id);
          return user;
      
    




@RequestMapping(value = "users/id", method = RequestMethod.GET)
public Resource<UserResource> get(@PathVariable Long id) throws NotFoundException 
      User user = userService.findUser(id)
      if (user == null)
           log.error("Unexpected error, User with ID " + id + " not found");
           throw new NotFoundException("User with ID " + id + " not found");
      
      return new Resource<UserResource>(getUserResource(user));
 

基于@Jai 响应,唯一的区别是 if,因为有时您需要接收用户 null

public void anotherMethod(@PathVariable Long id)
    User user = userService.findOne(id);
    if(user == null) 
        //in this case I don't want to throw NotFoundException and make some other logic like create the user for example.
    

【讨论】:

以上是关于什么属于Controller层,什么属于Service层?的主要内容,如果未能解决你的问题,请参考以下文章

为什么将@Transactional与@Service一起使用而不是@Controller

三层架构是啥?

spring属于哪个层次?主要解决啥问题?

springboot中怎么集成Swagger,让你拥有属于自己的api管理器

springboot中怎么集成Swagger,让你拥有属于自己的api管理器

springboot中怎么集成Swagger,让你拥有属于自己的api管理器