[Spring Boot 3新特性] Spring boot 3新Rest客户端RestClient

背景

在Spring项目中,我们往往使用RestTemplate、HttpClient、OkHttp实现远程服务的调用。

随着Spring 6 和 Spring Boot 3版本的发布,Spring 6.1 M2 版本引入了RestClient客户端,并且在官方文档中强烈建议使用 。

If you are not using Spring WebFlux or Project Reactor in your application we recommend that you use RestClient to call remote REST services.

接下来,我们尝鲜试用一下:

客户端配置

package com.example.demo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;

@Configuration
public class RestClientConfig {

    @Value("${demo.url}")
    private String demoServiceUrl;

    @Bean
    public RestClient restClient() {
        return RestClient.builder().baseUrl(demoServiceUrl).build();
    }
}

  • 可以按照服务地址创建不同的Client。

基本使用

package com.example.demo.service;

import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;


@Service
public class RestClientService {
    @Resource
    private RestClient restClient;

    public String sayHello(String hello) {
        String res = restClient.get().uri("say1/{content}", hello).retrieve().body(String.class);
        return "say:" + res;
    }
}

高级配置

通常我们需要设置一些个性话参数来满足我们的需求,可以通设置factory、converters实现灵活使用,详情可以参考API:

/**
	 * A mutable builder for creating a {@link RestClient}.
	 */
	interface Builder {

		/**
		 * Configure a base URL for requests. Effectively a shortcut for:
		 * <pre class="code">
		 * String baseUrl = "https://abc.go.com/v1";
		 * DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
		 * RestClient client = RestClient.builder().uriBuilderFactory(factory).build();
		 * </pre>
		 * <p>The {@code DefaultUriBuilderFactory} is used to prepare the URL
		 * for every request with the given base URL, unless the URL request
		 * for a given URL is absolute in which case the base URL is ignored.
		 * <p><strong>Note:</strong> this method is mutually exclusive with
		 * {@link #uriBuilderFactory(UriBuilderFactory)}. If both are used, the
		 * {@code baseUrl} value provided here will be ignored.
		 * @return this builder
		 * @see DefaultUriBuilderFactory#DefaultUriBuilderFactory(String)
		 * @see #uriBuilderFactory(UriBuilderFactory)
		 */
		Builder baseUrl(String baseUrl);

		/**
		 * Configure default URL variable values to use when expanding URI
		 * templates with a {@link Map}. Effectively a shortcut for:
		 * <pre class="code">
		 * Map&lt;String, ?&gt; defaultVars = ...;
		 * DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
		 * factory.setDefaultVariables(defaultVars);
		 * RestClient client = RestClient.builder().uriBuilderFactory(factory).build();
		 * </pre>
		 * <p><strong>Note:</strong> this method is mutually exclusive with
		 * {@link #uriBuilderFactory(UriBuilderFactory)}. If both are used, the
		 * {@code defaultUriVariables} value provided here will be ignored.
		 * @return this builder
		 * @see DefaultUriBuilderFactory#setDefaultUriVariables(Map)
		 * @see #uriBuilderFactory(UriBuilderFactory)
		 */
		Builder defaultUriVariables(Map<String, ?> defaultUriVariables);

		/**
		 * Provide a pre-configured {@link UriBuilderFactory} instance. This is
		 * an alternative to, and effectively overrides the following shortcut
		 * properties:
		 * <ul>
		 * <li>{@link #baseUrl(String)}
		 * <li>{@link #defaultUriVariables(Map)}.
		 * </ul>
		 * @param uriBuilderFactory the URI builder factory to use
		 * @return this builder
		 * @see #baseUrl(String)
		 * @see #defaultUriVariables(Map)
		 */
		Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory);

		/**
		 * Global option to specify a header to be added to every request,
		 * if the request does not already contain such a header.
		 * @param header the header name
		 * @param values the header values
		 * @return this builder
		 */
		Builder defaultHeader(String header, String... values);

		/**
		 * Provide a consumer to access to every {@linkplain #defaultHeader(String, String...)
		 * default header} declared so far, with the possibility to add, replace, or remove.
		 * @param headersConsumer the consumer
		 * @return this builder
		 */
		Builder defaultHeaders(Consumer<HttpHeaders> headersConsumer);

		/**
		 * Provide a consumer to customize every request being built.
		 * @param defaultRequest the consumer to use for modifying requests
		 * @return this builder
		 */
		Builder defaultRequest(Consumer<RequestHeadersSpec<?>> defaultRequest);

		/**
		 * Register a default
		 * {@linkplain ResponseSpec#onStatus(Predicate, ResponseSpec.ErrorHandler) status handler}
		 * to apply to every response. Such default handlers are applied in the
		 * order in which they are registered, and after any others that are
		 * registered for a specific response.
		 * @param statusPredicate to match responses with
		 * @param errorHandler handler that typically, though not necessarily,
		 * throws an exception
		 * @return this builder
		 */
		Builder defaultStatusHandler(Predicate<HttpStatusCode> statusPredicate,
						ResponseSpec.ErrorHandler errorHandler);

		/**
		 * Register a default
		 * {@linkplain ResponseSpec#onStatus(ResponseErrorHandler) status handler}
		 * to apply to every response. Such default handlers are applied in the
		 * order in which they are registered, and after any others that are
		 * registered for a specific response.
		 * @param errorHandler handler that typically, though not necessarily,
		 * throws an exception
		 * @return this builder
		 */
		Builder defaultStatusHandler(ResponseErrorHandler errorHandler);

		/**
		 * Add the given request interceptor to the end of the interceptor chain.
		 * @param interceptor the interceptor to be added to the chain
		 * @return this builder
		 */
		Builder requestInterceptor(ClientHttpRequestInterceptor interceptor);

		/**
		 * Manipulate the interceptors with the given consumer. The list provided to
		 * the consumer is "live", so that the consumer can be used to remove
		 * interceptors, change ordering, etc.
		 * @param interceptorsConsumer a function that consumes the interceptors list
		 * @return this builder
		 */
		Builder requestInterceptors(Consumer<List<ClientHttpRequestInterceptor>> interceptorsConsumer);

		/**
		 * Add the given request initializer to the end of the initializer chain.
		 * @param initializer the initializer to be added to the chain
		 * @return this builder
		 */
		Builder requestInitializer(ClientHttpRequestInitializer initializer);

		/**
		 * Manipulate the initializers with the given consumer. The list provided to
		 * the consumer is "live", so that the consumer can be used to remove
		 * initializers, change ordering, etc.
		 * @param initializersConsumer a function that consumes the initializers list
		 * @return this builder
		 */
		Builder requestInitializers(Consumer<List<ClientHttpRequestInitializer>> initializersConsumer);

		/**
		 * Configure the {@link ClientHttpRequestFactory} to use. This is useful
		 * for plugging in and/or customizing options of the underlying HTTP
		 * client library (e.g. SSL).
		 * <p>If no request factory is specified, {@code RestClient} uses
		 * {@linkplain org.springframework.http.client.HttpComponentsClientHttpRequestFactory Apache Http Client},
		 * {@linkplain org.springframework.http.client.JettyClientHttpRequestFactory Jetty Http Client}
		 * if available on the classpath, and defaults to the
		 * {@linkplain org.springframework.http.client.JdkClientHttpRequestFactory JDK HttpClient}
		 * if the {@code java.net.http} module is loaded, or to a
		 * {@linkplain org.springframework.http.client.SimpleClientHttpRequestFactory simple default}
		 * otherwise.
		 * @param requestFactory the request factory to use
		 * @return this builder
		 */
		Builder requestFactory(ClientHttpRequestFactory requestFactory);

		/**
		 * Configure the message converters for the {@code RestClient} to use.
		 * @param configurer the configurer to apply
		 * @return this builder
		 */
		Builder messageConverters(Consumer<List<HttpMessageConverter<?>>> configurer);

		/**
		 * Configure the {@link io.micrometer.observation.ObservationRegistry} to use
		 * for recording HTTP client observations.
		 * @param observationRegistry the observation registry to use
		 * @return this builder
		 */
		Builder observationRegistry(ObservationRegistry observationRegistry);

		/**
		 * Apply the given {@code Consumer} to this builder instance.
		 * <p>This can be useful for applying pre-packaged customizations.
		 * @param builderConsumer the consumer to apply
		 * @return this builder
		 */
		Builder apply(Consumer<Builder> builderConsumer);

		/**
		 * Clone this {@code RestClient.Builder}.
		 */
		Builder clone();

		/**
		 * Build the {@link RestClient} instance.
		 */
		RestClient build();
	}

