Как принять post запрос на java
Перейти к содержимому

Как принять post запрос на java

  • автор:

Публикация с помощью Java HttpClient

API Java HttpClient был представлен в Java 11. API реализует клиентскую часть самых последних стандартов HTTP . Он поддерживает HTTP/1.1 и HTTP/2, как синхронную, так и асинхронную модели программирования.

Мы можем использовать его для отправки HTTP-запросов и получения их ответов. До Java 11 нам приходилось полагаться на элементарную реализацию URLConnection или сторонние библиотеки, такие как Apache HttpClient .

В этом руководстве мы рассмотрим отправку POST-запросов с помощью Java HttpClient . Мы покажем, как отправлять как синхронные, так и асинхронные запросы POST, а также параллельные запросы POST. Кроме того, мы проверим, как добавлять параметры аутентификации и тела JSON в запросы POST.

Наконец, мы увидим, как загружать файлы и отправлять данные формы. Поэтому мы рассмотрим большинство распространенных вариантов использования.

2. Подготовка POST-запроса​

Прежде чем мы сможем отправить HTTP-запрос, нам сначала нужно создать экземпляр HttpClient .

Экземпляры HttpClient можно настроить и создать из его построителя с помощью метода newBuilder . В противном случае, если настройка не требуется, мы можем использовать метод утилиты newHttpClient для создания клиента по умолчанию:

 HttpClient client = HttpClient.newHttpClient(); 

HttpClient будет использовать HTTP/2 по умолчанию. Он также автоматически понизится до HTTP/1.1, если сервер не поддерживает HTTP/2.

Теперь мы готовы создать экземпляр HttpRequest из его построителя. Позже мы воспользуемся экземпляром клиента для отправки этого запроса. Минимальные параметры для POST-запроса — это URL-адрес сервера, метод запроса и тело:

 HttpRequest request = HttpRequest.newBuilder()   .uri(URI.create(serviceUrl))   .POST(HttpRequest.BodyPublishers.noBody())   .build(); 

Тело запроса должно быть предоставлено через класс BodyPublisher . Это издатель реактивного потока, который публикует потоки тела запроса по запросу. В нашем примере мы использовали публикатор тела, который не отправляет тело запроса.

3. Отправка POST-запроса​

Теперь, когда мы подготовили запрос POST, давайте рассмотрим различные варианты его отправки.

3.1. Синхронно​

Мы можем отправить подготовленный запрос, используя этот метод отправки по умолчанию. Этот метод заблокирует наш код до тех пор, пока не будет получен ответ :

 HttpResponseString> response = client.send(request, HttpResponse.BodyHandlers.ofString()) 

Утилита BodyHandlers реализует различные полезные обработчики, такие как обработка тела ответа как строки или потоковая передача тела ответа в файл. После получения ответа объект HttpResponse будет содержать статус ответа, заголовки и тело:

 assertThat(response.statusCode())   .isEqualTo(200);   assertThat(response.body())   .isEqualTo(""); 

3.2. Асинхронно​

Мы могли бы отправить тот же запрос из предыдущего примера асинхронно, используя метод sendAsync . Вместо того, чтобы блокировать наш код, этот метод сразу вернет экземпляр CompletableFuture : ****

 CompletableFutureHttpResponseString>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); 

CompletableFuture завершается с HttpResponse , как только он становится доступным:

 HttpResponseString> response = futureResponse.get();   assertThat(response.statusCode()).isEqualTo(200);   assertThat(response.body()).isEqualTo(""); 

3.3. Одновременно​

Мы можем комбинировать Streams с CompletableFutures , чтобы выдавать несколько запросов одновременно и ждать их ответов :

 ListCompletableFutureHttpResponseString>>> completableFutures = serviceUrls.stream()   .map(URI::create)   .map(HttpRequest::newBuilder)   .map(builder -> builder.POST(HttpRequest.BodyPublishers.noBody()))   .map(HttpRequest.Builder::build)   .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))   .collect(Collectors.toList()); 

Теперь давайте дождемся завершения всех запросов, чтобы мы могли обработать их ответы сразу:

 CompletableFutureListHttpResponseString>>> combinedFutures = CompletableFuture   .allOf(completableFutures.toArray(new CompletableFuture[0]))   .thenApply(future ->   completableFutures.stream()   .map(CompletableFuture::join)   .collect(Collectors.toList())); 

