skip to content

What are matrix variables in Spring MVC, how do you bind them with @MatrixVariable, and what must be configured to use them?

level: seniorimportance: nice to knowfreq 25%

answer

  1. Semicolon name=value inside a path segment
  2. @MatrixVariable, pathVar disambiguates the segment
  3. Scoped to a segment, not the whole request (unlike ?query)
  4. Must set removeSemicolonContent=false via configurePathMatch
  5. Segment must be captured by a {var}

basics

~20 s

Matrix variables are semicolon-separated name=value pairs attached to a path segment, like /cars;color=red;year=2020. You bind them with @MatrixVariable. In Spring MVC they're stripped by default, so you must enable them by turning off URL-path removeSemicolonContent.

solid answer

~40 s

Matrix variables (from Tim Berners-Lee's URI matrix notation) are key=value pairs embedded in a path segment using semicolons: /owners/42;q=alice/pets;species=dog. They attach to a specific segment, unlike query params. You bind them with @MatrixVariable — @MatrixVariable(name="q", pathVar="ownerId") String q — where pathVar disambiguates which segment's variable when the same name appears in multiple segments. They can be typed, defaulted (defaultValue), collected into a List, or grabbed wholesale into a MultiValueMap. The catch: Spring MVC's UrlPathHelper strips semicolon content by default (removeSemicolonContent=true) as a security measure, so matrix variables are ignored unless you configure it off — via WebMvcConfigurer.configurePathMatch(...) setting a UrlPathHelper with removeSemicolonContent=false. Also each matrix variable lives on a path segment that must itself be captured by a {var} in the mapping.

code

java · 20 lines
java
@Configuration
class WebConfig implements WebMvcConfigurer {
    @Override public void configurePathMatch(PathMatchConfigurer c) {
        UrlPathHelper h = new UrlPathHelper();
        h.setRemoveSemicolonContent(false); // enable matrix variables
        c.setUrlPathHelper(h);
    }
}

@RestController
class PetController {
    // GET /owners/42/pets/7;species=dog;name=rex
    @GetMapping("/owners/{ownerId}/pets/{petId}")
    Pet find(@PathVariable Long ownerId,
             @PathVariable Long petId,
             @MatrixVariable(pathVar = "petId") Map<String,String> attrs,
             @MatrixVariable(name="species", pathVar="petId") String species) {
        return svc.find(ownerId, petId, species);
    }
}

go deeper

for a junior

Usually unaware matrix variables exist; acceptable.

for a middle

Recognizes the ;k=v syntax and @MatrixVariable but may not know the config requirement.

for a senior

Explains segment scoping, pathVar disambiguation, collection binding, and the removeSemicolonContent opt-in.

for a principal

Weighs the security trade-off of enabling semicolon content and explains why most APIs choose query params instead.

## What matrix variables are **Matrix variables** encode name/value pairs **inside a path segment**, delimited by semicolons rather than the `?`/`&` of the query string: ``` GET /owners/42;status=active/pets;species=dog;name=rex ``` Here the segment `42;status=active` carries a matrix variable `status=active`, and `pets;species=dog;name=rex` carries two. Multiple values use commas or repeated names: `;colors=red,green` or `;colors=red;colors=green`. Unlike query parameters (which belong to the whole request), a matrix variable is scoped to **its segment**, which is what makes it useful for expressing per-segment qualifiers in hierarchical URLs. ## Binding with @MatrixVariable ```java @GetMapping("/owners/{ownerId}/pets/{petId}") public Pet find( @PathVariable String ownerId, @MatrixVariable(name = "species", pathVar = "petId") String species) { ... } ``` Attributes: - **name** — the matrix key. Optional if it matches the parameter name. - **pathVar** — which path segment the variable belongs to, needed when the same matrix name appears under more than one `{var}`. Without it, an ambiguous name throws an error. - **required** / **defaultValue** — like `@RequestParam`. - **Types & collections**: bind to `int`, `List<String>`, etc. Grab everything in a segment: ```java @MatrixVariable(pathVar = "petId") Map<String, String> petMatrix ``` or all matrix variables across the URL: ```java @MatrixVariable MultiValueMap<String, String> all ``` ## The mandatory configuration By default Spring MVC **removes semicolon content** from the path (`UrlPathHelper.removeSemicolonContent = true`). This is a deliberate security default (semicolons in paths have been used to bypass filters / smuggle content). Consequently **matrix variables are silently ignored** out of the box. To use them you must opt in: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper helper = new UrlPathHelper(); helper.setRemoveSemicolonContent(false); configurer.setUrlPathHelper(helper); } } ``` Without this, `@MatrixVariable` parameters resolve to null/default. ## Requirements and gotchas - **A matrix variable lives on a captured segment**: the mapping must include a `{var}` for the segment the matrix data hangs off; matrix content is parsed relative to that path variable. - **Not a query param**: `/pets?species=dog` is `@RequestParam`, not `@MatrixVariable`. Different position, different binding. - **Security posture**: turning off `removeSemicolonContent` re-enables semicolon handling; ensure downstream code and any security filters are comfortable with that. This is why matrix variables stay a niche feature. - **Encoding**: reserved characters in values should be percent-encoded. - **PathPattern**: matrix parameters are handled per-segment by the parsed `RequestPath`, which is cleaner than the legacy string-based approach, but the enable-semicolons requirement still applies. ## When to use Matrix variables suit **optional, segment-scoped qualifiers in hierarchical resources** (filtering a sub-collection differently at each level). In practice most APIs prefer query parameters for simplicity and tooling support; matrix variables remain a 'good to know' rather than an everyday tool.

  • Why do matrix variables return null unless you change configuration?
    Spring MVC's UrlPathHelper has removeSemicolonContent=true by default (a security default), which strips the ;key=value content from the path before matching. You must set it false via PathMatchConfigurer to keep matrix data.
  • When is the pathVar attribute of @MatrixVariable necessary?
    When the same matrix variable name can appear on more than one captured path segment. pathVar tells Spring which segment's copy to bind; without it an ambiguous name causes an error.

saying these in an interview costs you the question

  • Confusing matrix variables with query parameters (?k=v)
  • Not knowing they're disabled by default and forgetting removeSemicolonContent=false
  • Thinking a matrix variable applies to the whole request rather than one segment
  • Believing @MatrixVariable works without a {var} capturing the segment

context