skip to content

Controllers, Mapping & Handler Methods

Writing the handlers themselves: controller stereotypes, request mapping and path patterns, binding parameters and bodies, custom argument resolvers, and the functional WebMvc.fn alternative. This is the code interviewers ask you to write on a whiteboard.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

page 1 of 2

How does Spring MVC decide what value to pass to each parameter of a @RequestMapping controller method?

level: juniorimportance: must knowfreq 70%

answer

  1. supportsParameter -> resolveArgument
  2. first match wins in a composite
  3. RequestMappingHandlerAdapter holds the lists
  4. ModelAndViewContainer carries model + view
  5. return side = HandlerMethodReturnValueHandler

basics

~20 s

For every controller-method parameter Spring asks a list of HandlerMethodArgumentResolver strategies which one can handle it. The first that says yes resolves the value (from a request param, path variable, body, etc.) and passes it in.

solid answer

~30 s

Spring MVC controller methods have flexible signatures because RequestMappingHandlerAdapter holds an ordered list of HandlerMethodArgumentResolver strategies (a composite). For each MethodParameter it calls supportsParameter until one returns true, then that resolver's resolveArgument produces the value. Built-ins cover @RequestParam, @PathVariable, @RequestHeader, @RequestBody, @ModelAttribute, Model/Map, HttpServletRequest, Principal, RedirectAttributes, and more. Symmetrically, HandlerMethodReturnValueHandler strategies process the return value (view name, @ResponseBody, ModelAndView, etc.). This strategy-based design is why you can add or reorder parameters freely and why the framework is extensible: you can plug in your own resolver/handler without changing controller code.

code

java · 16 lines
java
// The two strategy interfaces Spring MVC iterates for every handler method.
public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter parameter);
    Object resolveArgument(MethodParameter parameter,
                           ModelAndViewContainer mavContainer,
                           NativeWebRequest webRequest,
                           WebDataBinderFactory binderFactory) throws Exception;
}

public interface HandlerMethodReturnValueHandler {
    boolean supportsReturnType(MethodParameter returnType);
    void handleReturnValue(Object returnValue,
                           MethodParameter returnType,
                           ModelAndViewContainer mavContainer,
                           NativeWebRequest webRequest) throws Exception;
}

go deeper

for a junior

Know the two interfaces exist and that Spring picks the first resolver that supports a parameter.

for a middle

Explain the composite, first-match ordering, ModelAndViewContainer, and name several built-in resolvers.

for a senior

Discuss RequestMappingHandlerAdapter wiring, catch-all ordering, and dual-SPI processors like RequestResponseBodyMethodProcessor.

for a principal

Reason about extensibility, resolver caching, and how this SPI keeps controller signatures decoupled from transport concerns.

