我在泽西岛有两个API,一个可能使用另一个。
class PersonAPI{
@PATH("/person")
@GET
// support query param filter such as ?first_name=John&birthday=1988-09-12
public Person getPerson(){
return PersonService.getPerson(...);
}
}
// some other class
class PetAPI{
@PATH("/pet")
@GET
// support query param such as ?owner.first_name=John&owner.birthday=1988-09-12
public Pet getPet(){
//filter person based on "owner." params
}
}
在PetAPI
中实施过滤人员的一种方法是访问PersonService
,但我希望PetAPI
通过HTTP请求使用PersonAPI
,就像PersonAPI
一样是另一种资源。这是因为PetAPI
将来可能会重构为另一个容器,并且不会与PersonAPI
在同一个应用程序中。
在Jersey中有没有办法像这样调用PersonAPI,即使现在PersonAPI
和PetAPI
在同一个应用程序中?
WebTarget target = client.target(baseURL + "/person");
target.queryParam( .... );
target.request().get().readEntity(Person.class);
编辑:我想更重要的问题是:在处理需要使用其他资源的资源时这是一个好方法吗?
答案 0 :(得分:1)
您描述的情况非常常见,并且不以任何方式特定于泽西岛。
毫无疑问,您不希望在同一容器中的API之间进行Web服务调用。那效率很低。当API在同一个容器中时,你真的想要一个有效的解决方案,当它们放在不同的容器中时,它很容易重构。
与面向服务的项目一起使用的模式是为服务定义接口,然后具有该接口的两个不同实现。第一个实现是您已经拥有的实现,并包含实际的业务逻辑。当业务逻辑实际在另一个容器中实现时,使用第二个实现。具体来说,您的界面可能被称为PersonService
,它由PersonServiceImpl
和PersonRemoteServiceImpl
(或您喜欢的任何命名约定)实现。
PersonServiceImpl.getPerson()
查询数据库(或者它会得到一个人)。
PersonRemoteServiceImpl.getPerson()
使得和HTTP调用另一个容器来获取此人。
现在,将PetApi
和PersonApi
放在同一个容器中,您甚至不需要实现PersonRemoteServiceImpl
(还原) - 保存该重构直到您需要它为止。但是当你做重构时,你只需要创建"远程"实现服务并替换您在PetApi
中使用的服务的具体实现。事实上,在您需要第二次实现之前,您可以推迟为服务创建单独的界面。
如果您想让这种方法更容易一些,您可能不希望将服务方法实现为静态(如示例代码所示)。问题是你必须提到实际的类,而不是能够将它切换到接口。像这样的编码模式就是我的建议:
public interface PersonService {
Person getPerson();
}
public class PersonServiceImpl implements PersonService {
public Person getPerson() { return new Person(); }
}
public class PersonApi {
@PATH("/person")
@GET
public Person getPerson(){
return getPersonService().getPerson(...);
}
public PersonService getPersonService() {
// Return the appropriate implementation.
if (personService == null) {
personService = new PersonServiceImpl();
}
return personService
}
private PersonService personService;
}
服务实现实例的示例管理是天真的,并且最好是实现某种类型的服务管理器"它将在该服务的所有消费者之间共享一个实例,或者像Spring一样实现IOC(控制反转)以注入所需服务实现。
如上所述,(除非您使用其中一个框架),您可以推迟将接口与实现分开,直到您真正需要它为止。如果您提前计划,如果/当您真正需要时,该重构很容易本地化。