Поскольку мы объединили все ответы, используя методы allOf и join , мы получили новый CompletableFuture , который содержит наши ответы:

 ListHttpResponseString>> responses = combinedFutures.get();  responses.forEach((response) ->    assertThat(response.statusCode()).isEqualTo(200);   assertThat(response.body()).isEqualTo("");   >); 

4. Добавление параметров аутентификации​

Мы можем установить аутентификатор на уровне клиента для HTTP-аутентификации для всех запросов :

 HttpClient client = HttpClient.newBuilder()   .authenticator(new Authenticator()    @Override   protected PasswordAuthentication getPasswordAuthentication()    return new PasswordAuthentication(   "foreach",   "123456".toCharArray());   >   >)   .build(); 

Однако HttpClient не отправляет базовые учетные данные, пока не будет запрошен для них с заголовком WWW-Authenticate с сервера.

Чтобы обойти это, мы всегда можем создать и отправить основной заголовок авторизации вручную:

 HttpRequest request = HttpRequest.newBuilder()   .uri(URI.create(serviceUrl))   .POST(HttpRequest.BodyPublishers.noBody())   .header("Authorization", "Basic " +   Base64.getEncoder().encodeToString(("foreach:123456").getBytes()))   .build(); 

5. Добавление тела​

В примерах до сих пор мы не добавляли никаких тел к нашим POST-запросам. Однако метод POST обычно используется для отправки данных на сервер через тело запроса .

5.1. JSON-текст​

Утилита BodyPublishers реализует различные полезные средства публикации, такие как публикация тела запроса из строки или файла. Мы можем опубликовать данные JSON как String , преобразованные с использованием набора символов UTF-8:

 HttpRequest request = HttpRequest.newBuilder()   .uri(URI.create(serviceUrl))   .POST(HttpRequest.BodyPublishers.ofString(""))   .build(); 

5.2. Загрузка файлов​

Давайте создадим временный файл , который мы можем использовать для загрузки через HttpClient :

 Path file = tempDir.resolve("temp.txt");   ListString> lines = Arrays.asList("1", "2", "3");   Files.write(file, lines); 

HttpClient предоставляет отдельный метод BodyPublishers.ofFile для добавления файла в тело POST . Мы можем просто добавить наш временный файл в качестве параметра метода, а API позаботится об остальном:

 HttpRequest request = HttpRequest.newBuilder()   .uri(URI.create(serviceUrl))   .POST(HttpRequest.BodyPublishers.ofFile(file))   .build(); 

5.3. Отправка форм​

В отличие от файлов, HttpClient не предоставляет отдельного метода для публикации данных формы. Поэтому нам снова нужно использовать метод BodyPublishers.ofString :

 MapString, String> formData = new HashMap>();  formData.put("username", "foreach");  formData.put("message", "hello");    HttpRequest request = HttpRequest.newBuilder()   .uri(URI.create(serviceUrl))   .POST(HttpRequest.BodyPublishers.ofString(getFormDataAsString(formData)))   .build(); 

Однако нам нужно преобразовать данные формы из Map в String , используя пользовательскую реализацию:

 private static String getFormDataAsString(MapString, String> formData)    StringBuilder formBodyBuilder = new StringBuilder();   for (Map.EntryString, String> singleEntry : formData.entrySet())    if (formBodyBuilder.length() > 0)    formBodyBuilder.append("&");   >   formBodyBuilder.append(URLEncoder.encode(singleEntry.getKey(), StandardCharsets.UTF_8));   formBodyBuilder.append("=");   formBodyBuilder.append(URLEncoder.encode(singleEntry.getValue(), StandardCharsets.UTF_8));   >   return formBodyBuilder.toString();   > 

6. Заключение​

В этой статье мы рассмотрели отправку POST-запросов с использованием Java HttpClient API, представленного в Java 11 .

Мы узнали, как создать экземпляр HttpClient и подготовить POST-запрос. Мы увидели, как отправлять подготовленные запросы синхронно, асинхронно и параллельно. Далее мы также увидели, как добавить основные параметры аутентификации.

Наконец, мы рассмотрели добавление тела к запросу POST. Мы рассмотрели полезные нагрузки JSON, загрузку файлов и отправку данных формы.

