向自身发出 HTTP 请求:重用端点
Make HTTP request to itself: reusing endpoint
我在泽西岛有两个 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
就好像 [=15] =] 是另一种资源。这是因为 PetAPI
将来可能会被重构为另一个容器,并且不会与 PersonAPI
在同一个应用程序中。
泽西岛有没有办法像这样调用 PersonAPI,即使现在 PersonAPI
和 PetAPI
在同一个应用程序中?
WebTarget target = client.target(baseURL + "/person");
target.queryParam( .... );
target.request().get().readEntity(Person.class);
编辑:我想更重要的问题是:当处理一种资源需要使用另一种资源时,这是一种好方法吗?
您描述的情况很常见,在任何方面都不是泽西岛特有的。
毫无疑问,您不希望在同一容器中的 API 之间进行 Web 服务调用。那是低效的。当 API 位于同一容器中并且易于重构时,您确实需要一个高效的解决方案 if/when 它们位于不同的容器中。
一种适用于面向服务的项目的模式是为服务定义一个接口,然后对该接口进行两种不同的实现。第一个实现是您已有的实现,它包含实际的业务逻辑。当业务逻辑实际在另一个容器中实现时,使用第二种实现。具体来说,您的接口可能被称为 PersonService
,它由 PersonServiceImpl
和 PersonRemoteServiceImpl
(或您喜欢的任何命名约定)实现。
PersonServiceImpl.getPerson()
查询数据库(或者它得到一个人)。
PersonRemoteServiceImpl.getPerson()
对另一个容器进行 HTTP 调用以获取此人。
目前,PetApi
和 PersonApi
位于同一个容器中,您甚至不需要实施 PersonRemoteServiceImpl
(目前)- 保存该重构,直到您需要它.但是当你进行重构时,你只需要创建服务的 "remote" 实现并替换你在 PetApi
中使用的服务的具体实现。事实上,您可以推迟为服务创建单独的接口,直到您需要第二个实现。
如果你想让这种方法更简单一些,你可能不想将你的服务方法实现为静态的(如你的示例代码所示)。问题是您必须提及实际的 class,而不是能够将其切换到界面。像这样的编码模式是我的建议:
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;
}
服务实现实例的示例管理是天真的,最好是实现某种 "service manager" 将在该服务的所有消费者之间共享一个实例,或者像 Spring 实现 IOC(控制反转)以注入所需的服务实现。
如上所述,(除非您使用的是其中一种框架)您可以推迟将接口与实现分离,直到您真正需要它。如果您提前计划,该重构很容易本地化 if/when 您确实需要它。
我在泽西岛有两个 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
就好像 [=15] =] 是另一种资源。这是因为 PetAPI
将来可能会被重构为另一个容器,并且不会与 PersonAPI
在同一个应用程序中。
泽西岛有没有办法像这样调用 PersonAPI,即使现在 PersonAPI
和 PetAPI
在同一个应用程序中?
WebTarget target = client.target(baseURL + "/person");
target.queryParam( .... );
target.request().get().readEntity(Person.class);
编辑:我想更重要的问题是:当处理一种资源需要使用另一种资源时,这是一种好方法吗?
您描述的情况很常见,在任何方面都不是泽西岛特有的。
毫无疑问,您不希望在同一容器中的 API 之间进行 Web 服务调用。那是低效的。当 API 位于同一容器中并且易于重构时,您确实需要一个高效的解决方案 if/when 它们位于不同的容器中。
一种适用于面向服务的项目的模式是为服务定义一个接口,然后对该接口进行两种不同的实现。第一个实现是您已有的实现,它包含实际的业务逻辑。当业务逻辑实际在另一个容器中实现时,使用第二种实现。具体来说,您的接口可能被称为 PersonService
,它由 PersonServiceImpl
和 PersonRemoteServiceImpl
(或您喜欢的任何命名约定)实现。
PersonServiceImpl.getPerson()
查询数据库(或者它得到一个人)。
PersonRemoteServiceImpl.getPerson()
对另一个容器进行 HTTP 调用以获取此人。
目前,PetApi
和 PersonApi
位于同一个容器中,您甚至不需要实施 PersonRemoteServiceImpl
(目前)- 保存该重构,直到您需要它.但是当你进行重构时,你只需要创建服务的 "remote" 实现并替换你在 PetApi
中使用的服务的具体实现。事实上,您可以推迟为服务创建单独的接口,直到您需要第二个实现。
如果你想让这种方法更简单一些,你可能不想将你的服务方法实现为静态的(如你的示例代码所示)。问题是您必须提及实际的 class,而不是能够将其切换到界面。像这样的编码模式是我的建议:
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;
}
服务实现实例的示例管理是天真的,最好是实现某种 "service manager" 将在该服务的所有消费者之间共享一个实例,或者像 Spring 实现 IOC(控制反转)以注入所需的服务实现。
如上所述,(除非您使用的是其中一种框架)您可以推迟将接口与实现分离,直到您真正需要它。如果您提前计划,该重构很容易本地化 if/when 您确实需要它。