### The problem this solves A Spring MVC controller method can declare almost any parameter list — `@RequestParam String q`, `@PathVariable Long id`, `@RequestBody Order body`, `Model model`, `HttpServletRequest req`, `Principal user`, `RedirectAttributes ra`. Something has to look at each parameter, figure out where its value comes from, and produce it before the method is invoked. That something is the **argument-resolver** subsystem. ### The core SPI Spring defines two strategy interfaces (SPIs = Service Provider Interfaces, i.e. extension points): - **`HandlerMethodArgumentResolver`** — resolves an incoming parameter value: - `boolean supportsParameter(MethodParameter parameter)` — can I handle this parameter? - `Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)` — produce the value. - **`HandlerMethodReturnValueHandler`** — processes what the method returns: - `boolean supportsReturnType(MethodParameter returnType)` - `void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)` `MethodParameter` is Spring's reflection wrapper that carries the parameter's type, index, annotations, and generic info. ### Where they live and how they run `RequestMappingHandlerAdapter` (the adapter that actually invokes `@RequestMapping` methods) builds two composites at startup: a `HandlerMethodArgumentResolverComposite` and a `HandlerMethodReturnValueHandlerComposite`. Each composite holds an **ordered list**. When a request arrives: 1. For each method parameter, the composite iterates its resolvers, calling `supportsParameter`; the **first** that returns `true` wins and its `resolveArgument` runs (results are cached per parameter for speed). 2. The method is invoked with the resolved args. 3. The return value is handed to the return-value composite, which finds the first handler whose `supportsReturnType` is true and calls `handleReturnValue`. ### The shared context object Both sides get a **`ModelAndViewContainer`** — a mutable bag that carries the model attributes and the chosen view (or a `@ResponseBody`-was-handled flag) across resolution and handling. For example the `Model` argument resolver hands the controller the container's model; a view-name return handler sets the view on the same container. ### Representative built-in resolvers - `RequestParamMethodArgumentResolver` — `@RequestParam`, and (in catch-all mode) simple types. - `PathVariableMethodArgumentResolver` — `@PathVariable`. - `RequestHeaderMethodArgumentResolver` — `@RequestHeader`. - `RequestResponseBodyMethodProcessor` — `@RequestBody` / `@ResponseBody` (implements BOTH SPIs; delegates to `HttpMessageConverter`s). - `ServletModelAttributeMethodProcessor` — `@ModelAttribute` and, in catch-all mode, complex objects (data binding). - `ModelMethodProcessor` / `MapMethodProcessor` — `Model`, `ModelMap`, `Map` parameters. - `RedirectAttributesMethodArgumentResolver` — `RedirectAttributes`. - `ServletRequestMethodArgumentResolver` — `HttpServletRequest`, `HttpSession`, `Principal`, `Locale`, etc. ### Gotchas / edge cases - **First-match wins**: order matters. The last two default resolvers are *catch-alls* (simple types → request param; everything else → model attribute), so an unannotated `String` becomes a request param and an unannotated object gets data-bound. - Some processors implement **both** SPIs (`RequestResponseBodyMethodProcessor`, `ModelAttributeMethodProcessor`), so the same class appears in both composites. - Resolution happens **before** the method runs; a resolver can throw (e.g. `MissingServletRequestParameterException`) and short-circuit into exception handling. ### When to care Day to day you rely on built-ins. You reach for this knowledge when you need a **custom parameter** (e.g. inject the current tenant or a decoded principal object) or a **custom return type** — then you implement the SPI and register it.

  • If a controller parameter has no annotation and is a simple type like String, how is it resolved?
    By the catch-all RequestParamMethodArgumentResolver (configured with useDefaultResolution=true), which is placed last, so an unannotated simple type is treated as a @RequestParam by its name.
  • What object lets the argument side and the return side communicate?
    ModelAndViewContainer — it carries the model attributes and the selected view/redirect state across resolvers, the handler invocation, and return-value handlers.

saying these in an interview costs you the question

  • Thinking Spring uses reflection parameter names alone with no strategy layer
  • Believing all resolvers run for every parameter (only the first supporting one runs)
  • Confusing HandlerMethodArgumentResolver with HandlerInterceptor or Filter

context

open as a page

How do you capture a dynamic segment from a URL in a Spring MVC controller, and how do you read its value?

level: juniorimportance: must knowfreq 85%

basics

~10 s

Put a placeholder in curly braces in the mapping, like /users/{id}, then bind it with @PathVariable on a method parameter. Spring extracts that URL segment and passes it into your method.

open as a page

What is the difference between @RequestBody and @ModelAttribute in a Spring MVC controller?

level: juniorimportance: must knowfreq 78%

basics

~10 s

@RequestBody reads the raw request body (usually JSON) and deserializes it into an object using a message converter. @ModelAttribute binds request parameters (query string or HTML form fields) onto an object via its setters.

open as a page

What is @RequestMapping in Spring MVC, and how do the shortcuts @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, and @PatchMapping relate to it?

level: juniorimportance: must knowfreq 90%

basics

~10 s

@RequestMapping maps HTTP requests (by URL path and method) to controller methods. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, and @PatchMapping are shortcuts for @RequestMapping with the HTTP method already fixed (GET, POST, PUT, DELETE, PATCH).

open as a page

What is the difference between @RequestParam and @PathVariable, and when do you use each?

level: juniorimportance: must knowfreq 85%

basics

~20 s

@PathVariable pulls a value out of the URL path itself (e.g. /users/42 -> id=42). @RequestParam reads a query-string parameter after the ? (e.g. /users?id=42) or a form field. You use @PathVariable to identify a resource, @RequestParam to filter/paginate/search.

open as a page

What is the difference between @Controller and @RestController in Spring MVC?

level: juniorimportance: must knowfreq 85%

basics

~10 s

@Controller returns view names that a template engine renders into HTML. @RestController is @Controller plus @ResponseBody, so every method's return value becomes the HTTP response body (usually JSON) instead of a view name.

open as a page

What does RedirectAttributes do, and what is the difference between addAttribute and addFlashAttribute?

