Java SpringDTO-DAO(资源-实体)映射到哪个应用层:控制器还是服务?
我正在编写一个Spring(4.1.7)web应用程序,它公开一个RESTful服务,并希望使用DTO“资源”对象在控制器和客户端浏览器之间进行通信,而不是公开我的持久性实体 目前,该应用程序具有以下层:Java SpringDTO-DAO(资源-实体)映射到哪个应用层:控制器还是服务?,java,spring,spring-mvc,architecture,spring-hateoas,Java,Spring,Spring Mvc,Architecture,Spring Hateoas,我正在编写一个Spring(4.1.7)web应用程序,它公开一个RESTful服务,并希望使用DTO“资源”对象在控制器和客户端浏览器之间进行通信,而不是公开我的持久性实体 目前,该应用程序具有以下层: 视图(JSP/JSON) 控制员 DAO(@Service) DAO(@Repository) 我的问题是,我应该在哪里将DAO实体映射到DTO资源?我看了一些使用springhateoas的示例,它们显示了Resource扩展ResourceSupport的对象在控制器中映射。这是最好的
- 视图(JSP/JSON)
- 控制员
- DAO(
)@Service
- DAO(
)@Repository
springhateoas
的示例,它们显示了Resource
扩展ResourceSupport
的对象在控制器中映射。这是最好的方法,还是应该从DAO服务返回资源
我希望将Link
元素添加到返回的资源中(对于自身和相关资源),但如果服务中处理Link
元素,而不了解控制器及其@RequestMapping
,则无法看到如何解析Link
元素。另一方面,我不知道用映射将控制器
弄得乱七八糟是否是一种好的做法。DTO(数据传输对象)在其名称中很明显,用于将数据传输出应用程序。在您的情况下,放置它们的最佳位置是控制器层。
您应该只向UI公开DTO,当您从UI获取数据时,您应该将其转换为业务实体并调用下面的层。
原因是,通过这种方式,您可以在不破坏UI的情况下自由地更改业务实体,从而实现更好的维护。同样,出于同样的原因,您的业务/DAO层应该不知道UI和DTO。
因此,在应用程序中,将DTO转换为业务实体(反之亦然)的最佳位置是控制器层
附言:也来看看;) 注意在我写这个答案时,我假设您所说的DTO是服务层的请求和响应对象。因此,我以这种方式使用术语DTO,并将术语资源对象用于“DTO”对象。我现在不想编辑整个答案。所以这个暗示
我应该在哪里将DAO实体映射到DTO资源
在服务层中。通常,服务层实现用例,是事务边界
例如
我希望将链接元素添加到返回的资源中(对于自身和相关资源),但如果在服务中处理链接元素,而不了解控制器及其@RequestMapping,则无法看到如何解析链接元素
你说得对。这些信息仅在控制器中可用。您可以添加资源模型,就像普通的ui模型一样
例如
然后在控制器中,您可以使用它并添加链接
@RequestMapping("/placeOrder")
public @ResponseBody OrderPlacedRessource placeOrderAction(HttpServletRequest request){
OrderService service = ...;
ShoppingCartTO cart = ...;
OrderPlacedTO orderPlacedTO = service.placeOrder(cart);
OrderPlacedRessource orderPlacedRes = new OrderPlacedModel();
orderPlacedRes.setOrderNumber(orderPlacedTO.getOrderNumber());
// since orderPlacedRes is a RessourceSupport we can add links
// Use the HttpServletRequest to build your links
Link link = new Link("http://localhost:8080/something");
orderPlacedRes.addLink(link);
return orderPlacedRes;
}
PS:如果使用org.springframework.hateoas.mvc.ControllerLinkBuilder
,构建链接会更容易。例如
orderPlacedRes.add(linkTo(methodOn(YourController.class).orderOverview(userId)).withSelfRel());
有关详细信息,请参阅。您可以使用不同的方法来调用映射。
请参阅本教程,例如:或问题:。这还取决于控制器中有多少逻辑。
我更喜欢在util类中映射EntityDTO。你可以相对自由地选择,从哪里称呼他们。看来,“最好的设计是最简单的设计”——爱因斯坦。关于DTO必要性的类似文章:
我的意见是在控制器层进行映射,因为该层负责输入/输出。服务层应该是独立的,以便可以将其用于开发另一个接口
如果您创建映射器类并仅在控制器层中创建它们,那么控制器中不会出现太多混乱。您是否建议我实际实现3个并行模型:DAO(例如OrderDao
)、DTO(例如OrderPlacedTo
)和Resource(例如OrderPlacedResource
)?这确实解决了我对服务具有控制器感知能力的担忧(反之亦然),但随着数据模型的增长,这可能会失控。
@RequestMapping("/placeOrder")
public @ResponseBody OrderPlacedRessource placeOrderAction(HttpServletRequest request){
OrderService service = ...;
ShoppingCartTO cart = ...;
OrderPlacedTO orderPlacedTO = service.placeOrder(cart);
OrderPlacedRessource orderPlacedRes = new OrderPlacedModel();
orderPlacedRes.setOrderNumber(orderPlacedTO.getOrderNumber());
// since orderPlacedRes is a RessourceSupport we can add links
// Use the HttpServletRequest to build your links
Link link = new Link("http://localhost:8080/something");
orderPlacedRes.addLink(link);
return orderPlacedRes;
}
orderPlacedRes.add(linkTo(methodOn(YourController.class).orderOverview(userId)).withSelfRel());