向自身发出 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,即使现在 PersonAPIPetAPI 在同一个应用程序中?

WebTarget target = client.target(baseURL + "/person");
target.queryParam( .... );
target.request().get().readEntity(Person.class);

编辑:我想更重要的问题是:当处理一种资源需要使用另一种资源时,这是一种好方法吗?

您描述的情况很常见,在任何方面都不是泽西岛特有的。

毫无疑问,您不希望在同一容器中的 API 之间进行 Web 服务调用。那是低效的。当 API 位于同一容器中并且易于重构时,您确实需要一个高效的解决方案 if/when 它们位于不同的容器中。

一种适用于面向服务的项目的模式是为服务定义一个接口,然后对该接口进行两种不同的实现。第一个实现是您已有的实现,它包含实际的业务逻辑。当业务逻辑实际在另一个容器中实现时,使用第二种实现。具体来说,您的接口可能被称为 PersonService,它由 PersonServiceImplPersonRemoteServiceImpl(或您喜欢的任何命名约定)实现。

PersonServiceImpl.getPerson() 查询数据库(或者它得到一个人)。

PersonRemoteServiceImpl.getPerson() 对另一个容器进行 HTTP 调用以获取此人。

目前,PetApiPersonApi 位于同一个容器中,您甚至不需要实施 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 您确实需要它。