1. введение
В этом кратком руководстве мы проиллюстрируем, как использовать RestTemplate Spring для отправки запросов POST, отправляющих содержимое JSON.
Дальнейшее чтение:
Изучение тестовой панели Spring Boot TestRestTemplate
Обработка ошибок пружинной пластины
2. Настройка примера
Давайте начнем с добавления простого класса Person model для представления данных, подлежащих публикации:
public class Person { private Integer id; private String name; // standard constructor, getters, setters }
Для работы с объектами Person мы добавим интерфейс Person Service и реализацию с двумя методами:
public interface PersonService { public Person saveUpdatePerson(Person person); public Person findPersonById(Integer id); }
Реализация этих методов просто вернет объект. Здесь мы используем фиктивную реализацию этого слоя, чтобы сосредоточиться на веб-слое.
3. Настройка REST API
Давайте определим простой REST API для нашего класса Person :
@PostMapping( value = "/createPerson", consumes = "application/json", produces = "application/json") public Person createPerson(@RequestBody Person person) { return personService.saveUpdatePerson(person); } @PostMapping( value = "/updatePerson", consumes = "application/json", produces = "application/json") public Person updatePerson(@RequestBody Person person, HttpServletResponse response) { response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath() .path("/findPerson/" + person.getId()).toUriString()); return personService.saveUpdatePerson(person); }
Помните, что мы хотим опубликовать данные в формате JSON. Для этого мы добавили атрибут consumers в аннотацию @PostMapping со значением “application/json” для обоих методов.
Аналогично, мы устанавливаем атрибут products в “application/json”, чтобы сообщить Spring, что нам нужно тело ответа в формате JSON.
Мы аннотировали параметр person аннотацией @RequestBody для обоих методов. Это сообщит Spring, что объект person будет привязан к телу запроса HTTP .
Наконец, оба метода возвращают объект Person , который будет привязан к телу ответа. Заметим, что мы будем аннотировать наш класс API с помощью @RestController , чтобы аннотировать все методы API скрытой аннотацией @ResponseBody .
4. Использование RestTemplate
Теперь мы можем написать несколько модульных тестов для тестирования нашего Person REST API. Здесь мы попытаемся отправить запросы POST в Person API, используя методы POST, предоставляемые RestTemplate : postForObject , postForEntity и postForLocation .
Прежде чем мы начнем реализовывать наши модульные тесты, давайте определим метод настройки для инициализации объектов, которые мы будем использовать во всех наших методах модульного тестирования:
@BeforeClass public static void runBeforeAllTestMethods() { createPersonUrl = "http://localhost:8082/spring-rest/createPerson"; updatePersonUrl = "http://localhost:8082/spring-rest/updatePerson"; restTemplate = new RestTemplate(); headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); personJsonObject = new JSONObject(); personJsonObject.put("id", 1); personJsonObject.put("name", "John"); }
Помимо этого метода настройки, обратите внимание, что мы будем ссылаться на следующий картограф, чтобы преобразовать строку JSON в объект JsonNode в наших модульных тестах:
private final ObjectMapper objectMapper = new ObjectMapper();
Как уже упоминалось ранее, мы хотим опубликовать данные в формате JSON. Для этого мы добавим в наш запрос заголовок Content-Type с типом носителя APPLICATION_JSON .
Класс Http Headers Spring предоставляет различные методы для доступа к заголовкам. Здесь мы устанавливаем заголовок Content-Type в application/json , вызывая метод setContentType . Мы прикрепим объект headers к нашим запросам.
4.1. Публикация JSON С Помощью postForObject
Метод RestTemplate ‘s postForObject создает новый ресурс, отправляя объект в заданный шаблон URI. Он возвращает результат, автоматически преобразованный в тип, указанный в параметре responseType .
Допустим, мы хотим сделать запрос POST к нашему Person API для создания нового Person объекта и вернуть этот вновь созданный объект в ответе.
Сначала мы построим объект request типа HttpEntity на основе person JSONObject и заголовков, содержащих Content-Type . Это позволяет методу postForObject отправлять тело запроса JSON:
@Test public void givenDataIsJson_whenDataIsPostedByPostForObject_thenResponseBodyIsNotNull() throws IOException { HttpEntityrequest = new HttpEntity (personJsonObject.toString(), headers); String personResultAsJsonStr = restTemplate.postForObject(createPersonUrl, request, String.class); JsonNode root = objectMapper.readTree(personResultAsJsonStr); assertNotNull(personResultAsJsonStr); assertNotNull(root); assertNotNull(root.path("name").asText()); }
Метод postForObject() возвращает тело ответа в виде типа String .
Мы также можем вернуть ответ в виде Person object, установив параметр responseType :
Person person = restTemplate.postForObject(createPersonUrl, request, Person.class); assertNotNull(person); assertNotNull(person.getName());
На самом деле, наш метод обработчика запросов, совпадающий с URL-адресом create Person URL, создает тело ответа в формате JSON.
Но это не является ограничением для нас — postForObject способен автоматически преобразовывать тело ответа в запрошенный тип Java (например, String , Person ), указанный в параметре responseType .
4.2. Размещение JSON С postForEntity
По сравнению с postForObject() , postForEntity() возвращает ответ в виде ResponseEntity объекта. Кроме этого, оба метода выполняют одну и ту же работу.
Допустим, мы хотим сделать запрос POST к нашему Person API, чтобы создать новый Person объект и вернуть ответ в виде ResponseEntity .
Мы можем использовать метод postForEntity для реализации этого:
@Test public void givenDataIsJson_whenDataIsPostedByPostForEntity_thenResponseBodyIsNotNull() throws IOException { HttpEntityrequest = new HttpEntity (personJsonObject.toString(), headers); ResponseEntity responseEntityStr = restTemplate. postForEntity(createPersonUrl, request, String.class); JsonNode root = objectMapper.readTree(responseEntityStr.getBody()); assertNotNull(responseEntityStr.getBody()); assertNotNull(root.path("name").asText()); }
Аналогично postForObject , postForEntity имеет параметр responseType для преобразования тела ответа в запрошенный тип Java.
Здесь мы смогли вернуть тело ответа в виде ResponseEntity .
Мы также можем вернуть ответ в виде объекта ResponseEntity , установив параметр responseType в Person.class :
ResponseEntityresponseEntityPerson = restTemplate. postForEntity(createPersonUrl, request, Person.class); assertNotNull(responseEntityPerson.getBody()); assertNotNull(responseEntityPerson.getBody().getName());
4.3. Размещение JSON С Помощью postForLocation
Аналогично методам postForObject и postForEntity , postForLocation также создает новый ресурс, отправляя данный объект в данный URI. Единственное отличие заключается в том, что он возвращает значение заголовка Location .
Помните, мы уже видели, как установить заголовок Location ответа в нашем методе updatePerson REST API выше:
response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath() .path("/findPerson/" + person.getId()).toUriString());
Теперь давайте представим, что мы хотим вернуть заголовок Location ответа после обновления объекта person , который мы опубликовали.
Мы можем реализовать это с помощью метода postForLocation :
@Test public void givenDataIsJson_whenDataIsPostedByPostForLocation_thenResponseBodyIsTheLocationHeader() throws JsonProcessingException { HttpEntityrequest = new HttpEntity (personJsonObject.toString(), headers); URI locationHeader = restTemplate.postForLocation(updatePersonUrl, request); assertNotNull(locationHeader); }
5. Заключение
В этой статье мы рассмотрели, как использовать RestTemplate для выполнения запроса POST с помощью JSON.
Как всегда, все примеры и фрагменты кода можно найти на GitHub .