level: middleimportance: must knowfreq 60%

basics

~20 s

RedirectAttributes controls data passed through a redirect. addAttribute puts values in the redirect URL (path/query params, visible). addFlashAttribute stores objects server-side in a flash map that survives exactly one redirect, so they aren't in the URL and can be complex objects.

open as a page

What do the consumes and produces attributes do on @RequestMapping / the mapping shortcuts, and how do they interact with request headers?

level: middleimportance: must knowfreq 72%

basics

~20 s

consumes restricts a handler to requests whose Content-Type matches (what the endpoint accepts in the body). produces restricts by the client's Accept header and sets the response content type. Non-matching requests get 415 (Unsupported Media Type) or 406 (Not Acceptable).

open as a page

How do you make a @RequestParam optional? Explain required, defaultValue, and Optional, and how they interact.

level: middleimportance: must knowfreq 75%

basics

~20 s

By default @RequestParam is required, so a missing param -> 400. Make it optional with required=false (value is null when absent), or give defaultValue="..." (used when absent, and implies not-required), or declare the type as Optional<T> or a nullable type.

open as a page

What is the mass-assignment (over-posting) risk in Spring MVC data binding, and how do you defend against it?

level: seniorimportance: must knowfreq 55%

basics

~20 s

@ModelAttribute binds every request parameter whose name matches a property, so an attacker can add extra params (like admin=true) to set fields the form never exposed. Defend with setAllowedFields/setDisallowedFields in @InitBinder, or bind to a narrow DTO instead of the entity.

open as a page

What is the difference between Model, ModelMap, and ModelAndView, and how do controller model attributes reach the view?

level: juniorimportance: should knowfreq 55%

basics

~20 s

Model is an interface for adding named attributes to the view. ModelMap is a Map-based implementation of that idea. ModelAndView bundles the model AND the view name/object together as a return value. Attributes you add become variables the view template can render.

open as a page

What is the functional endpoint model (WebMvc.fn) in Spring MVC, and what are its core building blocks?

level: juniorimportance: should knowfreq 35%

basics

~10 s

WebMvc.fn is an alternative to @Controller where you define routes in code. A RouterFunction maps a RequestPredicate (like GET /hello) to a HandlerFunction that takes a ServerRequest and returns a ServerResponse.

open as a page

How do you read request data with ServerRequest and build responses with ServerResponse in a functional handler?

level: middleimportance: should knowfreq 30%

basics

~10 s

ServerRequest gives you the body via request.body(Type.class), path variables via pathVariable("id"), and query params via param("q"). ServerResponse is a builder: ServerResponse.ok().body(obj) or ServerResponse.created(uri).build() to set status, headers, and body.

open as a page

How do you constrain a path variable to a specific format, e.g. only digits or a fixed pattern?

level: middleimportance: should knowfreq 55%

basics

~20 s

Add a regex after a colon inside the braces: {id:[0-9]+} matches only digits. Spring uses the regex to decide whether the URL matches that segment, so non-matching URLs fall through to other mappings or 404.

open as a page

What is WebDataBinder and what can you configure with an @InitBinder method?

level: middleimportance: should knowfreq 60%

basics

~20 s

WebDataBinder binds request parameters onto a target object and converts their types. An @InitBinder method receives that binder before binding so you can register custom editors/converters, restrict which fields may be bound, mark required fields, or attach a Validator.

open as a page

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

level: middleimportance: should knowfreq 48%

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.

open as a page

How does @ResponseBody behave at the class level versus the method level, and how do you return both views and JSON from one controller?

level: middleimportance: should knowfreq 55%

basics

~20 s