Как всегда, полный исходный код доступен на GitHub .

  • 1. Обзор
  • 2. Подготовка POST-запроса
  • 3. Отправка POST-запроса
    • 3.1. Синхронно
    • 3.2. Асинхронно
    • 3.3. Одновременно
    • 5.1. JSON-текст
    • 5.2. Загрузка файлов
    • 5.3. Отправка форм

    Как отправить post запрос java

    Вот пример кода, который отправляет POST-запрос на сервер и выводит ответ:

    import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; public class HttpPostRequest  public static void main(String[] args)  try  // Создаем URL-адрес для запроса URL url = new URL("http://www.example.com/api"); // Создаем объект HttpURLConnection и настраиваем его HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); // Создаем тело запроса String body = "param1=value1¶m2=value2"; // Записываем тело запроса в поток вывода OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); writer.write(body); writer.flush(); // Считываем ответ от сервера BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; StringBuilder response = new StringBuilder(); while ((line = reader.readLine()) != null)  response.append(line); > reader.close(); // Выводим ответ от сервера System.out.println(response.toString()); > catch (Exception e)  e.printStackTrace(); > > > 
    • Здесь мы создаем объект HttpURLConnection и настраиваем его для отправки POST-запроса
    • Затем мы записываем тело запроса в поток вывода и считываем ответ от сервера с помощью BufferedReader
    • В конце мы выводим ответ от сервера на экран.

    Обратите внимание, что в примере мы отправляем запрос с параметрами param1 и param2 , но вы можете изменить их на свои параметры в зависимости от вашего запроса.

    Добавление записи через POST-запрос в Spring Boot

    В статье Работа с БД в Spring Boot на примере postgresql мы узнали как читать данные из БД. Но чтение данных – это лишь малая часть всех операций, которые встречаются в типичном java-приложении. Теперь попробуем создать полноценный rest-интерфейс для добавления новых записей, их модификации и удаления.

    За основу возьмём наше приложение из указанной статьи. Оно состоит из трёх слоёв: работа с БД (repository), бизнес-логика приложения (service) и сам rest-интерфейс (controller), который обрабатывает входящий json и генерирует исходящий.

    Репозиторий

    Начнём с доработки репозитория (интерфейс ProfileRepository), где до сих пор был только один метод чтения данных. Добавим метод вставки записи в БД:

    void insertProfile(String firstName, String secondName, int age);

    При добавлении новой записи нам достаточно всего три поля. id будет сгенерирован в БД автоматически.

    В реализацию интерфейса ProfileRepositoryImpl добавляем sql-запросы в виде констант, которые принято размещать в начале класса:

    private static final String SQL_INSERT_PROFILE =
    «insert into profile (first_name, last_name, age) values (:firstName, :lastName, :age)» ;

    Имена параметров, которые мы будем подставлять в sql-запрос, начинаются с двоеточия.

    Вот реализация добавления записи в БД:

    @Override
    public void insertProfile(String firstName, String lastName, int age) var params = new MapSqlParameterSource();
    params.addValue( «firstName» , firstName);
    params.addValue( «lastName» , lastName);
    params.addValue( «age» , age);
    jdbcTemplate.update( SQL_INSERT_PROFILE , params);
    >

    Всё предельно просто: сначала собираем параметры, затем передаём их вместе с запросом в метод jdbcTemplate.update(), который вопреки своему названию отвечает вообще за любые изменения данных (и insert, и update, и delete). Обратите внимание, что jdbcTemplate у нас имеет тип NamedParameterJdbcTemplate – именно он позволяет использовать именованные параметры. Иначе пришлось бы писать знаки вопроса.

    Сервисный слой

    Перейдём к сервисному слою. Интерфейс ProfileService не отличается оригинальностью:

    void createProfile(String firstName, String secondName, int age);

    Его реализация в ProfileServiceImpl. Здесь по сути только вызываем метод репозитория:

    @Override
    public void createProfile(String firstName, String secondName, int age) profileRepository.insertProfile(firstName, secondName, age);
    >

    Контроллер

    Согласно архитектуре restful-сервисов, чтение данных мы делаем при помощи GET-запросов, а создание – при помощи POST. Также хотелось бы отметить, что у GET-запроса не может быть тела запроса (body), все его параметры перечисляются в строке запроса. А POST-запрос может иметь тело, в которое мы будем помещать целевой json.

    Сперва нам нужно добавить в проект ещё одну зависимость spring-boot-starter-validation, которая позволяет валидировать входящие запросы:


    org.springframework.boot
    spring-boot-starter-validation

    Перейдём к нашему контроллеру ProfileController и добавим в него метод создания профиля.

    @PostMapping
    @ResponseStatus (HttpStatus. CREATED )
    public void createProfile( @Valid @RequestBody ProfileRequest request) profileService.createProfile(
    request.firstName(),
    request.lastName(),
    request.age()
    );
    >

    В качестве аргумента метод принимает объект ProfileRequest, реализованный как record-class:

    public record ProfileRequest(
    @NotNull
    String firstName,
    @NotNull
    String lastName,
    @NotNull
    @Min ( 1 )
    Integer age
    ) >

    Эта модель представляет собой ровно тот объект, который мы ожидаем в теле запроса. Имена полей в json должны совпадать с именами полей в классе (при желании это можно переопределить дополнительной аннотацией). Дополнительно накладываем ограничения из пакета javax.validation.constraints на каждое поле.

    Аннотация @NotNull применима для ссылочных типов и означает обязательность этого поля в запросе. Обратите внимание, что тут мы специально используем ссылочный Integer, который допускает null, а не примитивный int, который по умолчанию равен нулю. Ссылочный числовой тип вместе с @NotNull позволяет проверять обязательность числовых типов.

    Аннотация @Min говорит сама за себя и ограничивает числовые типы снизу. Тем самым мы никогда не допустим, чтобы нам передали отрицательное число в качестве возраста.

    Чтобы эти проверки работали для входящего json, параметр метода надо снабдить аннотацией @Valid, а чтобы именно в этот класс был преобразован входящий json, также добавляем @RequestBody. Внутри просто вызываем сервисный слой.

    Аннотация @PostMapping указывает на то, что это обработчик POST-запроса. В скобках можно указать относительный урл, но в данном случае мы его не указали, поэтому запрос надо будет кидать по тому адресу, который указан на уровне контроллера, то есть /profiles. @ResponseStatus показывает, какой http-код нужно вернуть в ответ. В данном случае мы опять следуем rest-соглашениям и возвращаем код 201 – «Created».

    Теперь мы готовы к тому, чтобы выполнить rest-запрос на создание новой записи в БД. Запускаем приложение и отравляем указанный POST-запрос по адресу http://127.0.0.1:8080/profiles. В http-заголовках обязательно указываем Content-Type: application/json.

    <
    «firstName» : «Петр» ,
    «lastName» : «Сидоров» ,
    «age» : 14
    >

    В ответ в случае успеха получаем http-статус 201. Если же мы попытаемся нарушить наши ограничения по полям, то получим json с подробным описанием ошибки.

    Таким образом, Spring Boot позволяет буквально за 5 минут создать полноценный обработчик POST-запроса с валидацией входящих параметров.

    В следующей статье Обновление записи через PUT-запрос в Spring Boot рассмотрим как можно обновлять записи.

    Как принять POST запрос?

    Как принять POST запрос? Не понимаю как это сделать, нигде не нашёл. Например, нам отсылают данные с помощью API (передают ФИО и номер телефона), а как нам их принять, не совсем понимаю.

    Отслеживать
    задан 23 окт 2019 в 14:15
    1,375 1 1 золотой знак 19 19 серебряных знаков 37 37 бронзовых знаков
    23 окт 2019 в 14:42
    @Bakhuss если оформите ответ, то я отмечу его как правильным.
    7 ноя 2019 в 13:34
    Благодарю, но там только ссылка на гайд, которая гуглится на раз. 😉
    8 ноя 2019 в 11:45

    1 ответ 1

    Сортировка: Сброс на вариант по умолчанию

    Для начала необходим UserRepo (необходим, чтобы программа понимала куда отправлять и с чем работает)

    public interface UserRepo extends CrudRepository

    Дальше Application (запуск нашего Spring)

    @SpringBootApplication public class Application < public static void main(String[] args) < SpringApplication.run(Application.class, args); >> 

    UserController (программа принимает и отправляет на преобразование данных вида Json)

    @RestController @RequestMapping("/users") //какое угодно слово может быть вместо users public class UserController < @Autowired private UserRepo userRepo; @PostMapping(consumes = ) public String createUser(@Valid @RequestBody User requestUserDetails) < userRepo.save(requestUserDetails); return "Сообщение доставлено."; >> 

    В заключении User (преобразовывает данные)

    @Entity @Table(name = "НАЗВАНИЕ БД", schema = "НАЗВАНИЕ СХЕМЫ") public class User < @Id private String phone; private String message; public String getPhone() < return phone; >public void setPhone(String phone) < this.phone = phone; >public String getMessage() < return message; >public void setLastName(String message) < this.message = message; >> 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *