【问题标题】:DropWizard/Jersey API ClientsDropWizard/Jersey API 客户端
【发布时间】:2014-12-24 15:43:02
【问题描述】:

DropWizard 在 REST 的底层使用 Jersey。我试图弄清楚如何为我的 DropWizard 应用程序将公开的 RESTful 端点编写客户端。

为了这个例子,假设我的 DropWizard 应用程序有一个 CarResource,它公开了一些简单的 RESTful 端点用于 CRUDding 汽车:

@Path("/cars")
public class CarResource extends Resource {
    // CRUDs car instances to some database (DAO).
    public CardDao carDao = new CarDao();

    @POST
    public Car createCar(String make, String model, String rgbColor) {
        Car car = new Car(make, model, rgbColor);
        carDao.saveCar(car);

        return car;
    }

    @GET
    @Path("/make/{make}")
    public List<Car> getCarsByMake(String make) {
        List<Car> cars = carDao.getCarsByMake(make);
        return cars;
    }
}

所以我会想象结构化 API 客户端类似于CarServiceClient

// Packaged up in a JAR library. Can be used by any Java executable to hit the Car Service
// endpoints.
public class CarServiceClient {
    public HttpClient httpClient;

    public Car createCar(String make, String model, String rgbColor) {
        // Use 'httpClient' to make an HTTP POST to the /cars endpoint.
        // Needs to deserialize JSON returned from server into a `Car` instance.
        // But also needs to handle if the server threw a `WebApplicationException` or
        // returned a NULL.
    }

    public List<Car> getCarsByMake(String make) {
        // Use 'httpClient' to make an HTTP GET to the /cars/make/{make} endpoint.
        // Needs to deserialize JSON returned from server into a list of `Car` instances.
        // But also needs to handle if the server threw a `WebApplicationException` or
        // returned a NULL.
    }
}

但我能找到的仅有的两个关于 Drop Wizard 客户端的官方参考完全相互矛盾:

  • DropWizard recommended project structure - 它声称我应该将我的客户端代码放在car.service.client 包下的car-client 项目中;但后来...
  • DropWizard Client manual - 这使它看起来像是一个“DropWizard 客户端”,用于将我的 DropWizard 应用程序与 其他 RESTful Web 服务集成(因此充当中间人)。

所以我问,为 DropWizard Web 服务编写 Java API 客户端的标准方法是什么? DropWizard 是否有可用于此类用例的客户端库?我应该通过一些 Jersey 客户端 API 来实现客户端吗?有人可以在我的CarServiceClient 中添加伪代码,以便我了解它是如何工作的吗?

【问题讨论】:

    标签: java rest jersey dropwizard webservices-client


    【解决方案1】:

    这是您可以通过 JAX-RS 客户端使用的模式。

    获取客户端:

    javax.ws.rs.client.Client init(JerseyClientConfiguration config, Environment environment) {
        return new JerseyClientBuilder(environment).using(config).build("my-client");
    }
    

    然后您可以通过以下方式拨打电话:

    javax.ws.rs.core.Response post = client
            .target("http://...")
            .request(MediaType.APPLICATION_JSON)
            .header("key", value)
            .accept(MediaType.APPLICATION_JSON)
            .post(Entity.json(myObj));
    

    【讨论】:

      【解决方案2】:

      是的,dropwizard-client 提供的只是服务本身使用,最有可能与其他服务通信。它不直接为客户端应用程序提供任何东西。

      无论如何,它对 HttpClients 并没有多大作用。它只是根据yml文件配置客户端,将现有的Jackson对象映射器和验证器分配给Jersey客户端,我认为复用了应用程序的线程池。你可以在https://github.com/dropwizard/dropwizard/blob/master/dropwizard-client/src/main/java/io/dropwizard/client/JerseyClientBuilder.java上查看所有内容

      我想我会像您使用 Jersey Client 那样构建我的课程。以下是我一直用于客户端服务的抽象类:

      public abstract class HttpRemoteService {
      
        private static final String AUTHORIZATION_HEADER = "Authorization";
        private static final String TOKEN_PREFIX = "Bearer ";
      
        private Client client;
      
        protected HttpRemoteService(Client client) {
          this.client = client;
        }
      
        protected abstract String getServiceUrl();  
      
        protected WebResource.Builder getSynchronousResource(String resourceUri) {
          return client.resource(getServiceUrl() + resourceUri).type(MediaType.APPLICATION_JSON_TYPE);
        }
      
        protected WebResource.Builder getSynchronousResource(String resourceUri, String authToken) {
          return getSynchronousResource(resourceUri).header(AUTHORIZATION_HEADER, TOKEN_PREFIX + authToken);
        }
      
        protected AsyncWebResource.Builder getAsynchronousResource(String resourceUri) {
          return client.asyncResource(getServiceUrl() + resourceUri).type(MediaType.APPLICATION_JSON_TYPE);
        }
      
        protected AsyncWebResource.Builder getAsynchronousResource(String resourceUri, String authToken) {
          return getAsynchronousResource(resourceUri).header(AUTHORIZATION_HEADER, TOKEN_PREFIX + authToken);
        }
      
        protected void isAlive() {
          client.resource(getServiceUrl()).get(ClientResponse.class);
        }  
      
      }
      

      这是我如何具体化的:

      private class TestRemoteService extends HttpRemoteService {
      
          protected TestRemoteService(Client client) {
            super(client);
          }
      
          @Override
          protected String getServiceUrl() {
            return "http://localhost:8080";
          }
      
          public Future<TestDTO> get() {
            return getAsynchronousResource("/get").get(TestDTO.class);
          }
      
          public void post(Object object) {
            getSynchronousResource("/post").post(object);
          }
      
          public void unavailable() {
            getSynchronousResource("/unavailable").get(Object.class);
          }
      
          public void authorize() {
            getSynchronousResource("/authorize", "ma token").put();
          }
        }
      

      【讨论】:

        【解决方案3】:

        如果有人在构建客户端时尝试使用 DW 0.8.2,并且您收到以下错误:

        cannot access org.apache.http.config.Registry
        class file for org.apache.http.config.Registry not found
        
        at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:858)
        at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
        ... 19 more
        

        将 pom.xml 中的 dropwizard-client 从 0.8.2 更新到 0.8.4,你应该会很好。我相信 jetty 子依赖已更新并修复了它。

            <dependency>
                <groupId>io.dropwizard</groupId>
                <artifactId>dropwizard-client</artifactId>
                <version>0.8.4</version>
                <scope>compile</scope>
            </dependency>
        

        【讨论】:

          【解决方案4】:

          可以结合Spring Framework来实现

          【讨论】:

            猜你喜欢
            • 2015-08-28
            • 1970-01-01
            • 1970-01-01
            • 2015-07-11
            • 2021-08-22
            • 2023-03-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多