How do I request Spring Boot of RESTFul services using the Jersey client

  • 2020-12-20 03:37:19
  • OfStack

This article introduces the use of Jersey client to request Spring Boot(RESTFul) service, share to everyone, specific as follows:

Jersey client gets Client object instance encapsulation:


@Service("jerseyPoolingClient") 
public class JerseyPoolingClientFactoryBean implements FactoryBean<Client>, InitializingBean, DisposableBean{ 
   
  /** 
   * Client Interface is REST The basic interface of the client, used for and REST Server communication. Client Is defined as 1 A heavyweight object whose internal management  
   *  The client communicates with various underlying objects, such as connectors, parsers, and so on. Therefore, it is not recommended to generate a large number of Client Instance, the 1 Point under development  
   *  Special care is required, and the interface requires that the connection be closed, otherwise memory leaks will occur  
   */ 
  private Client client; 
   
  /** 
   * 1 a Client Maximum number of connections, default 2000 
   */ 
  private int maxTotal = 2000; 
   
  /** 
   *  The default maximum number of connections per route  
   */ 
  private int defaultMaxPerRoute = 1000; 
   
  private ClientConfig clientConfig; 
   
  public JerseyPoolingClientFactoryBean() { 
  } 
   
  /** 
   *  Constructor with configuration  
   * @param clientConfig 
   */ 
  public JerseyPoolingClientFactoryBean(ClientConfig clientConfig) { 
    this.clientConfig = clientConfig; 
  } 
 
  public JerseyPoolingClientFactoryBean(int maxTotal, int defaultMaxPerRoute) { 
    this.maxTotal = maxTotal; 
    this.defaultMaxPerRoute = defaultMaxPerRoute; 
  } 
 
  /** 
   * attention: 
   * Details : When the container is destroyed, release Client resources  
   * @author chhliu 
   */ 
  @Override 
  public void destroy() throws Exception { 
    this.client.close(); 
  } 
 
  /** 
   * 
   * attention: 
   * Details : in the form of a connection pool Client object  
   * @author chhliu 
   */ 
  @Override 
  public void afterPropertiesSet() throws Exception { 
    //  If no tape is used ClientConfig , the instance of the class is null , is initialized with the default configuration  
    if(this.clientConfig == null){ 
      final ClientConfig clientConfig = new ClientConfig(); 
      //  Connection pool management instance, which is thread-safe and supports multiple concurrent operations  
      PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(); 
      pcm.setMaxTotal(this.maxTotal); 
      pcm.setDefaultMaxPerRoute(this.defaultMaxPerRoute); 
       
      clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, pcm); 
      /* 
       *  In the use of Jersey To request Spring Boot Service, Spring Boot Use the default Jackson To resolve JSON 
       *  while Jersey Use the default MOXy parsing JSON when Jersey Client Want to Spring Boot When a service requests a resource,  
       *  This difference can result in server and client pairs POJO Different transformations, resulting in a deserialization error  
       *  Therefore, it needs to be in Client the Config Registration in an instance Jackson features  
       */ 
      clientConfig.register(JacksonFeature.class); 
      //  Using a configuration Apache Connector. The default connector is HttpUrlConnector 
      clientConfig.connectorProvider(new ApacheConnectorProvider()); 
      client = ClientBuilder.newClient(clientConfig); 
    }else{ 
      //  Use in the constructor ClientConfig To initialize the Client object  
      client = ClientBuilder.newClient(this.clientConfig); 
    } 
  } 
 
  /** 
   * attention: 
   * Details Returns the Client Object if the object is null , create 1 A default Client 
   * @author chhliu 
   */ 
  @Override 
  public Client getObject() throws Exception { 
    if(null == this.client){ 
      return ClientBuilder.newClient(); 
    } 
    return this.client; 
  } 
 
  /** 
   * attention: 
   * Details : get Client Type of object  
   * @author chhliu 
   */ 
  @Override 
  public Class<?> getObjectType() { 
    return (this.client == null ? Client.class : this.client.getClass()); 
  } 
 
  /** 
   * attention: 
   * Details : Client Whether the object is a singleton, the default is a singleton  
   * @author chhliu 
   */ 
  @Override 
  public boolean isSingleton() { 
    return true; 
  } 
} 

