2017-10-10 67 views
0

正如我已经几次面临这个问题没有很好地解决REST API建设者:REST API设计查询

拥有它似乎很清楚一个实体组织,我们可以休息型号为/组织,所有的包(GET,POSt,PUT,DELETE,过滤,分页,...)

请注意,我使用Spring将@RestController类和spring-data PagingAndSortingRepository注入到控制器中。

的问题

/组织/(编号)开始/用户

这是一个REST API一个完美的URL,但开始引起一些疼痛。

如果我们按照在组织控制器中处理请求的路径,我们需要将UserDAO添加到控制器,所以我们可以在每个控制器中注入很多DAOS并且每个控制器都负责返回许多不同的对象:组织,用户,型号等

将问题推到DAO层不是解决方案;试图使存储库返回所有这些不同的对象将不起作用(PagingAndSortingRepository应该抱怨,如果我们试图与不同的实体一起工作),并且它感觉不到正确的事情,因为我们强制存储库与其领域之外的实体一起工作。

在控制器和DAO之间使用中间层可以工作,一个服务层可以容纳这些不同的DAO并提供一个外观,但又会感觉错误:首先,控制器仍在处理许多不属于它的对象其次,我们有一个没有真正目的的图层,可以使用DAO的组合来增长,或者拥有一个可以查询任何东西的伟大的主DAO对象。

解决这个问题的好方法是什么?

回答

0

我实际上有几次类似的问题,并带有通用的解决方案。让我们首先重新定义问题:在您的服务或控制器中,您将需要执行可能具有不同类型的操作。 (在你的情况下,你需要访问一个在不同运行时可能是用户,组织模型或其他东西的对象。每种访问类型都是由一个单独的bean执行的,并且不希望将所有这些bean注入到服务/控制器

解决方案是工厂模式,我做了以下工作:我创建了一个接口和一个抽象类来实现这个接口(在你的情况下它就像GenericDao和GenericDaoImpl)。工厂类(说GeneralDaoFactory)。这个类包含地图Map<String, GenericDao>在我的泛型类中,我写了一个构造函数,它将自己添加到Factory中。Factory接收一个名称(通常是一个类名)和一个GenericDao实例,并将其放入其内部映射然后你只需编写实现GenericDaoImpl(OrganizationDaoImpl,UserDaoImpl等)和m确信他们被定义为豆类。在初始化期间,Spring将实例化所有的bean,每个运行其构造函数的bean将自己放入工厂。所以,现在在你的代码在你的控制器/所有你需要做的服务:

GenericDao userDao = GeneralDaoFactory.getInstance("UserDaoImpl"); 
GenericDao organizationDao = GeneralDaoFactory.getInstance("OrganizationDaoImpl"); 

工厂将被Spring的scienes后面初始化,你不需要任何注入这些DAOS提前。你只需要知道他们的名字,并知道你现在需要哪一个。也曾经,你需要添加一个新道,所有你需要做的是actuially写入其implementatin,现在可从您的工厂

+0

mmm ...不确定理解,因为你在最后注入了两个DAO ......但我想也许你的建议是使用通用DAO的泛型控制器和一个机制来确定具体需要哪些DAO请求,并将在运行时实例化具有特定DAO的特定控制器以提供该特定请求。这是它吗? – Rafael

+0

@Rafael你错过了。首先没有通用控制器 - 只是你的常规控制器。其次,没有DAO被注入,它们只是在Spring中被创建为bean,但没有被注入到任何地方。但是你有一个工厂可以保存对它们的引用 - 每个bean都将自己放入工厂地图的构造函数中。然后在您的控制器运行时,您可以通过工厂获得任何DAO –

0

幽州/organization/{id}/users是一个REST API一个完美的URL。

这是一个合理的网址,但我认为,由于网址跨域,因此只能用于搜索

此外,强制执行单个责任来限制每个控制器的DAO数量。上述URL的支持控制器将类似于OrganizationUsersSearchController。据推测,该方法返回List<User> users为请求的id。此类与OrganzationsDAO进行交互以获取某些上下文,并将上下文传递给UsersDAO以获取用户列表。 DAO可以被服务类包装,所以控制器只是一个门面。

一旦客户端拥有users的列表,CRUD操作将由客户端使用单个域URL(例如/users/{userId})调用。 UserController只与UsersDAO相互作用。再一次,也许将DAO包装在一个服务类中,这样控制器就是一个门面。

+0

“只能用于搜索”。 ...我可以同意,仍然看起来像一个非常稳固的其余网址。 “单一责任被强制限制每个控制器的DAO数量”正是这个问题的出发点。现在我认为OrganizationUsersSearchController对我来说看起来像是一个糟糕的解决方案,因为控制器将开始倍增......我们将以可能很多的控制器临时结束以支持这些操作,同时路由也将是复杂的,因为起始部分的URl是一样的。 – Rafael