Spring 会根据工程依赖,自动选择客户端的引入,按如下优先级顺序引入:

  • Apache HttpClient

  • Jetty HttpClient

  • OkHttp (deprecated)

  • Simple JDK client (HttpURLConnection)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot 可以很方便地与 Elasticsearch 进行集成。下面是一个简单的步骤: 1. 添加 Elasticsearch 依赖 在 `pom.xml` 文件中添加 Elasticsearch 的 Maven 依赖: ```xml <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.12.0</version> </dependency> ``` 2. 配置 Elasticsearch 连接 在 `application.properties` 文件中添加 Elasticsearch 的连接配置: ```properties spring.elasticsearch.rest.uris=http://localhost:9200 ``` 3. 创建 Elasticsearch 客户端 使用 Spring Boot 的自动配置机制,可以很方便地创建 Elasticsearch 客户端: ```java @Configuration public class ElasticSearchConfig { @Value("${spring.elasticsearch.rest.uris}") private String esHost; @Bean(destroyMethod = "close") public RestHighLevelClient restHighLevelClient() { return new RestHighLevelClient(RestClient.builder(HttpHost.create(esHost))); } } ``` 4. 使用 Elasticsearch 客户端 现在,可以在需要使用 Elasticsearch 的地方注入 `RestHighLevelClient` 客户端: ```java @Autowired private RestHighLevelClient client; ``` 然后,就可以使用 Elasticsearch 的 REST API 进行索引、搜索等操作了。例如: ```java IndexRequest request = new IndexRequest("posts"); request.id("1"); String jsonString = "{" + "\"user\":\"kimchy\"," + "\"postDate\":\"2021-06-01\"," + "\"message\":\"trying out Elasticsearch\"" + "}"; request.source(jsonString, XContentType.JSON); IndexResponse response = client.index(request, RequestOptions.DEFAULT); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值