Request encapsulation of Spring Boot service:


@Component("jerseyClient") 
public class JerseyClient { 
   
  @Resource(name="jerseyPoolingClient") 
  private Client client; 
   
  /** 
   * attention: 
   * Details Through: id To query for objects  
   * @author chhliu 
   */ 
  public ResultMsg<GitHubEntity> getResponseById(final String id) throws JsonProcessingException, IOException{ 
    WebTarget webTarget = client.target("http://localhost:8080").path("/github/get/user/"+id); 
    Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); 
    GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){}; 
    Response response = invocationBuilder.get(); 
    if(response.getStatus() == 200){ 
      /* 
       *  When calling readEntity Method, the program will automatically release the connection  
       *  Even if there is no call readEntity Method, which returns the object of the generic type directly, and the underlying layer still releases the connection  
       */ 
      return response.readEntity(genericType); 
    }else{ 
      ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>(); 
      res.setErrorCode(String.valueOf(response.getStatus())); 
      res.setErrorMsg(response.getStatusInfo().toString()); 
      res.setOK(false); 
      return res; 
    } 
  } 
   
  /** 
   * attention: 
   * Details : Paging query  
   * @author chhliu 
   */ 
  public ResultMsg<Pager<GitHubEntity>> getGithubWithPager(final Integer pageOffset, final Integer pageSize, final String orderColumn){ 
    WebTarget webTarget = client.target("http://localhost:8080").path("/github/get/users/page") 
        .queryParam("pageOffset", pageOffset) 
        .queryParam("pageSize", pageSize) 
        .queryParam("orderColumn", orderColumn); 
        //  Note that if the media type here is MediaType.APPLICATION_JSON , then the parameters in the corresponding service should be appended @RequestBody 
        Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); 
    GenericType<ResultMsg<Pager<GitHubEntity>>> genericType = new GenericType<ResultMsg<Pager<GitHubEntity>>>(){}; 
    Response response = invocationBuilder.get(); 
    if(response.getStatus() == 200){ 
      return response.readEntity(genericType); 
    }else{ 
      ResultMsg<Pager<GitHubEntity>> res = new ResultMsg<Pager<GitHubEntity>>(); 
      res.setErrorCode(String.valueOf(response.getStatus())); 
      res.setErrorMsg(response.getStatusInfo().toString()); 
      res.setOK(false); 
      return res; 
    } 
     
  } 
   
  /** 
   * attention: 
   * Details : Query by user name  
   * @author chhliu 
   */ 
  public ResultMsg<List<GitHubEntity>> getResponseByUsername(final String username) throws JsonProcessingException, IOException{ 
    WebTarget webTarget = client.target("http://localhost:8080").path("/github/get/users/"+username); 
    Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); 
    GenericType<ResultMsg<List<GitHubEntity>>> genericType = new GenericType<ResultMsg<List<GitHubEntity>>>(){}; 
    Response response = invocationBuilder.get(); 
    if(response.getStatus() == 200){ 
      return response.readEntity(genericType); 
    }else{ 
      ResultMsg<List<GitHubEntity>> res = new ResultMsg<List<GitHubEntity>>(); 
      res.setErrorCode(String.valueOf(response.getStatus())); 
      res.setErrorMsg(response.getStatusInfo().toString()); 
      res.setOK(false); 
      return res; 
    } 
  } 
   
  /** 
   * attention: 
   * Details : according to the id To delete 1 A record  
   * @author chhliu 
   */ 
  public ResultMsg<GitHubEntity> deleteById(final String id) throws JsonProcessingException, IOException{ 
    WebTarget target = client.target("http://localhost:8080").path("/github/delete/"+id); 
    GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){}; 
    Response response = target.request().delete(); 
    if(response.getStatus() == 200){ 
      return response.readEntity(genericType); 
    }else{ 
      ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>(); 
      res.setErrorCode(String.valueOf(response.getStatus())); 
      res.setErrorMsg(response.getStatusInfo().toString()); 
      res.setOK(false); 
      return res; 
    } 
  } 
   
  /** 
   * attention: 
   * Details Update: 1 records  
   * @author chhliu 
   */ 
  public ResultMsg<GitHubEntity> update(final GitHubEntity entity) throws JsonProcessingException, IOException{ 
    WebTarget target = client.target("http://localhost:8080").path("/github/put"); 
    GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){}; 
    Response response = target.request().buildPut(Entity.entity(entity, MediaType.APPLICATION_JSON)).invoke(); 
    if(response.getStatus() == 200){ 
      return response.readEntity(genericType); 
    }else{ 
      ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>(); 
      res.setErrorCode(String.valueOf(response.getStatus())); 
      res.setErrorMsg(response.getStatusInfo().toString()); 
      res.setOK(false); 
      return res; 
    } 
  } 
   
  /** 
   * attention: 
   * Details Insert: 1 records  
   * @author chhliu 
   */ 
  public ResultMsg<GitHubEntity> save(final GitHubEntity entity) throws JsonProcessingException, IOException{  
     WebTarget target = client.target("http://localhost:8080").path("/github/post"); 
     GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){}; 
     Response response = target.request().buildPost(Entity.entity(entity, MediaType.APPLICATION_JSON)).invoke(); 
     if(response.getStatus() == 200){ 
       return response.readEntity(genericType); 
     }else{ 
      ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>(); 
      res.setErrorCode(String.valueOf(response.getStatus())); 
      res.setErrorMsg(response.getStatusInfo().toString()); 
      res.setOK(false); 
      return res; 
     } 
  } 
} 

Jersey client interface details

1 Client interface

Create a Client instance through ClientBuilder structure, often use a ClientConfig instance as a parameter, if we use Client client = ClientBuilder. newClient () method to create instances of Client, always create a Client examples, but the instance is a heavyweight object, therefore, it is recommended to use HTTP connection pool to manage connections, rather than every request to create a Client object, specific connection pool management way to see the code example above.

2 WebTarget interface

WebTarget interface is an interface to realize resource location for REST client. Through WebTarget interface, we can define the specific address of the requested resource, query parameters and media type information, etc. We can be done by means of method of chain for 1 WebTarget instance configuration, but it is important to note that although WebTarget use way and the method of StringBuffer chain way are very similar, but the essence is the no 1 sample, WebTarget method chain must set the return value, as a handle to the follow-up process, this is what meaning, see the following sample:

Example 1: Example of StringBuffer's method chain


StringBuffer sb = new StringBuffer("lch"); 
     sb.append("hello"); 
     sb.append("world"); 
     sb.append("hello").append("world"); //  The effect of this approach and the above two lines of code is 1 Kind of.  

Example 2: Example of WebTarget's method chain


//  use 1 Line of code to instantiate a method chain WebTarget 
WebTarget webTarget = client.target("http://localhost:8080"); 
webTarget.path("/github/get/users/page") 
  .queryParam("pageOffset", pageOffset) 
  .queryParam("pageSize", pageSize) 
  .queryParam("orderColumn", orderColumn); 
//  Below is a separate instantiation using the method chain WebTarget 
webTarget.path("/github/get/users/page"); 
webTarget.queryParam("pageOffset", pageOffset); 
webTarget.queryParam("pageSize", pageSize); 
//  The above two methods of instantiation produce very different results. The above method of instantiation is OK There is no problem with the following instantiation. In the following instantiation, each 1 All rows will be generated 1 a  
//  The new WebTarget Object, the original WebTarget It didn't work, after all 1 None of the row instances 1 If, for example, we want to instantiate in multiple rows, we must provide for the return of each method 1 Handle, as follows:  
 
WebTarget target = client.target("http://localhost:8080"); 
WebTarget pathTarget = target.path("/github/get/users/page"); 
WebTarget paramTarget = pathTarget.queryParam("pageOffset", pageOffset); 
 
//  When you use it last, use it last 1 a WebTarget Instance object is enough  

3 Invocation interface

Invocation interface is the interface that makes a request to REST server after resource positioning configuration is completed. The request includes synchronous and asynchronous modes. It is defined by Builder interface inside Invocation interface.


Future<ResultMsg<List<GitHubEntity>>> response = invocationBuilder.async().get(genericType); 
 
    if(response.isDone()){ 
      return response.get(); 
    } 

The Invocation. Builder interface instance performs the GET and POST requests respectively to submit the query and create. By default, the return type of the HTTP method call is Response type, and it also supports the return value of generic types. In the above example, we used a lot of generics, which we won't explain too much here.


Related articles: