Пример Spring Boot Restful Client c RestTemplate

1- Цель примера

Статья основана на:
  • Spring Boot 2.x

  • RestTemplate

  • Eclipse 3.7

В данной статье я покажу вам как создать приложение Restful Client используя  Spring Boot. С 4 функциями:
  1. Создать request с методом GET, отправить к Restful Web Service чтобы получить список сотрудников (employee), или информацию сотрудника. Полученные данные будут иметь формат XML или JSON.
  2. Создать request с методом PUT, отправить к Restful Web Service, чтобы запросить изменить информацию сотрудника, данные прикрепленные к request имеют формат XML или JSON.
  3. Создать request с методом POST, отправить к Restful Web Service чтобы добавить нового сотрудника, данные прикрепленные к request имеют формат XML или JSON.
  4. Создать request с методом DELETE, отправить к Restful Web Service чтобы удалить сотрудника.
Данная статья использует  Restful Web Service созданные из следующего примера:
Класс  RestTemplate является центральным классом в  Spring Framework для синхронических вызовов (synchronous calls) сделанных с помощью  Client для доступа к  RESTful Web Service. Данный класс предоставляет функции для легкого потребления  REST Services. При использовании вышеупомянутого класса, пользователь должен предоставить  URL, параметры (если есть) и извлечь полученные результаты. RestTemplate контролирует соединения  HTTP (HTTP Connection).

2- Создать Spring Boot project

На  Eclipse, создать  Spring Boot project.
OK, project создан.

3- Конфигурация pom.xml

Данный Project должен использовать библиотеки  Spring Restful Client. Поэтому у вас есть 2 выбора:
  1. spring-boot-starter-web
  2. spring-boot-starter-data-rest

spring-boot-starter-web

spring-boot-starter-web включает библиотеки для построения веб приложения используя  Spring MVC, и использовать  tomcat как  Web Container по умолчанию. Включает библиотеки для приложения  RESTful.
spring-boot-starter-web
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring-boot-starter-data-rest

spring-boot-starter-data-rest включает библиотеки для работы с  Spring RESTful.
spring-boot-starter-data-rest
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-rest -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-rest</artifactId>            
</dependency>

Java <==> JSON

Оба  "Starter" выше содержат библиотеку  jackson-databind, поддерживающую конвертацию объекта Java в JSON и наоборот.

Java <==> XML

Spring использует  JAXB (готовый в JDK) для конвертации объекта  Java в  XML и наоборот. Но классы Java должны быть аннотированы (annotate) с помощью @XmlRootElement,... Поэтому мой совет это вам стоит использовать  jackson-dataformat-xml как библиотеку для конвертации  XML и Java. Чтобы использовать  jackson-dataformat-xml вам нужно его объявить в файле  pom.xml:
jackson-dataformat-xml
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>
OK, у вас есть 2 выбора для объявления в pom.xml:
** pom.xml (Option 1) **
<dependencies>
     ......

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>            
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>
    
        .....
</dependencies>
** pom.xml (Option 2) **
<dependencies>
     ......

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>            
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>
    
        .....
</dependencies>
Необходимая библиотека  Apache Commons Codec для кодирования (encode) username/password, в случае если вы используете  Rest Client чтобы иметь доступ к ресурсам защищенным с помощью  Basic Authentication.
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
</dependency>
Полное содержание файла  pom.xml:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.o7planning</groupId>
    <artifactId>SpringBootRestfulClient</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootRestfulClient</name>
    <description>Spring Boot + Restful Client</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>            
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4- GET - getForObject

Использовать метод  getForObject чтобы отправить запрос (request) к  Restful Service, и получить возвращенные данные. Ниже являются самые простые примеры, возвращенные данные являются String.
SimplestGetExample.java
package org.o7planning.sbrestfulclient.get;

import org.springframework.web.client.RestTemplate;

public class SimplestGetExample {

	static final String URL_EMPLOYEES = "http://localhost:8080/employees";

	static final String URL_EMPLOYEES_XML = "http://localhost:8080/employees.xml";
	static final String URL_EMPLOYEES_JSON = "http://localhost:8080/employees.json";

