[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-reactive-kak-rabotaet-webclient-i-chem-on-otlichaetsya-ot-resttemplate":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},1281,"kak-rabotaet-webclient-i-chem-on-otlichaetsya-ot-resttemplate",31,"reactive","Reactive","⚡","Как работает WebClient и чем он отличается от RestTemplate?","WebClient — неблокирующий, реактивный HTTP-клиент из Spring WebFlux, пришедший на замену блокирующему RestTemplate. Начиная со Spring 6.1, появился также RestClient — блокирующий клиент с fluent API.\n\n### Эволюция HTTP-клиентов в Spring\n\n| Клиент | Версия Spring | Модель | Статус в 2026 |\n|--------|--------------|--------|---------------|\n| RestTemplate | Spring 3 (2009) | Блокирующий | Maintenance mode |\n| WebClient | Spring 5 (2017) | Реактивный (неблокирующий) | Актуален |\n| RestClient | Spring 6.1 (2023) | Блокирующий, fluent API | Рекомендуемый для блокирующего кода |\n\n### WebClient — базовое использование\n\n```java\nWebClient webClient = WebClient.builder()\n    .baseUrl(\"https:\u002F\u002Fapi.example.com\")\n    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)\n    .build();\n\n\u002F\u002F GET — Mono\nMono\u003CUser> user = webClient.get()\n    .uri(\"\u002Fusers\u002F{id}\", 1)\n    .retrieve()\n    .bodyToMono(User.class);\n\n\u002F\u002F GET — Flux (список)\nFlux\u003CUser> users = webClient.get()\n    .uri(\"\u002Fusers\")\n    .retrieve()\n    .bodyToFlux(User.class);\n\n\u002F\u002F POST\nMono\u003CUser> created = webClient.post()\n    .uri(\"\u002Fusers\")\n    .bodyValue(new CreateUserRequest(\"John\", \"john@example.com\"))\n    .retrieve()\n    .bodyToMono(User.class);\n```\n\n\u003Cdetails>\u003Csummary>Обработка ошибок HTTP\u003C\u002Fsummary>\n\n```java\nMono\u003CUser> user = webClient.get()\n    .uri(\"\u002Fusers\u002F{id}\", userId)\n    .retrieve()\n    .onStatus(HttpStatusCode::is4xxClientError, response ->\n        response.bodyToMono(ErrorResponse.class)\n            .flatMap(error -> Mono.error(new ApiException(error.getMessage()))))\n    .onStatus(HttpStatusCode::is5xxServerError, response ->\n        Mono.error(new ServiceUnavailableException(\"Сервис недоступен\")))\n    .bodyToMono(User.class)\n    .retryWhen(Retry.backoff(3, Duration.ofSeconds(1))\n        .filter(e -> e instanceof ServiceUnavailableException));\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\u003Csummary>Таймауты и конфигурация\u003C\u002Fsummary>\n\n```java\nHttpClient httpClient = HttpClient.create()\n    .responseTimeout(Duration.ofSeconds(5))\n    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);\n\nWebClient webClient = WebClient.builder()\n    .baseUrl(\"https:\u002F\u002Fapi.example.com\")\n    .clientConnector(new ReactorClientHttpConnector(httpClient))\n    .filter(ExchangeFilterFunction.ofRequestProcessor(request -> {\n        log.info(\"Request: {} {}\", request.method(), request.url());\n        return Mono.just(request);\n    }))\n    .build();\n```\n\n\u003C\u002Fdetails>\n\n### RestClient (Spring 6.1+) — блокирующая альтернатива\n\n```java\nRestClient restClient = RestClient.builder()\n    .baseUrl(\"https:\u002F\u002Fapi.example.com\")\n    .build();\n\nUser user = restClient.get()\n    .uri(\"\u002Fusers\u002F{id}\", 1)\n    .retrieve()\n    .body(User.class);\n```\n\n### Сравнение\n\n| Критерий | RestTemplate | WebClient | RestClient |\n|----------|-------------|-----------|------------|\n| Блокирующий | Да | Нет | Да |\n| API стиль | Методы (getForObject) | Fluent chain | Fluent chain |\n| Streaming | Нет | Да | Нет |\n| Зависимость | spring-web | spring-webflux + reactor-netty | spring-web |\n| Тестирование | MockRestServiceServer | MockWebServer | MockRestServiceServer |\n\n### Частые ошибки\n\n- Создавать новый WebClient на каждый запрос — WebClient потокобезопасный, создавайте один раз\n- Вызывать `.block()` в реактивном контексте — deadlock; допустим только в блокирующем коде\n- Не обрабатывать HTTP-ошибки — без `onStatus` WebClient бросает неинформативное исключение\n- Использовать WebClient только потому, что RestTemplate deprecated — для блокирующего кода лучше RestClient\n\n### Как используется в 2026\n\n- RestClient — стандартный HTTP-клиент для Spring MVC (Spring 6.1+)\n- WebClient — для реактивных приложений (WebFlux) и streaming\n- RestTemplate встречается в legacy-коде\n- Spring HTTP Interface (`@HttpExchange`) работает и с WebClient, и с RestClient — декларативный стиль\n\n> **На собеседовании:** знайте три клиента (RestTemplate, WebClient, RestClient) и когда какой использовать. Частая ошибка — говорить «RestTemplate deprecated, используйте WebClient» без нюансов. RestTemplate в maintenance mode, но для блокирующего кода лучше RestClient, а не WebClient с .block().","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Как работает WebClient и чем он отличается от RestTemplate? — Gymterview","WebClient — неблокирующий, реактивный HTTP-клиент из Spring WebFlux, пришедший на замену блокирующему RestTemplate. Начиная со Spring 6.1, появился также RestCl","WebClient — неблокирующий, реактивный HTTP-клиент из Spring WebFlux, пришедший на замену блокирующему RestTemplate. Начи",[7,13],"WebClient — неблокирующий, реактивный HTTP-клиент из Spring WebFlux, пришедший на замену блокирующему RestTemplate. Начиная со Spring 6.1, появился также RestClient — блокирующий клиент с fluent API.",true]