When using SpringBoot, RestTemplate is usually used if you need to invoke a third-party Rest API. Sometimes I don’t know how to pass a parameter, but when the parameter is assigned a value, the receiver receives a null value. This article summarizes some of the most commonly used methods.

The preparatory work

The request object
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
  private Long id;

  private String name;
}
Copy the code

Third Party request

@RestController
public class PersonController {
		
    // Store the relationship between id and person
    private static Map<Long, Person> persons = new HashMap<>();
		// Generate the ID of person
    private static final LongAdder ID_ADDER = new LongAdder();
    static {
        ID_ADDER.add(1L);
        Person person = new Person();
        person.setId(ID_ADDER.longValue());
        person.setName("1-person"); persons.put(person.getId(), person); }... Omit others}Copy the code

For the third party interface only simple implementation, ignore some details such as parameter verification.

RestTemplate accesses the GET interface

The request parameters are in the path

Third-party interface to query Person by ID

@GetMapping("/getPerson/{id}")
public Person getPersonPathVariable(@PathVariable(name = "id") Long id) {
  return persons.getOrDefault(id, new Person());
}
Copy the code

Sample request

Get / / request
URI uri = UriComponentsBuilder.fromUriString(String.format(URL_FORMAT, "/getPerson/{id}")).build(1L);
ResponseEntity<Person> forEntity = REST_TEMPLATE.getForEntity(uri, Person.class);
log.info("getForEntity result:{}", forEntity);

Person forObject = REST_TEMPLATE.getForObject(uri, Person.class);
log.info("getForObject result:{}", forObject);
Copy the code

ResponseEntity in addition to the normal return result, also contains HTTP related information, see the following log.

16:10:48. [the main] INFO 391 com. Yichao. Myblogs. Resttemplate. RestTemplateTest - getForEntity result: < 200, Person (id = 1, name=1-person),[Content-Type:"application/json", Transfer-Encoding:"chunked", Date:"Sat, 15 May 2021 08:10:48 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]>Copy the code
Generic request parameter passing, i.e.? name=xxx&id=xxx

Third-party interface to query Person by ID

@GetMapping("/getPerson")
public Person getPersonWithParams(HttpServletRequest httpServletRequest) {
  String idStr = httpServletRequest.getParameter("id");
  return persons.getOrDefault(Long.valueOf(idStr), new Person());
}
Copy the code

Sample request

Get / / request
URI uri = UriComponentsBuilder.fromUriString(String.format(URL_FORMAT, "/getPerson/{id}")).build(1L);

uri = UriComponentsBuilder.fromUriString(String.format(URL_FORMAT, "/getPerson? id={id}")).build(1L);
ResponseEntity<Person> forEntity = REST_TEMPLATE.getForEntity(uri, Person.class);
log.info("getForEntity result:{}", forEntity);

Person forObject = REST_TEMPLATE.getForObject(uri, Person.class);
log.info("getForObject result:{}", forObject);
Copy the code

RestTemplate accesses the POST interface

The following are distinguished by several different forms of API parameters.

The argument uses @requestBody

Third-party interface that stores the Person passed in and returns the Person object with the primary key added.

@PostMapping("/add/requestBody")
public Person postRequestBody(@RequestBody Person person) {
  ID_ADDER.add(1L);
  Long id = ID_ADDER.longValue();
  person.setId(id);
  persons.put(person.getId(), person);
  return person;
}
Copy the code

Sample request

String url = String.format(URL_FORMAT, "/add/requestBody");
Person person;
ResponseEntity<Person> responseEntity;

// Generate an object containing only name. The third-party interface is responsible for generating the ID and returning it
Person mockPerson = mockPerson();

person = REST_TEMPLATE.postForObject(url, mockPerson, Person.class);
log.info("requestBody postForObject result:{}", person);

responseEntity = REST_TEMPLATE.postForEntity(url, mockPerson, Person.class);
log.info("requestBody postForEntity result:{}", responseEntity);
Copy the code
Working directly with objects

Third-party Interface

@PostMapping("/add/form")
public Person postForm(Person person) {
  ID_ADDER.add(1L);
  Long id = ID_ADDER.longValue();
  person.setId(id);
  persons.put(person.getId(), person);
  return person;
}
Copy the code

Sample request

// form request format
String url = String.format(URL_FORMAT, "/add/form");
HttpHeaders headers = new HttpHeaders();

Person mockPerson = mockPerson();
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
// Convert the request object to a map and add it to multiValueMap
@SuppressWarnings("unchecked")
Map<String, Object> params = JSON.parseObject(JSON.toJSONString(mockPerson), Map.class);
params.forEach(map::add);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(map, headers);
Person person = REST_TEMPLATE.postForObject(url, httpEntity, Person.class);
log.info("form postForObject result:{}", person);

ResponseEntity<Person> responseEntity = REST_TEMPLATE.postForEntity(url, httpEntity, Person.class);
log.info("form postForEntity result{}", responseEntity);
Copy the code
The use of it

Third-party Interface

@PostMapping("/add/requestParam")
public Person postRequestParam(HttpServletRequest httpServletRequest) {
    ID_ADDER.add(1L);
    String name = httpServletRequest.getParameter("name");
    Long id = ID_ADDER.longValue();
    Person person = new Person();
    person.setId(id);
    person.setName(name);
    persons.put(person.getId(), person);
    return person;
}
Copy the code

Sample request

This method is the same as the form request

String url = String.format(URL_FORMAT, "/add/requestParam");
HttpHeaders headers = new HttpHeaders();

Person mockPerson = mockPerson();
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
// Convert the request object to a map and add it to multiValueMap
@SuppressWarnings("unchecked")
Map<String, Object> params = JSON.parseObject(JSON.toJSONString(mockPerson), Map.class);
params.forEach(map::add);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(map, headers);
Person person = REST_TEMPLATE.postForObject(url, httpEntity, Person.class);
log.info("requestParam postForObject result:{}", person);

ResponseEntity<Person> responseEntity = REST_TEMPLATE.postForEntity(url, httpEntity, Person.class);
log.info("requestParam postForEntity result{}", responseEntity);
Copy the code

Advanced usage

Interfaces return generics

Third-party interface that returns a list of Persons

@GetMapping("/listAll")
public List<Person> list(a) {
  return new ArrayList<>(persons.values());
}
Copy the code

Sample request

String url = String.format(URL_FORMAT, "listAll");
// Specify the parameter type, which will actually store the returned type
ParameterizedTypeReference<List<Person>> parameterizedTypeReference = new ParameterizedTypeReference<List<Person>>() {
};
ResponseEntity<List<Person>> exchange = REST_TEMPLATE.exchange(url, HttpMethod.GET, null, parameterizedTypeReference);
log.info("testGeneric result:{}", exchange);
List<Person> personList = exchange.getBody();
log.info("person List:{}", personList);
Copy the code
Customized RestTemplate

The following code is used to set some properties of RestTemplate, such as the HTTP connection pool information used by RestTemplate

private static HttpComponentsClientHttpRequestFactory clientHttpRequestFactory(a) {
  try {
    HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
    // Start setting the connection pool
    PoolingHttpClientConnectionManager poolingHttpClientConnectionManager =
      new PoolingHttpClientConnectionManager();
    // Maximum number of connections
    poolingHttpClientConnectionManager.setMaxTotal(100);
    // Number of concurrent routes
    poolingHttpClientConnectionManager.setDefaultMaxPerRoute(10);
    httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
    // Do not retry
    httpClientBuilder.setRetryHandler(new HttpRequestRetryHandler() {
      @Override
      public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
        if (exception instanceof org.apache.http.NoHttpResponseException) {
          // Retry is required in this case
          log.warn("No response from server on " + executionCount + " call");
          return true;
        }
        return false; }}); HttpClient httpClient = httpClientBuilder.build(); HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =// httpClient connection configuration
      new HttpComponentsClientHttpRequestFactory(httpClient);
    // Connection timed out
    clientHttpRequestFactory.setConnectTimeout(5000);
    // Data read timeout time
    clientHttpRequestFactory.setReadTimeout(30000);
    // Insufficient connection wait time
    clientHttpRequestFactory.setConnectionRequestTimeout(5000);
    return clientHttpRequestFactory;
  } catch (Exception e) {
    log.error("Error initializing HTTP connection pool", e);
  }
  return null;
}

Copy the code

Set the RestTemplate

new RestTemplateBuilder().requestFactory(() -> clientHttpRequestFactory()).build();
Copy the code

The last

RestTemplate is very powerful, and this article mainly introduces some common features, as well as the previous pit, hoping to help you.