Skip to content

Commit 9daf99a

Browse files
committed
Merge branch '6.2.x'
2 parents c6b4b43 + e735c2d commit 9daf99a

File tree

4 files changed

+62
-15
lines changed

4 files changed

+62
-15
lines changed

framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,30 @@
33

44
[.small]#xref:web/webflux/reactive-spring.adoc#webflux-filters[See equivalent in the Reactive stack]#
55

6-
The `spring-web` module provides some useful filters:
6+
In the Servlet API, you can add a `jakarta.servlet.Filter` to apply interception-style logic
7+
before and after the rest of the processing chain of filters and the target `Servlet`.
8+
9+
The `spring-web` module has a number of built-in `Filter` implementations:
710

811
* xref:web/webmvc/filters.adoc#filters-http-put[Form Data]
912
* xref:web/webmvc/filters.adoc#filters-forwarded-headers[Forwarded Headers]
1013
* xref:web/webmvc/filters.adoc#filters-shallow-etag[Shallow ETag]
1114
* xref:web/webmvc/filters.adoc#filters-cors[CORS]
1215
* xref:web/webmvc/filters.adoc#filters.url-handler[URL Handler]
1316

14-
Servlet filters can be configured in the `web.xml` configuration file or using Servlet annotations.
15-
If you are using Spring Boot, you can
16-
{spring-boot-docs}/how-to/webserver.html#howto.webserver.add-servlet-filter-listener.spring-bean[declare them as beans and configure them as part of your application].
17+
There are also base class implementations for use in Spring applications:
18+
19+
* `GenericFilterBean` -- base class for a `Filter` configured as a Spring bean;
20+
integrates with the Spring `ApplicationContext` lifecycle.
21+
* `OncePerRequestFilter` -- extension of `GenericFilterBean` that supports a single
22+
invocation at the start of a request, i.e. during the `REQUEST` dispatch phase, and
23+
ignoring further handling via `FORWARD` dispatches. The filter also provides control
24+
over whether the `Filter` gets involved in `ASYNC` and `ERROR` dispatches.
25+
26+
Servlet filters can be configured in `web.xml` or via Servlet annotations.
27+
In a Spring Boot application , you can
28+
{spring-boot-docs}/how-to/webserver.html#howto.webserver.add-servlet-filter-listener.spring-bean[declare Filter's as beans]
29+
and Boot will have them configured.
1730

1831

1932
[[filters-http-put]]

spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,25 @@
2222
import org.springframework.util.StreamUtils;
2323

2424
/**
25-
* Represents an HTTP output message that allows for setting a streaming body.
26-
* Note that such messages typically do not support {@link #getBody()} access.
25+
* Contract for {@code HttpOutputMessage} implementations to expose the ability
26+
* to stream request body content by writing to an {@link OutputStream} from
27+
* a callback.
28+
*
29+
* <p>The {@link #setBody(Body)} method provides the option to stream, and is
30+
* mutually exclusive use of {@link #getBody()}, which instead returns an
31+
* {@code OutputStream} that aggregates the request body before sending it.
2732
*
2833
* @author Arjen Poutsma
34+
* @author Rossen Stoyanchev
2935
* @since 4.0
3036
* @see #setBody
3137
*/
3238
public interface StreamingHttpOutputMessage extends HttpOutputMessage {
3339

3440
/**
3541
* Set the streaming body callback for this message.
42+
* <p>Note that this is mutually exclusive with {@link #getBody()}, which
43+
* may instead aggregate the request body before sending it.
3644
* @param body the streaming body callback
3745
*/
3846
void setBody(Body body);
@@ -60,9 +68,9 @@ public boolean repeatable() {
6068

6169

6270
/**
63-
* Defines the contract for bodies that can be written directly to an
64-
* {@link OutputStream}. Useful with HTTP client libraries that provide
65-
* indirect access to an {@link OutputStream} via a callback mechanism.
71+
* Contract to stream request body content to an {@link OutputStream}.
72+
* In some HTTP client libraries this is only possible indirectly through a
73+
* callback mechanism.
6674
*/
6775
@FunctionalInterface
6876
interface Body {

spring-web/src/main/java/org/springframework/http/client/AbstractStreamingClientHttpRequest.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,23 @@
2222
import org.jspecify.annotations.Nullable;
2323

2424
import org.springframework.http.HttpHeaders;
25+
import org.springframework.http.HttpOutputMessage;
2526
import org.springframework.http.StreamingHttpOutputMessage;
2627
import org.springframework.util.Assert;
2728
import org.springframework.util.FastByteArrayOutputStream;
2829

2930
/**
30-
* Abstract base for {@link ClientHttpRequest} that also implement
31-
* {@link StreamingHttpOutputMessage}. Ensures that headers and
32-
* body are not written multiple times.
31+
* Extension of {@link AbstractClientHttpRequest} that adds the ability to stream
32+
* request body content directly to the underlying HTTP client library through
33+
* the {@link StreamingHttpOutputMessage} contract.
34+
*
35+
* <p>It is necessary to call {@link #setBody} and stream the request body through
36+
* a callback for access to the {@code OutputStream}. The alternative to call
37+
* {@link #getBody()} is also supported as a fallback, but that does not stream,
38+
* and returns an aggregating {@code OutputStream} instead.
3339
*
3440
* @author Arjen Poutsma
41+
* @author Rossen Stoyanchev
3542
* @since 6.1
3643
*/
3744
abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequest
@@ -42,6 +49,12 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ
4249
private @Nullable FastByteArrayOutputStream bodyStream;
4350

4451

52+
/**
53+
* Implements the {@link HttpOutputMessage} contract for request body content.
54+
* <p>Note that this method does not result in streaming, and the returned
55+
* {@code OutputStream} aggregates the full content in a byte[] before
56+
* sending. To use streaming, call {@link #setBody} instead.
57+
*/
4558
@Override
4659
protected final OutputStream getBodyInternal(HttpHeaders headers) {
4760
Assert.state(this.body == null, "Invoke either getBody or setBody; not both");
@@ -52,6 +65,10 @@ protected final OutputStream getBodyInternal(HttpHeaders headers) {
5265
return this.bodyStream;
5366
}
5467

68+
/**
69+
* Implements the {@link StreamingHttpOutputMessage} contract for writing
70+
* request body by streaming directly to the underlying HTTP client.
71+
*/
5572
@Override
5673
public final void setBody(Body body) {
5774
Assert.notNull(body, "Body must not be null");
@@ -72,12 +89,14 @@ protected final ClientHttpResponse executeInternal(HttpHeaders headers) throws I
7289

7390

7491
/**
75-
* Abstract template method that writes the given headers and content to the HTTP request.
76-
* @param headers the HTTP headers
92+
* Abstract method for concrete implementations to write the headers and
93+
* {@link StreamingHttpOutputMessage.Body} to the HTTP request.
94+
* @param headers the HTTP headers for the request
7795
* @param body the HTTP body, may be {@code null} if no body was {@linkplain #setBody(Body) set}
7896
* @return the response object for the executed request
7997
* @since 6.1
8098
*/
81-
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException;
99+
protected abstract ClientHttpResponse executeInternal(
100+
HttpHeaders headers, @Nullable Body body) throws IOException;
82101

83102
}

spring-web/src/main/java/org/springframework/web/client/RequestCallback.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.lang.reflect.Type;
2121

22+
import org.springframework.http.HttpOutputMessage;
2223
import org.springframework.http.client.ClientHttpRequest;
2324

2425
/**
@@ -44,6 +45,12 @@ public interface RequestCallback {
4445
* Gets called by {@link RestTemplate#execute} with an opened {@code ClientHttpRequest}.
4546
* Does not need to care about closing the request or about handling errors:
4647
* this will all be handled by the {@code RestTemplate}.
48+
* <p><strong>Note:</strong> In order to stream request body content directly
49+
* to the underlying HTTP library, implementations must check if the request
50+
* is an implementation of {@link org.springframework.http.StreamingHttpOutputMessage},
51+
* and set the request body through it. Use of the {@link HttpOutputMessage#getBody()}
52+
* is also supported, but results in full content aggregation prior to execution.
53+
* All built-in request implementations support {@code StreamingHttpOutputMessage}.
4754
* @param request the active HTTP request
4855
* @throws IOException in case of I/O errors
4956
*/

0 commit comments

Comments
 (0)