向自己发出HTTP请求:重用端点

时间:2016-03-09 18:57:41

标签: proxy jersey jax-rs

我在泽西岛有两个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,即使现在PersonAPIPetAPI在同一个应用程序中?

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

编辑:我想更重要的问题是:在处理需要使用其他资源的资源时这是一个好方法吗?

1 个答案:

答案 0 :(得分:1)

您描述的情况非常常见,并且不以任何方式特定于泽西岛。

毫无疑问,您不希望在同一容器中的API之间进行Web服务调用。那效率很低。当API在同一个容器中时,你真的想要一个有效的解决方案,当它们放在不同的容器中时,它很容易重构。

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

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

PersonRemoteServiceImpl.getPerson()使得和HTTP调用另一个容器来获取此人。

现在,将PetApiPersonApi放在同一个容器中,您甚至不需要实现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(控制反转)以注入所需服务实现。

如上所述,(除非您使用其中一个框架),您可以推迟将接口与实现分开,直到您真正需要它为止。如果您提前计划,如果/当您真正需要时,该重构很容易本地化。