	public static void main(String[] args) {

		RestTemplate restTemplate = new RestTemplate();

		// Send request with GET method and default Headers.
		String result = restTemplate.getForObject(URL_EMPLOYEES, String.class);

		System.out.println(result);
	}

}
Запросы отправленные к  Restful Service должны кастомизировать информацию  Headers чтобы сказать  Restful Service вид формата данных, который вы хотите получить ( JSON, XML, ...)
GetWithHeaderExample.java
package org.o7planning.sbrestfulclient.get;

import java.util.Arrays;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class GetWithHeaderExample {

	static final String URL_EMPLOYEES = "http://localhost:8080/employees";

	public static void main(String[] args) {

		// HttpHeaders
		HttpHeaders headers = new HttpHeaders();

		headers.setAccept(Arrays.asList(new MediaType[] { MediaType.APPLICATION_JSON }));
		// Request to return JSON format
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.set("my_other_key", "my_other_value");

		// HttpEntity<String>: To get result as String.
		HttpEntity<String> entity = new HttpEntity<String>(headers);

		// RestTemplate
		RestTemplate restTemplate = new RestTemplate();

		// Send request with GET method, and Headers.
		ResponseEntity<String> response = restTemplate.exchange(URL_EMPLOYEES, //
				HttpMethod.GET, entity, String.class);

		String result = response.getBody();

		System.out.println(result);
	}

}
Данные возвращенные от  Restful Serivce имеют формат  XML или  JSON, которые могут быть конвертированы (Convert) автоматически в объект Java.
Employee.java
package org.o7planning.sbrestfulclient.model;

public class Employee {

    private String empNo;
    private String empName;
    private String position;

    public Employee() {

    }

    public Employee(String empNo, String empName, String position) {
        this.empNo = empNo;
        this.empName = empName;
        this.position = position;
    }

    public String getEmpNo() {
        return empNo;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

}
SimplestGetPOJOExample.java
package org.o7planning.sbrestfulclient.get;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.web.client.RestTemplate;

public class SimplestGetPOJOExample {

	static final String URL_EMPLOYEES = "http://localhost:8080/employees";

	static final String URL_EMPLOYEES_XML = "http://localhost:8080/employees.xml";
	static final String URL_EMPLOYEES_JSON = "http://localhost:8080/employees.json";

	public static void main(String[] args) {

		RestTemplate restTemplate = new RestTemplate();

		// Send request with GET method and default Headers.
		Employee[] list = restTemplate.getForObject(URL_EMPLOYEES, Employee[].class);

		if (list != null) {
			for (Employee e : list) {
				System.out.println("Employee: " + e.getEmpNo() + " - " + e.getEmpName());
			}
		}

	}

}

5- GET - exchange

Использование метода  exchange также поможет вам отправить request к  Restful Service, возвращенный результат это объект  ResponseEntity, данный объект содержит много иноформации заслуживающего внимания, как  HttpStatus,...
GetPOJOWithHeaderExample.java
package org.o7planning.sbrestfulclient.get;

import java.util.Arrays;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class GetPOJOWithHeaderExample {

	static final String URL_EMPLOYEES = "http://localhost:8080/employees";

	public static void main(String[] args) {

		// HttpHeaders
		HttpHeaders headers = new HttpHeaders();

		headers.setAccept(Arrays.asList(new MediaType[] { MediaType.APPLICATION_XML }));
		// Request to return XML format
		headers.setContentType(MediaType.APPLICATION_XML);
		headers.set("my_other_key", "my_other_value");

		// HttpEntity<Employee[]>: To get result as Employee[].
		HttpEntity<Employee[]> entity = new HttpEntity<Employee[]>(headers);

		// RestTemplate
		RestTemplate restTemplate = new RestTemplate();

		// Send request with GET method, and Headers.
		ResponseEntity<Employee[]> response = restTemplate.exchange(URL_EMPLOYEES, //
				HttpMethod.GET, entity, Employee[].class);

		HttpStatus statusCode = response.getStatusCode();
		System.out.println("Response Satus Code: " + statusCode);

		// Status Code: 200
		if (statusCode == HttpStatus.OK) {
			// Response Body Data
			Employee[] list = response.getBody();

			if (list != null) {
				for (Employee e : list) {
					System.out.println("Employee: " + e.getEmpNo() + " - " + e.getEmpName());
				}
			}
		}

	}

}

6- GET - Basic Authentication

Для ресурсов данных (resource) защищенных с помощью  Basic Authentication, запросы (request) которые вы отправляете на  REST Service должны прикреплять  username/password. Информация  username/password должна быть кодирована (encode) используя алгоритм  Base64 перед тем как прикреплять с request.
Смотрите так же:
GetWithBasicAuthExample.java
package org.o7planning.sbrestfulclient.get;

import java.nio.charset.Charset;
import java.util.Arrays;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.apache.commons.codec.binary.Base64;

public class GetWithBasicAuthExample {

