什么属于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
springboot中怎么集成Swagger,让你拥有属于自己的api管理器