[[webflux-ann-matrix-variables]]
= Matrix Variables

[.small]#xref:web/webmvc/mvc-controller/ann-methods/matrix-variables.adoc[See equivalent in the Servlet stack]#

{rfc-site}/rfc3986#section-3.3[RFC 3986] discusses name-value pairs in
path segments. In Spring WebFlux, we refer to those as "`matrix variables`" based on an
https://www.w3.org/DesignIssues/MatrixURIs.html["`old post`"] by Tim Berners-Lee, but they
can be also be referred to as URI path parameters.

Matrix variables can appear in any path segment, with each variable separated by a semicolon and
multiple values separated by commas -- for example, `"/cars;color=red,green;year=2012"`. Multiple
values can also be specified through repeated variable names -- for example,
`"color=red;color=green;color=blue"`.

Unlike Spring MVC, in WebFlux, the presence or absence of matrix variables in a URL does
not affect request mappings. In other words, you are not required to use a URI variable
to mask variable content. That said, if you want to access matrix variables from a
controller method, you need to add a URI variable to the path segment where matrix
variables are expected. The following example shows how to do so:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	// GET /pets/42;q=11;r=22

	@GetMapping("/pets/{petId}")
	public void findPet(@PathVariable String petId, @MatrixVariable int q) {

		// petId == 42
		// q == 11
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	// GET /pets/42;q=11;r=22

	@GetMapping("/pets/{petId}")
	fun findPet(@PathVariable petId: String, @MatrixVariable q: Int) {

		// petId == 42
		// q == 11
	}
----
======


Given that all path segments can contain matrix variables, you may sometimes need to
disambiguate which path variable the matrix variable is expected to be in,
as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	// GET /owners/42;q=11/pets/21;q=22

	@GetMapping("/owners/{ownerId}/pets/{petId}")
	public void findPet(
			@MatrixVariable(name="q", pathVar="ownerId") int q1,
			@MatrixVariable(name="q", pathVar="petId") int q2) {

		// q1 == 11
		// q2 == 22
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@GetMapping("/owners/{ownerId}/pets/{petId}")
	fun findPet(
			@MatrixVariable(name = "q", pathVar = "ownerId") q1: Int,
			@MatrixVariable(name = "q", pathVar = "petId") q2: Int) {

		// q1 == 11
		// q2 == 22
	}
----
======

You can define a matrix variable may be defined as optional and specify a default value
as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	// GET /pets/42

	@GetMapping("/pets/{petId}")
	public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) {

		// q == 1
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	// GET /pets/42

	@GetMapping("/pets/{petId}")
	fun findPet(@MatrixVariable(required = false, defaultValue = "1") q: Int) {

		// q == 1
	}
----
======

To get all matrix variables, use a `MultiValueMap`, as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

	@GetMapping("/owners/{ownerId}/pets/{petId}")
	public void findPet(
			@MatrixVariable MultiValueMap<String, String> matrixVars,
			@MatrixVariable(pathVar="petId") MultiValueMap<String, String> petMatrixVars) {

		// matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
		// petMatrixVars: ["q" : 22, "s" : 23]
	}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

	@GetMapping("/owners/{ownerId}/pets/{petId}")
	fun findPet(
			@MatrixVariable matrixVars: MultiValueMap<String, String>,
			@MatrixVariable(pathVar="petId") petMatrixVars: MultiValueMap<String, String>) {

		// matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
		// petMatrixVars: ["q" : 22, "s" : 23]
	}
----
======