	public static final String USER_NAME = "tom";
	public static final String PASSWORD = "123";

	static final String URL_EMPLOYEES = "http://localhost:8080/employees";

	public static void main(String[] args) {

		// HttpHeaders
		HttpHeaders headers = new HttpHeaders();

		// 
		// Authentication
		// 
		String auth = USER_NAME + ":" + PASSWORD;
		byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
		String authHeader = "Basic " + new String(encodedAuth);
		headers.set("Authorization", authHeader);
		// 
		headers.setAccept(Arrays.asList(new MediaType[] { MediaType.APPLICATION_JSON }));
		// Request to return JSON format
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.set("my_other_key", "my_other_value");

		// HttpEntity<String>: To get result as String.
		HttpEntity<String> entity = new HttpEntity<String>(headers);

		// RestTemplate
		RestTemplate restTemplate = new RestTemplate();

		// Send request with GET method, and Headers.
		ResponseEntity<String> response = restTemplate.exchange(URL_EMPLOYEES, //
				HttpMethod.GET, entity, String.class);

		String result = response.getBody();

		System.out.println(result);
	}

}

7- POST - postForObject

Метод  postForObject используется для отправки request к  Restful Service чтобы создать ресурс данных (resource), одновременно возвращает только что созданные ресурсы данных.
Post_postForObject_Example.java
package org.o7planning.sbrestfulclient.post;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;

public class Post_postForObject_Example {

   static final String URL_CREATE_EMPLOYEE = "http://localhost:8080/employee";

   public static void main(String[] args) {

      String empNo = "E11";

      Employee newEmployee = new Employee(empNo, "Tom", "Cleck");

      HttpHeaders headers = new HttpHeaders();
      headers.add("Accept", MediaType.APPLICATION_XML_VALUE);
      headers.setContentType(MediaType.APPLICATION_XML);

      RestTemplate restTemplate = new RestTemplate();

      // Data attached to the request.
      HttpEntity<Employee> requestBody = new HttpEntity<>(newEmployee, headers);

      // Send request with POST method.
      Employee e = restTemplate.postForObject(URL_CREATE_EMPLOYEE, requestBody, Employee.class);

      if (e != null && e.getEmpNo() != null) {

         System.out.println("Employee created: " + e.getEmpNo());
      } else {
         System.out.println("Something error!");
      }

   }

}

8- POST - postForEntity

Метод  postForEntity использованные для отправления request к  Restful Service чтобы создать ресурс данных (resource). Данный метод возвращает объект  ResponseEntity, этот объект содержит только что созданный ресурс данных, и другую важную информацию, например  HttpStatus, ...
Post_postForEntity_Example.java
package org.o7planning.sbrestfulclient.post;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class Post_postForEntity_Example {

	static final String URL_CREATE_EMPLOYEE = "http://localhost:8080/employee";

	public static void main(String[] args) {

		Employee newEmployee = new Employee("E11", "Tom", "Cleck");

		RestTemplate restTemplate = new RestTemplate();

		// Data attached to the request.
		HttpEntity<Employee> requestBody = new HttpEntity<>(newEmployee);

		// Send request with POST method.
		ResponseEntity<Employee> result 
		     = restTemplate.postForEntity(URL_CREATE_EMPLOYEE, requestBody, Employee.class);

		System.out.println("Status code:" + result.getStatusCode());

		// Code = 200.
		if (result.getStatusCode() == HttpStatus.OK) {
			Employee e = result.getBody();
			System.out.println("(Client Side) Employee Created: "+ e.getEmpNo());
		}

	}

}

9- PUT - Простой пример

Метод  put класса  RestTemplate используется для отправления request к  Restful Service чтобы поменять ресурс данных (resource). Данный метод ничего не возвращает.
PutSimpleExample.java
package org.o7planning.sbrestfulclient.put;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;

public class PutSimpleExample {

	static final String URL_UPDATE_EMPLOYEE = "http://localhost:8080/employee";
	static final String URL_EMPLOYEE_PREFIX = "http://localhost:8080/employee";

	public static void main(String[] args) {

		String empNo = "E01";

		Employee updateInfo = new Employee(empNo, "Tom", "Cleck");

		HttpHeaders headers = new HttpHeaders();
		headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);

		RestTemplate restTemplate = new RestTemplate();

		// Data attached to the request.
		HttpEntity<Employee> requestBody = new HttpEntity<>(updateInfo, headers);

		// Send request with PUT method.
		restTemplate.put(URL_UPDATE_EMPLOYEE, requestBody, new Object[] {});

		String resourceUrl = URL_EMPLOYEE_PREFIX + "/" + empNo;

		Employee e = restTemplate.getForObject(resourceUrl, Employee.class);

		if (e != null) {
			System.out.println("(Client side) Employee after update: ");
			System.out.println("Employee: " + e.getEmpNo() + " - " + e.getEmpName());
		}
	}

}

10- PUT - exchange

Пример использования метода  exchange класса  RestTemplate для отправления request к Restful Service чтобы поменять ресурс данных.
PutWithExchangeExample.java
package org.o7planning.sbrestfulclient.put;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;

public class PutWithExchangeExample {

	static final String URL_UPDATE_EMPLOYEE = "http://localhost:8080/employee";
	static final String URL_EMPLOYEE_PREFIX = "http://localhost:8080/employee";

	public static void main(String[] args) {

		String empNo = "E01";

		Employee updateInfo = new Employee(empNo, "Tom", "Cleck");

		HttpHeaders headers = new HttpHeaders();
		headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);

		RestTemplate restTemplate = new RestTemplate();

		// Data attached to the request.
		HttpEntity<Employee> requestBody = new HttpEntity<>(updateInfo, headers);

		// Send request with PUT method.
		restTemplate.exchange(URL_UPDATE_EMPLOYEE, HttpMethod.PUT, requestBody, Void.class);

		String resourceUrl = URL_EMPLOYEE_PREFIX + "/" + empNo;

		Employee e = restTemplate.getForObject(resourceUrl, Employee.class);

		if (e != null) {
			System.out.println("(Client side) Employee after update: ");
			System.out.println("Employee: " + e.getEmpNo() + " - " + e.getEmpName());
		}
	}

}

11- DELELE

Использовать метод  delete класса  RestTemplate чтобы отправить request к  Restful Service для удаления ресурса данных.
DeleteSimpleExample.java
package org.o7planning.sbrestfulclient.delete;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.web.client.RestTemplate;

public class DeleteSimpleExample {

	public static void main(String[] args) {

		RestTemplate restTemplate = new RestTemplate();

		// empNo="E01"
		String resourceUrl = "http://localhost:8080/employee/E01";

		// Send request with DELETE method.
		restTemplate.delete(resourceUrl);

		// Get 
		Employee e = restTemplate.getForObject(resourceUrl, Employee.class);

		if (e != null) {
			System.out.println("(Client side) Employee after delete: ");
			System.out.println("Employee: " + e.getEmpNo() + " - " + e.getEmpName());
		} else {
			System.out.println("Employee not found!");
		}
	}

}
DeleteExample2.java
package org.o7planning.sbrestfulclient.delete;

import org.o7planning.sbrestfulclient.model.Employee;
import org.springframework.web.client.RestTemplate;

public class DeleteExample2 {

   public static void main(String[] args) {

      RestTemplate restTemplate = new RestTemplate();

      // URL with URI-variable
      String resourceUrl = "http://localhost:8080/employee/{empNo}";

      Object[] uriValues = new Object[] { "E01" };

      // Send request with DELETE method.
      restTemplate.delete(resourceUrl, uriValues);

      Employee e = restTemplate.getForObject(resourceUrl, Employee.class);

      if (e != null) {
         System.out.println("(Client side) Employee after delete: ");
         System.out.println("Employee: " + e.getEmpNo() + " - " + e.getEmpName());
      } else {
         System.out.println("Employee not found!");
      }
   }

}