At class level, @ResponseBody applies to every handler method (that's what @RestController does). At method level, it applies only to that one method. So on a plain @Controller you put @ResponseBody on just the JSON methods and leave the rest returning view names.

open as a page

How do you implement and register a custom HandlerMethodArgumentResolver, and where does it sit relative to the built-in resolvers?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Implement HandlerMethodArgumentResolver with supportsParameter (usually keyed on a custom annotation or type) and resolveArgument (pull the value from the request). Register it by overriding WebMvcConfigurer.addArgumentResolvers. It runs after the built-in resolvers.

open as a page

What is HandlerMethodReturnValueHandler, and how does Spring decide what to do with whatever a controller method returns?

level: seniorimportance: should knowfreq 40%

basics

~20 s

It's the return-side strategy interface. After the method runs, Spring finds the first HandlerMethodReturnValueHandler whose supportsReturnType is true and calls handleReturnValue, which turns the return value into a view, a serialized body, a redirect, etc.

open as a page

How do nested routes (nest / path) and filter functions (filter / before / after / onError) work in WebMvc.fn?

level: seniorimportance: should knowfreq 28%

basics

~20 s

nest() (or path()) groups routes under a shared predicate like /users, so you don't repeat it. Inside a nest you can attach filters that apply only to those routes: filter() wraps the handler, before()/after() transform the request/response, and onError() maps exceptions to responses.

open as a page

How are functional endpoints registered and dispatched, and how do they coexist with annotated @Controllers in the same application?

level: seniorimportance: should knowfreq 22%

basics

~20 s

You expose RouterFunction<ServerResponse> beans. Spring's RouterFunctionMapping combines them and the DispatcherServlet dispatches matching requests to them. Annotated controllers use RequestMappingHandlerMapping. Both work together; by default the annotated handler mapping is consulted before the functional one.

open as a page

Explain the wildcard tokens in Spring path patterns: ?, *, and **. How do they differ and where can each appear?

level: seniorimportance: should knowfreq 50%

basics

~20 s

? matches exactly one character within a segment. * matches zero or more characters within a single path segment (no slash). ** matches zero or more whole segments and, under PathPattern, must be the last element. You can capture ** with {*name}.

open as a page

How do PropertyEditors and the ConversionService differ for converting request values, and which should you prefer?

level: seniorimportance: should knowfreq 48%

basics

~10 s

PropertyEditors are the old JavaBeans mechanism: stateful, not thread-safe, registered per binding, only String↔Object. ConversionService (Converter/Formatter) is the modern, stateless, thread-safe, type-to-any-type system registered globally. Prefer the ConversionService.

open as a page

How does Spring choose between multiple candidate @RequestMapping handlers, and what path pattern features (variables, wildcards) participate in matching?

level: seniorimportance: should knowfreq 40%

basics

~20 s

When several mappings match, Spring picks the most specific one using RequestMappingInfo comparison: exact paths beat path variables beat wildcards, and more predicates (method, params, headers, produces) make a mapping more specific. Truly equal matches throw an ambiguous-mapping error.

open as a page

How do you bind multi-valued or dynamic query parameters — repeated params, a Map of all params, and MultiValueMap?

level: seniorimportance: should knowfreq 45%

basics

~10 s

For a repeated param (?tag=a&tag=b) bind List<String> or String[]. To grab every query param at once, use @RequestParam Map<String,String> (one value per name) or @RequestParam MultiValueMap<String,String> (preserves all values per name).

open as a page

Explain how @RestController is composed from stereotype meta-annotations, and how component scanning discovers it as a bean.

level: seniorimportance: should knowfreq 45%

basics

~20 s

@RestController is a composed annotation carrying @Controller (which itself carries @Component) plus @ResponseBody. Spring's component scanning finds @Component transitively through these meta-annotations, so a @RestController class is auto-registered as a bean and recognized as a web handler.

open as a page

Walk through how the DispatcherServlet decides whether a controller's return value is a view or a serialized body.

level: seniorimportance: should knowfreq 35%

basics

~20 s

After the handler runs, RequestMappingHandlerAdapter passes the return value to a chain of return-value handlers. If @ResponseBody is present (method or class), RequestResponseBodyMethodProcessor serializes it via HttpMessageConverters. Otherwise it's treated as a view name and resolved by a ViewResolver.

open as a page

Compare PathPatternParser with the legacy AntPathMatcher. Why did Spring switch defaults, and what behavioral differences should you know?

level: principalimportance: should knowfreq 40%

basics

~20 s

AntPathMatcher parses patterns as strings on every request; PathPatternParser pre-compiles each pattern once into a reusable PathPattern, so matching is much faster. PathPatternParser is the modern default and adds {*name} capture, but restricts ** to the pattern's end.

open as a page

Walk through how Spring resolves a @RequestBody parameter, including converter selection and failure modes.

level: principalimportance: should knowfreq 38%

basics

~20 s

A HandlerMethodArgumentResolver reads the request's InputStream, picks an HttpMessageConverter that supports the target type and the request's Content-Type, and uses it (e.g. Jackson) to deserialize the body. No match yields 415; a malformed body yields HttpMessageNotReadableException (400).

open as a page

showing 1–30 of 36