532 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			532 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| [[rest-client-access]]
 | |
| = REST Clients
 | |
| 
 | |
| The Spring Framework provides the following choices for making calls to REST endpoints:
 | |
| 
 | |
| * xref:integration/rest-clients.adoc#rest-webclient[`WebClient`] - non-blocking, reactive client with fluent API.
 | |
| * xref:integration/rest-clients.adoc#rest-resttemplate[`RestTemplate`] - synchronous client with template method API.
 | |
| * xref:integration/rest-clients.adoc#rest-http-interface[HTTP Interface] - annotated interface with generated, dynamic proxy implementation.
 | |
| 
 | |
| 
 | |
| [[rest-webclient]]
 | |
| == `WebClient`
 | |
| 
 | |
| `WebClient` is a non-blocking, reactive client to perform HTTP requests. It was
 | |
| introduced in 5.0 and offers an alternative to the `RestTemplate`, with support for
 | |
| synchronous, asynchronous, and streaming scenarios.
 | |
| 
 | |
| `WebClient` supports the following:
 | |
| 
 | |
| * Non-blocking I/O.
 | |
| * Reactive Streams back pressure.
 | |
| * High concurrency with fewer hardware resources.
 | |
| * Functional-style, fluent API that takes advantage of Java 8 lambdas.
 | |
| * Synchronous and asynchronous interactions.
 | |
| * Streaming up to or streaming down from a server.
 | |
| 
 | |
| See xref:web/webflux-webclient.adoc[WebClient] for more details.
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| [[rest-resttemplate]]
 | |
| == `RestTemplate`
 | |
| 
 | |
| The `RestTemplate` provides a higher level API over HTTP client libraries. It makes it
 | |
| easy to invoke REST endpoints in a single line. It exposes the following groups of
 | |
| overloaded methods:
 | |
| 
 | |
| NOTE: `RestTemplate` is in maintenance mode, with only requests for minor
 | |
| changes and bugs to be accepted. Please, consider using the
 | |
| xref:web/webflux-webclient.adoc[WebClient] instead.
 | |
| 
 | |
| [[rest-overview-of-resttemplate-methods-tbl]]
 | |
| .RestTemplate methods
 | |
| [cols="1,3"]
 | |
| |===
 | |
| | Method group | Description
 | |
| 
 | |
| | `getForObject`
 | |
| | Retrieves a representation via GET.
 | |
| 
 | |
| | `getForEntity`
 | |
| | Retrieves a `ResponseEntity` (that is, status, headers, and body) by using GET.
 | |
| 
 | |
| | `headForHeaders`
 | |
| | Retrieves all headers for a resource by using HEAD.
 | |
| 
 | |
| | `postForLocation`
 | |
| | Creates a new resource by using POST and returns the `Location` header from the response.
 | |
| 
 | |
| | `postForObject`
 | |
| | Creates a new resource by using POST and returns the representation from the response.
 | |
| 
 | |
| | `postForEntity`
 | |
| | Creates a new resource by using POST and returns the representation from the response.
 | |
| 
 | |
| | `put`
 | |
| | Creates or updates a resource by using PUT.
 | |
| 
 | |
| | `patchForObject`
 | |
| | Updates a resource by using PATCH and returns the representation from the response.
 | |
| Note that the JDK `HttpURLConnection` does not support `PATCH`, but Apache
 | |
| HttpComponents and others do.
 | |
| 
 | |
| | `delete`
 | |
| | Deletes the resources at the specified URI by using DELETE.
 | |
| 
 | |
| | `optionsForAllow`
 | |
| | Retrieves allowed HTTP methods for a resource by using ALLOW.
 | |
| 
 | |
| | `exchange`
 | |
| | More generalized (and less opinionated) version of the preceding methods that provides extra
 | |
| flexibility when needed. It accepts a `RequestEntity` (including HTTP method, URL, headers,
 | |
| and body as input) and returns a `ResponseEntity`.
 | |
| 
 | |
| These methods allow the use of `ParameterizedTypeReference` instead of `Class` to specify
 | |
| a response type with generics.
 | |
| 
 | |
| | `execute`
 | |
| | The most generalized way to perform a request, with full control over request
 | |
| preparation and response extraction through callback interfaces.
 | |
| 
 | |
| |===
 | |
| 
 | |
| [[rest-resttemplate-create]]
 | |
| === Initialization
 | |
| 
 | |
| The default constructor uses `java.net.HttpURLConnection` to perform requests. You can
 | |
| switch to a different HTTP library with an implementation of `ClientHttpRequestFactory`.
 | |
| There is built-in support for the following:
 | |
| 
 | |
| * Apache HttpComponents
 | |
| * Netty
 | |
| * OkHttp
 | |
| 
 | |
| For example, to switch to Apache HttpComponents, you can use the following:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
 | |
| ----
 | |
| 
 | |
| Each `ClientHttpRequestFactory` exposes configuration options specific to the underlying
 | |
| HTTP client library -- for example, for credentials, connection pooling, and other details.
 | |
| 
 | |
| TIP: Note that the `java.net` implementation for HTTP requests can raise an exception when
 | |
| accessing the status of a response that represents an error (such as 401). If this is an
 | |
| issue, switch to another HTTP client library.
 | |
| 
 | |
| NOTE: `RestTemplate` can be instrumented for observability, in order to produce metrics and traces.
 | |
| See the xref:integration/observability.adoc#http-client.resttemplate[RestTemplate Observability support] section.
 | |
| 
 | |
| [[rest-resttemplate-uri]]
 | |
| ==== URIs
 | |
| 
 | |
| Many of the `RestTemplate` methods accept a URI template and URI template variables,
 | |
| either as a `String` variable argument, or as `Map<String,String>`.
 | |
| 
 | |
| The following example uses a `String` variable argument:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	String result = restTemplate.getForObject(
 | |
| 			"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
 | |
| ----
 | |
| 
 | |
| The following example uses a `Map<String, String>`:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	Map<String, String> vars = Collections.singletonMap("hotel", "42");
 | |
| 
 | |
| 	String result = restTemplate.getForObject(
 | |
| 			"https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
 | |
| ----
 | |
| 
 | |
| Keep in mind URI templates are automatically encoded, as the following example shows:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	restTemplate.getForObject("https://example.com/hotel list", String.class);
 | |
| 
 | |
| 	// Results in request to "https://example.com/hotel%20list"
 | |
| ----
 | |
| 
 | |
| You can use the `uriTemplateHandler` property of `RestTemplate` to customize how URIs
 | |
| are encoded. Alternatively, you can prepare a `java.net.URI` and pass it into one of
 | |
| the `RestTemplate` methods that accepts a `URI`.
 | |
| 
 | |
| For more details on working with and encoding URIs, see xref:web/webmvc/mvc-uri-building.adoc[URI Links].
 | |
| 
 | |
| [[rest-template-headers]]
 | |
| ==== Headers
 | |
| 
 | |
| You can use the `exchange()` methods to specify request headers, as the following example shows:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	String uriTemplate = "https://example.com/hotels/{hotel}";
 | |
| 	URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);
 | |
| 
 | |
| 	RequestEntity<Void> requestEntity = RequestEntity.get(uri)
 | |
| 			.header("MyRequestHeader", "MyValue")
 | |
| 			.build();
 | |
| 
 | |
| 	ResponseEntity<String> response = template.exchange(requestEntity, String.class);
 | |
| 
 | |
| 	String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
 | |
| 	String body = response.getBody();
 | |
| ----
 | |
| 
 | |
| You can obtain response headers through many `RestTemplate` method variants that return
 | |
| `ResponseEntity`.
 | |
| 
 | |
| [[rest-template-body]]
 | |
| === Body
 | |
| 
 | |
| Objects passed into and returned from `RestTemplate` methods are converted to and from raw
 | |
| content with the help of an `HttpMessageConverter`.
 | |
| 
 | |
| On a POST, an input object is serialized to the request body, as the following example shows:
 | |
| 
 | |
| ----
 | |
| URI location = template.postForLocation("https://example.com/people", person);
 | |
| ----
 | |
| 
 | |
| You need not explicitly set the Content-Type header of the request. In most cases,
 | |
| you can find a compatible message converter based on the source `Object` type, and the chosen
 | |
| message converter sets the content type accordingly. If necessary, you can use the
 | |
| `exchange` methods to explicitly provide the `Content-Type` request header, and that, in
 | |
| turn, influences what message converter is selected.
 | |
| 
 | |
| On a GET, the body of the response is deserialized to an output `Object`, as the following example shows:
 | |
| 
 | |
| ----
 | |
| Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);
 | |
| ----
 | |
| 
 | |
| The `Accept` header of the request does not need to be explicitly set. In most cases,
 | |
| a compatible message converter can be found based on the expected response type, which
 | |
| then helps to populate the `Accept` header. If necessary, you can use the `exchange`
 | |
| methods to provide the `Accept` header explicitly.
 | |
| 
 | |
| By default, `RestTemplate` registers all built-in
 | |
| xref:integration/rest-clients.adoc#rest-message-conversion[message converters], depending on classpath checks that help
 | |
| to determine what optional conversion libraries are present. You can also set the message
 | |
| converters to use explicitly.
 | |
| 
 | |
| [[rest-message-conversion]]
 | |
| ==== Message Conversion
 | |
| [.small]#xref:web/webflux/reactive-spring.adoc#webflux-codecs[See equivalent in the Reactive stack]#
 | |
| 
 | |
| The `spring-web` module contains the `HttpMessageConverter` contract for reading and
 | |
| writing the body of HTTP requests and responses through `InputStream` and `OutputStream`.
 | |
| `HttpMessageConverter` instances are used on the client side (for example, in the `RestTemplate`) and
 | |
| on the server side (for example, in Spring MVC REST controllers).
 | |
| 
 | |
| Concrete implementations for the main media (MIME) types are provided in the framework
 | |
| and are, by default, registered with the `RestTemplate` on the client side and with
 | |
| `RequestMappingHandlerAdapter` on the server side (see
 | |
| xref:web/webmvc/mvc-config/message-converters.adoc[Configuring Message Converters]).
 | |
| 
 | |
| The implementations of `HttpMessageConverter` are described in the following sections.
 | |
| For all converters, a default media type is used, but you can override it by setting the
 | |
| `supportedMediaTypes` bean property. The following table describes each implementation:
 | |
| 
 | |
| [[rest-message-converters-tbl]]
 | |
| .HttpMessageConverter Implementations
 | |
| [cols="1,3"]
 | |
| |===
 | |
| | MessageConverter | Description
 | |
| 
 | |
| | `StringHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write `String` instances from the HTTP
 | |
| request and response. By default, this converter supports all text media types
 | |
| (`text/{asterisk}`) and writes with a `Content-Type` of `text/plain`.
 | |
| 
 | |
| | `FormHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write form data from the HTTP
 | |
| request and response. By default, this converter reads and writes the
 | |
| `application/x-www-form-urlencoded` media type. Form data is read from and written into a
 | |
| `MultiValueMap<String, String>`. The converter can also write (but not read) multipart
 | |
| data read from a `MultiValueMap<String, Object>`. By default, `multipart/form-data` is
 | |
| supported. As of Spring Framework 5.2, additional multipart subtypes can be supported for
 | |
| writing form data. Consult the javadoc for `FormHttpMessageConverter` for further details.
 | |
| 
 | |
| | `ByteArrayHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write byte arrays from the
 | |
| HTTP request and response. By default, this converter supports all media types (`{asterisk}/{asterisk}`)
 | |
| and writes with a `Content-Type` of `application/octet-stream`. You can override this
 | |
| by setting the `supportedMediaTypes` property and overriding `getContentType(byte[])`.
 | |
| 
 | |
| | `MarshallingHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write XML by using Spring's
 | |
| `Marshaller` and `Unmarshaller` abstractions from the `org.springframework.oxm` package.
 | |
| This converter requires a `Marshaller` and `Unmarshaller` before it can be used. You can inject these
 | |
| through constructor or bean properties. By default, this converter supports
 | |
