skip to content

How do the params and headers attributes of @RequestMapping narrow request matching, and what expression forms do they support?

level: middleimportance: should knowfreq 48%

answer

  1. params -> query/form params; headers -> HTTP headers
  2. present / !absent / =value / !=value
  3. AND across multiple expressions
  4. Fail predicate = 404, wrong verb = 405
  5. Prefer consumes/produces over headers for Content-Type

basics

~20 s

params and headers add extra conditions: a handler only matches if the request has the given query parameters / headers. You can require presence ("debug"), absence ("!debug"), or a specific value ("type=admin"). They let two handlers share a path but split on a param or header value.

solid answer

~40 s

params and headers are additional request predicates on top of path and method. params matches on query parameters (or form-encoded params); headers matches on HTTP request headers. Both support the same expression syntax: "name" requires the param/header to be present; "!name" requires it to be absent; "name=value" requires an exact value; "name!=value" requires a differing value. This lets you disambiguate handlers on the same URL and verb — e.g. @GetMapping(path="/users", params="role=admin") vs params="role=guest". They are useful for feature flags, legacy query-style dispatch, or API-version headers. Note headers can also express media types, but for Content-Type/Accept the dedicated consumes/produces attributes are preferred because they yield the correct 415/406 semantics. A request that matches path+method but fails a params/headers predicate results in a 404, not a 405.

code

java · 20 lines
java
@RestController
@RequestMapping("/users")
public class UserRouting {

    // GET /users?role=admin
    @GetMapping(params = "role=admin")
    public List<User> admins() { ... }

    // GET /users?role=guest
    @GetMapping(params = "role=guest")
    public List<User> guests() { ... }

    // Only when the X-API-Version header equals 2
    @GetMapping(headers = "X-API-Version=2")
    public List<User> v2() { ... }

    // Must be present AND flag absent
    @GetMapping(params = { "q", "!debug" })
    public List<User> search(@RequestParam String q) { ... }
}

go deeper

for a junior

Aware params/headers can further restrict a mapping.

for a middle

Knows the four expression forms and params vs @RequestParam distinction.

for a senior

Explains 404-vs-405 semantics and why consumes/produces beat headers for media types.

for a principal

Weighs header/param versioning trade-offs against path/Accept versioning and route discoverability.

**Purpose.** Beyond path and HTTP method, `@RequestMapping` (and the shortcuts) can require certain **query parameters** (`params`) or **HTTP headers** (`headers`) to be present, absent, or equal to a value. These are *matching predicates*: they decide whether a handler is even eligible, not just how it reads input. **Expression syntax (identical for both).** - `"myParam"` — the parameter/header must be **present** (any value). - `"!myParam"` — the parameter/header must be **absent**. - `"myParam=value"` — must be present **and equal** `value`. - `"myParam!=value"` — present with a value **not equal** to `value` (or, for negation semantics, must not equal). Multiple expressions can be combined in an array; **all** must be satisfied (logical AND): `params = {"type=admin", "active"}`. **`params` details.** Matches against the servlet request parameters, which include both URL query-string parameters and `application/x-www-form-urlencoded` body params. Classic use: dispatch `GET /users?role=admin` and `GET /users?role=guest` to different handlers, or reject requests missing a required flag. It is *not* a substitute for `@RequestParam` — `@RequestParam` binds a value into a method argument; `params` decides whether the method runs at all. They are often used together. **`headers` details.** Matches arbitrary request headers, e.g. `headers = "X-API-Version=2"` to route by a custom versioning header, or `headers = "X-Requested-With=XMLHttpRequest"` to serve AJAX callers. While you *can* write `headers = "Content-Type=application/json"`, prefer `consumes`/`produces` for the Content-Type/Accept headers: they integrate with content negotiation and return the semantically correct **415/406** instead of a generic 404. **Status-code behavior.** If the path matches but the HTTP method doesn't, Spring returns **405 Method Not Allowed**. If path (and method) match but a `params`/`headers` predicate fails and no other handler matches, the request is unmatched → **404 Not Found**. This is a subtle but important distinction in interviews. **Gotchas.** - Header names are case-insensitive per HTTP; parameter names are case-sensitive. - Over-using `params`/`headers` for versioning creates hard-to-discover routes; many teams prefer explicit path or `Accept` versioning. - Best-match selection counts these predicates: a handler with more specific params/headers conditions wins over a less specific one on the same path. - `params="a!=b"` still requires resolution rules; presence/absence forms are the most common and least surprising. **When to use.** Feature-flag routing, splitting a legacy `?action=` style endpoint, custom-header API versioning, or requiring a mandatory flag. For content types, reach for `consumes`/`produces` instead.

  • If the path matches but a required params condition fails and nothing else matches, is it a 404 or a 405?
    404 Not Found. A 405 is only returned when the path matches but the HTTP method is wrong; a failed params/headers predicate simply means no handler matched.
  • How is params different from @RequestParam?
    params is a mapping predicate deciding whether the handler is eligible to run. @RequestParam binds a parameter's value into a method argument once the handler is selected. They solve different problems and are often combined.

saying these in an interview costs you the question

  • Confusing params with @RequestParam binding
  • Thinking a failed params/headers match returns 405
  • Using headers for Content-Type instead of consumes and expecting 415
  • Assuming multiple param expressions are OR'd (they are AND'd)

context