Add API versioning reference documentation

See gh-34569
This commit is contained in:
rstoyanchev 2025-05-09 16:37:23 +01:00
parent bf78980925
commit cce2771639
9 changed files with 469 additions and 0 deletions

View File

@ -197,6 +197,7 @@
*** xref:web/webmvc/mvc-uri-building.adoc[]
*** xref:web/webmvc/mvc-ann-async.adoc[]
*** xref:web/webmvc-cors.adoc[]
*** xref:web/webmvc-versioning.adoc[]
*** xref:web/webmvc/mvc-ann-rest-exceptions.adoc[]
*** xref:web/webmvc/mvc-security.adoc[]
*** xref:web/webmvc/mvc-caching.adoc[]
@ -225,6 +226,7 @@
**** xref:web/webmvc/mvc-config/static-resources.adoc[]
**** xref:web/webmvc/mvc-config/default-servlet-handler.adoc[]
**** xref:web/webmvc/mvc-config/path-matching.adoc[]
**** xref:web/webmvc/mvc-config/api-version.adoc[]
**** xref:web/webmvc/mvc-config/advanced-java.adoc[]
**** xref:web/webmvc/mvc-config/advanced-xml.adoc[]
*** xref:web/webmvc/mvc-http2.adoc[]
@ -292,6 +294,7 @@
*** xref:web/webflux-functional.adoc[]
*** xref:web/webflux/uri-building.adoc[]
*** xref:web/webflux-cors.adoc[]
*** xref:web/webflux-versioning.adoc[]
*** xref:web/webflux/ann-rest-exceptions.adoc[]
*** xref:web/webflux/security.adoc[]
*** xref:web/webflux/caching.adoc[]

View File

@ -0,0 +1,80 @@
[[webflux-versioning]]
= API Versioning
:page-section-summary-toc: 1
[.small]#xref:web/webmvc-versioning.adoc[See equivalent in the Servlet stack]#
Spring WebFlux supports API versioning. This section provides an overview of the support
and underlying strategies.
Please, see also related content in:
- Use xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-version[API Versions]
to map requests to annotated controller methods
- Configure API versioning in xref:web/webflux/config.adoc#webflux-config-api-version[WebFlux Config]
[[webflux-versioning-strategy]]
== ApiVersionStrategy
[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-strategy[See equivalent in the Servlet stack]#
This strategy holds all application preferences about how to manage versioning.
It delegates to xref:#webflux-versioning-resolver[ApiVersionResolver] to resolve versions
from requests, and to xref:#webflux-versioning-parser[ApiVersionParser] to parse raw version
values into `Comparable<?>`. It also helps to xref:#webflux-versioning-validation[validate]
request versions.
NOTE: `ApiVersionStrategy` helps to map requests to `@RequestMapping` controller methods,
and is initialized by the WebFlux config. Typically, applications do not interact directly with it.
[[webflux-versioning-resolver]]
== ApiVersionResolver
[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-resolver[See equivalent in the Servlet stack]#
This strategy resolves the API version from a request. The WebFlux config provides built-in
options to resolve from a header, a request parameter, or from the URL path.
You can also use a custom `ApiVersionResolver`.
[[webflux-versioning-parser]]
== ApiVersionParser
[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-parser[See equivalent in the Servlet stack]#
This strategy helps to parse raw version values into `Comparable<?>`, which helps to
compare, sort, and select versions. By default, the built-in `SemanticApiVersionParser`
parses a version into `major`, `minor`, and `patch` integer values. Minor and patch
values are set to 0 if not present.
[[webflux-versioning-validation]]
== Validation
[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-validation[See equivalent in the Servlet stack]#
If a request version is not supported, `InvalidApiVersionException` is raised resulting
in a 400 response. By default, the list of supported versions is initialized from declared
versions in annotated controller mappings. You can add to that list, or set it explicitly
to a fixed set of versions (i.e. ignoring declared ones) through the MVC config.
By default, a version is required when API versioning is enabled, but you can turn that
off in which case the highest available version is used. You can also specify a default
version. `MissingApiVersionException` is raised resulting in a 400 response when a
version is required but not present.
[[webflux-versioning-mapping]]
== Request Mapping
[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-mapping[See equivalent in the Servlet stack]#
`ApiVersionStrategy` supports the mapping of requests to annotated controller methods.
See xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-version[API Versions]
for more details.

View File

@ -686,6 +686,63 @@ reliance on it.
[[webflux-config-api-version]]
== API Version
[.small]#xref:web/webmvc/mvc-config/api-version.adoc[See equivalent in the Servlet stack]#
To enable API versioning with a request header, use the following:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim"]
----
@Configuration
public class WebConfiguration implements WebFluxConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.useRequestHeader("X-API-Version");
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim"]
----
@Configuration
class WebConfiguration : WebMvcConfigurer {
override fun configureApiVersioning(configurer: ApiVersionConfigurer) {
configurer.useRequestHeader("X-API-Version")
}
}
----
======
Alternatively, the version can be resolved from a request parameter, from a path segment,
or through a custom `ApiVersionResolver`.
TIP: When resolving from a path segment, consider configuring a path prefix once in
xref:web/webmvc/mvc-config/path-matching.adoc[Path Matching] options.
Raw version values are parsed with `SemanticVersionParser` by default, but you can use
a custom xref:web/webflux-versioning.adoc#webflux-versioning-parser[ApiVersionParser].
"Supported" versions are transparently detected from versions declared in request mappings
for convenience, but you can also set the list of supported versions explicitly, and
ignore declared ones. Requests with a version that is not supported are rejected with an
`InvalidApiVersionException` resulting in a 400 response.
Once API versioning is configured, you can begin to map requests to
xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-version[controller methods]
according to the request version.
[[webflux-config-blocking-execution]]
== Blocking Execution

View File

@ -408,6 +408,85 @@ Kotlin::
======
[[webflux-ann-requestmapping-version]]
== API Version
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-version[See equivalent in the Servlet stack]#
There is no standard way to specify an API version, so you need to configure that first
through the xref:web/webflux/config.adoc#webflux-config-api-version[WebFlux Config] along with other
config options. This results in the creation of an
xref:web/webflux-versioning.adoc#webflux-versioning-strategy[ApiVersionStrategy] that in
supports request mapping.
Once API versioning is enabled, you can begin to map requests with versions.
The `@RequestMapping` version attribute supports the following:
- No value -- match any version
- Fixed version ("1.2") -- match the given version only
- Baseline version ("1.2+") -- match the given version and above
If multiple controller methods have a version less than or equal to the request version,
the one closest to the request version is considered for mapping purposes,
in effect superseding the rest.
To illustrate this, consider the following controller mappings:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
@RestController
@RequestMapping("/account/{id}")
public class AccountController {
@GetMapping // <1>
public Account getAccount() {
}
@GetMapping(version = "1.1") // <2>
public Account getAccount1_1() {
}
@GetMapping(version = "1.2+") // <3>
public Account getAccount1_2() {
}
@GetMapping(version = "1.5") // <4>
public Account getAccount1_5() {
}
}
----
<1> match any version
<2> match version 1.1
<3> match version 1.2 and above
<4> match version 1.5
======
For request with version `"1.3"`:
- (1) matches as it matches any version
- (2) does not match
- (3) matches as it matches 1.2 and above, and is *chosen* as the highest match
- (4) is higher and does not match
For request with version `"1.5"`:
- (1) matches as it matches any version
- (2) does not match
- (3) matches as it matches 1.2 and above
- (4) matches and is *chosen* as the highest match
A request with version `"1.6"` does not have a match. (1) and (3) do match, but are
superseded by (4), which does not match. In this scenario, `NotAcceptableApiVersionException`
is raised resulting in a 400 response.
NOTE: The above assumes the request version is a "supported" versions. If not it would
fail xref:web/webflux-versioning.adoc#webflux-versioning-validation[Validation].
[[webflux-ann-requestmapping-head-options]]
== HTTP HEAD, OPTIONS

View File

@ -0,0 +1,81 @@
[[mvc-versioning]]
= API Versioning
:page-section-summary-toc: 1
[.small]#xref:web/webflux-versioning.adoc[See equivalent in the Reactive stack]#
Spring MVC supports API versioning. This section provides an overview of the support
and underlying strategies.
Please, see also related content in:
- Use xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-version[API Version]
to map requests to annotated controller methods
- Configure API versioning in xref:web/webmvc/mvc-config/api-version.adoc[MVC Config]
[[mvc-versioning-strategy]]
== ApiVersionStrategy
[.small]#xref:web/webflux-versioning.adoc#webflux-versioning-strategy[See equivalent in the Reactive stack]#
This strategy holds all application preferences about how to manage versioning.
It delegates to xref:#mvc-versioning-resolver[ApiVersionResolver] to resolve versions
from requests, and to xref:#mvc-versioning-parser[ApiVersionParser] to parse raw version
values into `Comparable<?>`. It also helps to xref:#mvc-versioning-validation[validate]
request versions.
NOTE: `ApiVersionStrategy` helps to map requests to `@RequestMapping` controller methods,
and is initialized by the MVC config. Typically, applications do not interact directly with it.
[[mvc-versioning-resolver]]
== ApiVersionResolver
[.small]#xref:web/webmvc-versioning.adoc#mvc-versioning-resolver[See equivalent in the Reactive stack]#
This strategy resolves the API version from a request. The MVC config provides built-in
options to resolve from a header, from a request parameter, or from the URL path.
You can also use a custom `ApiVersionResolver`.
[[mvc-versioning-parser]]
== ApiVersionParser
[.small]#xref:web/webflux-versioning.adoc#webflux-versioning-parser[See equivalent in the Reactive stack]#
This strategy helps to parse raw version values into `Comparable<?>`, which helps to
compare, sort, and select versions. By default, the built-in `SemanticApiVersionParser`
parses a version into `major`, `minor`, and `patch` integer values. Minor and patch
values are set to 0 if not present.
[[mvc-versioning-validation]]
== Validation
[.small]#xref:web/webflux-versioning.adoc#webflux-versioning-validation[See equivalent in the Reactive stack]#
If a request version is not supported, `InvalidApiVersionException` is raised resulting
in a 400 response. By default, the list of supported versions is initialized from declared
versions in annotated controller mappings. You can add to that list, or set it explicitly
to a fixed set of versions (i.e. ignoring declared ones) through the MVC config.
By default, a version is required when API versioning is enabled, but you can turn that
off in which case the highest available version is used. You can also specify a default
version. `MissingApiVersionException` is raised resulting in a 400 response when a
version is required but not present.
[[mvc-versioning-mapping]]
== Request Mapping
[.small]#xref:web/webflux-versioning.adoc#webflux-versioning-mapping[See equivalent in the Reactive stack]#
`ApiVersionStrategy` supports the mapping of requests to annotated controller methods.
See xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-version[API Version]
for more details.

View File

@ -0,0 +1,26 @@
[[mvc-config-api-version]]
= API Version
[.small]#xref:web/webflux/config.adoc#webflux-config-api-version[See equivalent in the Reactive stack]#
To enable API versioning with a request header, use the following:
include-code::./WebConfiguration[tag=snippet,indent=0]
Alternatively, the version can be resolved from a request parameter, from a path segment,
or through a custom `ApiVersionResolver`.
TIP: When resolving from a path segment, consider configuring a path prefix once in
xref:web/webmvc/mvc-config/path-matching.adoc[Path Matching] options.
Raw version values are parsed with `SemanticVersionParser` by default, but you can use
a custom xref:web/webmvc-versioning.adoc#mvc-versioning-parser[ApiVersionParser].
"Supported" versions are transparently detected from versions declared in request mappings
for convenience, but you can also set the list of supported versions explicitly, and
ignore declared ones. Requests with a version that is not supported are rejected with an
`InvalidApiVersionException` resulting in a 400 response.
Once API versioning is configured, you can begin to map requests to
xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-version[controller methods]
according to the request version.

View File

@ -429,6 +429,86 @@ xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-co
instead.
[[mvc-ann-requestmapping-version]]
== API Version
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-version[See equivalent in the Reactive stack]#
There is no standard way to specify an API version, so you need to configure that first
through the xref:web/webmvc/mvc-config/api-version.adoc[MVC Config] along with other
config options. This results in the creation of an
xref:web/webmvc-versioning.adoc#mvc-versioning-strategy[ApiVersionStrategy] that in turn
supports request mapping.
Once API versioning is enabled, you can begin to map requests with versions.
The `@RequestMapping` version attribute supports the following:
- No value -- match any version
- Fixed version ("1.2") -- match the given version only
- Baseline version ("1.2+") -- match the given version and above
If multiple controller methods have a version less than or equal to the request version,
the one closest to the request version is considered for mapping purposes,
in effect superseding the rest.
To illustrate this, consider the following controller mappings:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
@RestController
@RequestMapping("/account/{id}")
public class AccountController {
@GetMapping // <1>
public Account getAccount() {
}
@GetMapping(version = "1.1") // <2>
public Account getAccount1_1() {
}
@GetMapping(version = "1.2+") // <3>
public Account getAccount1_2() {
}
@GetMapping(version = "1.5") // <4>
public Account getAccount1_5() {
}
}
----
<1> match any version
<2> match version 1.1
<3> match version 1.2 and above
<4> match version 1.5
======
For request with version `"1.3"`:
- (1) matches as it matches any version
- (2) does not match
- (3) matches as it matches 1.2 and above, and is *chosen* as the highest match
- (4) is higher and does not match
For request with version `"1.5"`:
- (1) matches as it matches any version
- (2) does not match
- (3) matches as it matches 1.2 and above
- (4) matches and is *chosen* as the highest match
A request with version `"1.6"` does not have a match. (1) and (3) do match, but are
superseded by (4), which does not match. In this scenario, `NotAcceptableApiVersionException`
is raised resulting in a 400 response.
NOTE: The above assumes the request version is a "supported" versions. If not it would
fail xref:web/webmvc-versioning.adoc#mvc-versioning-validation[Validation].
[[mvc-ann-requestmapping-head-options]]
== HTTP HEAD, OPTIONS
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-head-options[See equivalent in the Reactive stack]#

View File

@ -0,0 +1,32 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.docs.web.webmvc.mvcconfig.mvcconfigapiversion;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ApiVersionConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
// tag::snippet[]
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.useRequestHeader("X-API-Version");
}
}
// end::snippet[]

View File

@ -0,0 +1,31 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.docs.web.webmvc.mvcconfig.mvcconfigapiversion
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.ApiVersionConfigurer
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
// tag::snippet[]
@Configuration
class WebConfiguration : WebMvcConfigurer {
override fun configureApiVersioning(configurer: ApiVersionConfigurer) {
configurer.useRequestHeader("X-API-Version")
}
}
// end::snippet[]