| `text/xml` and `application/xml`.
 | |
| 
 | |
| | `MappingJackson2HttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write JSON by using Jackson's
 | |
| `ObjectMapper`. You can customize JSON mapping as needed through the use of Jackson's
 | |
| provided annotations. When you need further control (for cases where custom JSON
 | |
| serializers/deserializers need to be provided for specific types), you can inject a custom `ObjectMapper`
 | |
| through the `ObjectMapper` property. By default, this
 | |
| converter supports `application/json`.
 | |
| 
 | |
| | `MappingJackson2XmlHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write XML by using
 | |
| https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML] extension's
 | |
| `XmlMapper`. You can customize XML mapping as needed through the use of JAXB
 | |
| or Jackson's provided annotations. When you need further control (for cases where custom XML
 | |
| serializers/deserializers need to be provided for specific types), you can inject a custom `XmlMapper`
 | |
| through the `ObjectMapper` property. By default, this
 | |
| converter supports `application/xml`.
 | |
| 
 | |
| | `SourceHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write
 | |
| `javax.xml.transform.Source` from the HTTP request and response. Only `DOMSource`,
 | |
| `SAXSource`, and `StreamSource` are supported. By default, this converter supports
 | |
| `text/xml` and `application/xml`.
 | |
| 
 | |
| | `BufferedImageHttpMessageConverter`
 | |
| | An `HttpMessageConverter` implementation that can read and write
 | |
| `java.awt.image.BufferedImage` from the HTTP request and response. This converter reads
 | |
| and writes the media type supported by the Java I/O API.
 | |
| 
 | |
| |===
 | |
| 
 | |
| [[rest-template-jsonview]]
 | |
| === Jackson JSON Views
 | |
| 
 | |
| You can specify a https://www.baeldung.com/jackson-json-view-annotation[Jackson JSON View]
 | |
| to serialize only a subset of the object properties, as the following example shows:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
 | |
| 	value.setSerializationView(User.WithoutPasswordView.class);
 | |
| 
 | |
| 	RequestEntity<MappingJacksonValue> requestEntity =
 | |
| 		RequestEntity.post(new URI("https://example.com/user")).body(value);
 | |
| 
 | |
| 	ResponseEntity<String> response = template.exchange(requestEntity, String.class);
 | |
| ----
 | |
| 
 | |
| [[rest-template-multipart]]
 | |
| === Multipart
 | |
| 
 | |
| To send multipart data, you need to provide a `MultiValueMap<String, Object>` whose values
 | |
| may be an `Object` for part content, a `Resource` for a file part, or an `HttpEntity` for
 | |
| part content with headers. For example:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
 | |
| 
 | |
| 	parts.add("fieldPart", "fieldValue");
 | |
| 	parts.add("filePart", new FileSystemResource("...logo.png"));
 | |
| 	parts.add("jsonPart", new Person("Jason"));
 | |
| 
 | |
| 	HttpHeaders headers = new HttpHeaders();
 | |
| 	headers.setContentType(MediaType.APPLICATION_XML);
 | |
| 	parts.add("xmlPart", new HttpEntity<>(myBean, headers));
 | |
| ----
 | |
| 
 | |
| In most cases, you do not have to specify the `Content-Type` for each part. The content
 | |
| type is determined automatically based on the `HttpMessageConverter` chosen to serialize
 | |
| it or, in the case of a `Resource` based on the file extension. If necessary, you can
 | |
| explicitly provide the `MediaType` with an `HttpEntity` wrapper.
 | |
| 
 | |
| Once the `MultiValueMap` is ready, you can pass it to the `RestTemplate`, as show below:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	MultiValueMap<String, Object> parts = ...;
 | |
| 	template.postForObject("https://example.com/upload", parts, Void.class);
 | |
| ----
 | |
| 
 | |
| If the `MultiValueMap` contains at least one non-`String` value, the `Content-Type` is set
 | |
| to `multipart/form-data` by the `FormHttpMessageConverter`. If the `MultiValueMap` has
 | |
| `String` values the `Content-Type` is defaulted to `application/x-www-form-urlencoded`.
 | |
| If necessary the `Content-Type` may also be set explicitly.
 | |
| 
 | |
| 
 | |
| [[rest-http-interface]]
 | |
| == HTTP Interface
 | |
| 
 | |
| The Spring Framework lets you define an HTTP service as a Java interface with annotated
 | |
| methods for HTTP exchanges. You can then generate a proxy that implements this interface
 | |
| and performs the exchanges. This helps to simplify HTTP remote access which often
 | |
| involves a facade that wraps the details of using the underlying HTTP client.
 | |
| 
 | |
| One, declare an interface with `@HttpExchange` methods:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	interface RepositoryService {
 | |
| 
 | |
| 		@GetExchange("/repos/{owner}/{repo}")
 | |
| 		Repository getRepository(@PathVariable String owner, @PathVariable String repo);
 | |
| 
 | |
| 		// more HTTP exchange methods...
 | |
| 
 | |
| 	}
 | |
| ----
 | |
| 
 | |
| Two, create a proxy that will perform the declared HTTP exchanges:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
 | |
| 	HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
 | |
| 
 | |
| 	RepositoryService service = factory.createClient(RepositoryService.class);
 | |
| ----
 | |
| 
 | |
| `@HttpExchange` is supported at the type level where it applies to all methods:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	@HttpExchange(url = "/repos/{owner}/{repo}", accept = "application/vnd.github.v3+json")
 | |
| 	interface RepositoryService {
 | |
| 
 | |
| 		@GetExchange
 | |
| 		Repository getRepository(@PathVariable String owner, @PathVariable String repo);
 | |
| 
 | |
| 		@PatchExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
 | |
| 		void updateRepository(@PathVariable String owner, @PathVariable String repo,
 | |
| 				@RequestParam String name, @RequestParam String description, @RequestParam String homepage);
 | |
| 
 | |
| 	}
 | |
| ----
 | |
| 
 | |
| 
 | |
| [[rest-http-interface-method-parameters]]
 | |
| === Method Parameters
 | |
| 
 | |
| Annotated, HTTP exchange methods support flexible method signatures with the following
 | |
| method parameters:
 | |
| 
 | |
| [cols="1,2", options="header"]
 | |
| |===
 | |
| | Method argument | Description
 | |
| 
 | |
| | `URI`
 | |
| | Dynamically set the URL for the request, overriding the annotation's `url` attribute.
 | |
| 
 | |
| | `HttpMethod`
 | |
| | Dynamically set the HTTP method for the request, overriding the annotation's `method` attribute
 | |
| 
 | |
| | `@RequestHeader`
 | |
| | Add a request header or multiple headers. The argument may be a `Map<String, ?>` or
 | |
|   `MultiValueMap<String, ?>` with multiple headers, a `Collection<?>` of values, or an
 | |
|   individual value. Type conversion is supported for non-String values.
 | |
| 
 | |
| | `@PathVariable`
 | |
| | Add a variable for expand a placeholder in the request URL. The argument may be a
 | |
|   `Map<String, ?>` with multiple variables, or an individual value. Type conversion
 | |
|   is supported for non-String values.
 | |
| 
 | |
| | `@RequestBody`
 | |
| | Provide the body of the request either as an Object to be serialized, or a
 | |
|   Reactive Streams `Publisher` such as `Mono`, `Flux`, or any other async type supported
 | |
|   through the configured `ReactiveAdapterRegistry`.
 | |
| 
 | |
| | `@RequestParam`
 | |
| | Add a request parameter or multiple parameters. The argument may be a `Map<String, ?>`
 | |
|   or `MultiValueMap<String, ?>` with multiple parameters, a `Collection<?>` of values, or
 | |
|   an individual value. Type conversion is supported for non-String values.
 | |
| 
 | |
|   When `"content-type"` is set to `"application/x-www-form-urlencoded"`, request
 | |
|   parameters are encoded in the request body. Otherwise, they are added as URL query
 | |
|   parameters.
 | |
| 
 | |
| | `@RequestPart`
 | |
| | Add a request part, which may be a String (form field), `Resource` (file part),
 | |
|   Object (entity to be encoded, e.g. as JSON), `HttpEntity` (part content and headers),
 | |
|   a Spring `Part`, or Reactive Streams `Publisher` of any of the above.
 | |
| 
 | |
| | `MultipartFile`
 | |
| | Add a request part from a `MultipartFile`, typically used in a Spring MVC controller
 | |
|   where it represents an uploaded file.
 | |
| 
 | |
| | `@CookieValue`
 | |
| | Add a cookie or multiple cookies. The argument may be a `Map<String, ?>` or
 | |
|   `MultiValueMap<String, ?>` with multiple cookies, a `Collection<?>` of values, or an
 | |
|   individual value. Type conversion is supported for non-String values.
 | |
| 
 | |
| |===
 | |
| 
 | |
| 
 | |
| [[rest-http-interface-return-values]]
 | |
| === Return Values
 | |
| 
 | |
| Annotated, HTTP exchange methods support the following return values:
 | |
| 
 | |
| [cols="1,2", options="header"]
 | |
| |===
 | |
| | Method return value | Description
 | |
| 
 | |
| | `void`, `Mono<Void>`
 | |
| | Perform the given request, and release the response content, if any.
 | |
| 
 | |
| | `HttpHeaders`, `Mono<HttpHeaders>`
 | |
| | Perform the given request, release the response content, if any, and return the
 | |
|   response headers.
 | |
| 
 | |
| | `<T>`, `Mono<T>`
 | |
| | Perform the given request and decode the response content to the declared return type.
 | |
| 
 | |
| | `<T>`, `Flux<T>`
 | |
| | Perform the given request and decode the response content to a stream of the declared
 | |
|   element type.
 | |
| 
 | |
| | `ResponseEntity<Void>`, `Mono<ResponseEntity<Void>>`
 | |
| | Perform the given request, and release the response content, if any, and return a
 | |
|   `ResponseEntity` with the status and headers.
 | |
| 
 | |
| | `ResponseEntity<T>`, `Mono<ResponseEntity<T>>`
 | |
| | Perform the given request, decode the response content to the declared return type, and
 | |
|   return a `ResponseEntity` with the status, headers, and the decoded body.
 | |
| 
 | |
| | `Mono<ResponseEntity<Flux<T>>`
 | |
| | Perform the given request, decode the response content to a stream of the declared
 | |
|   element type, and return a `ResponseEntity` with the status, headers, and the decoded
 | |
|   response body stream.
 | |
| 
 | |
| |===
 | |
| 
 | |
| TIP: You can also use any other async or reactive types registered in the
 | |
| `ReactiveAdapterRegistry`.
 | |
| 
 | |
| By default, the behavior of HTTP service methods with synchronous (blocking) method
 | |
| signature depends on connection and timeout settings of the underlying HTTP client.
 | |
| `HttpServiceProxyFactory.Builder` does expose a `blockTimeout` option that also lets you
 | |
| configure the maximum time to block for a response, but we recommend configuring timeout
 | |
| values directly on the underlying HTTP client, which likely provides more control over
 | |
| such settings.
 | |
| 
 | |
| 
 | |
| [[rest-http-interface-exceptions]]
 | |
| === Exception Handling
 | |
| 
 | |
| By default, `WebClient` raises `WebClientResponseException` for 4xx and 5xx HTTP status
 | |
| codes. To customize this, you can register a response status handler that applies to all
 | |
| responses performed through the client:
 | |
| 
 | |
| [source,java,indent=0,subs="verbatim,quotes"]
 | |
| ----
 | |
| 	WebClient webClient = WebClient.builder()
 | |
| 			.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
 | |
| 			.build();
 | |
| 
 | |
| 	WebClientAdapter clientAdapter = WebClientAdapter.forClient(webClient);
 | |
| 	HttpServiceProxyFactory factory = HttpServiceProxyFactory
 | |
| 			.builder(clientAdapter).build();
 | |
| ----
 | |
| 
 | |
| For more details and options, such as suppressing error status codes, see the Javadoc of
 | |
| `defaultStatusHandler` in `WebClient.Builder`.
 |