skip to content

View Resolution & Thymeleaf

For server-rendered pages, a logical view name is resolved to a View and rendered with the Model, including the redirect: and forward: prefixes. Worth knowing even in an API-first world, because interviewers contrast it with @ResponseBody bypassing views entirely.

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

questions

5

In Spring MVC, when a controller method returns the String "home", how does that turn into an actual HTML page? Walk through logical view names, the Model, and the ViewResolver.

level: juniorimportance: must knowfreq 70%

answer

  1. logical name != file path
  2. ViewResolver maps name -> View
  3. Model carries data, not the return value
  4. prefix + name + suffix
  5. @ResponseBody bypasses resolution

basics

~10 s

The returned String is a logical view name, not a file path. A ViewResolver maps it to a real template (e.g. "home" -> /WEB-INF/home.jsp or home.html). Data reaches the view through a Model object.

solid answer

~40 s

A controller that doesn't use @ResponseBody returns a logical view name — a short symbolic String like "home", decoupled from any physical file. After the handler runs, DispatcherServlet asks its configured ViewResolver(s) to translate that name into a View object. For example InternalResourceViewResolver with prefix "/WEB-INF/views/" and suffix ".jsp" turns "home" into "/WEB-INF/views/home.jsp"; ThymeleafViewResolver resolves "home" to templates/home.html. The controller supplies data by adding attributes to a Model (or ModelMap) parameter Spring injects; those attributes become accessible in the template. The View then renders, writing HTML to the response. This indirection lets you swap the view technology or template location without touching controller code.

code

java · 12 lines
java
@Controller
public class HomeController {

    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("greeting", "Hello, world");
        // "home" is a LOGICAL view name, not a path.
        // A ViewResolver maps it -> templates/home.html (Thymeleaf)
        //                       or -> /WEB-INF/views/home.jsp (JSP)
        return "home";
    }
}

go deeper

for a junior

Must know that the String is a logical name resolved by a ViewResolver, and that Model carries data.

for a middle

Should explain the DispatcherServlet -> ViewResolver -> View render sequence and prefix/suffix mapping.

for a senior

Should contrast view resolution with @ResponseBody and mention RequestToViewNameTranslator for void returns.

for a principal

Frames view resolution as a pluggable strategy enabling technology-agnostic controllers and multi-resolver chains.

## The problem view resolution solves A Spring MVC controller handles a request and usually needs to produce an HTML page. Rather than hard-coding a file path or writing HTML in Java, the controller returns a **logical view name** — a short symbolic String like `"home"`, `"users/list"`, or `"error"`. This name is deliberately decoupled from any physical template file. Something else — a **ViewResolver** — turns that name into a concrete page. ## The players - **`DispatcherServlet`**: the front controller. Every request goes through it. After the handler (your controller method) runs, it drives view resolution and rendering. - **Logical view name**: the `String` your method returns (when not annotated `@ResponseBody`). - **`Model` / `ModelMap` / `ModelAndView`**: a map of named attributes the controller wants to expose to the view. You add data with `model.addAttribute("user", user)`. - **`ViewResolver`**: a strategy interface, `View resolveViewName(String viewName, Locale locale)`. It maps the logical name to a `View`. - **`View`**: knows how to render — `void render(Map model, HttpServletRequest, HttpServletResponse)`. It writes the actual bytes to the response. ## The flow, step by step 1. Request arrives; `DispatcherServlet` dispatches to the matching handler method. 2. The method populates the `Model` and returns `"home"`. 3. `DispatcherServlet` loops over its ordered `ViewResolver` beans, calling `resolveViewName("home", locale)` until one returns a non-null `View`. 4. The chosen `View` (e.g. a JSP wrapped in an `InternalResourceView`, or a Thymeleaf template view) is rendered with the model attributes. 5. HTML is written to the response. ## Concrete resolver examples - **`InternalResourceViewResolver`** (JSP): configured with a `prefix` and `suffix`. `"home"` → `/WEB-INF/views/home.jsp`. - **`ThymeleafViewResolver`** (Spring Boot's default when `spring-boot-starter-thymeleaf` is present): `"home"` → `classpath:/templates/home.html`. ## How data reaches the view You don't return the data — you put it in the `Model`. Spring injects a `Model` if you declare it as a parameter: ```java @GetMapping("/") public String home(Model model) { model.addAttribute("greeting", "Hello"); return "home"; } ``` In a Thymeleaf template, `${greeting}` reads that attribute. In JSP it's a request attribute. ## Common gotchas - **Returning `void`**: if the method returns void and doesn't write the response itself, Spring derives a default view name from the request path (`RequestToViewNameTranslator`). Usually you should return the name explicitly. - **Confusing a view name with a URL**: `"home"` is not `/home`. It's a symbolic key the resolver expands. - **`@ResponseBody` / `@RestController`**: these bypass view resolution entirely — the return value is serialized to the body (JSON etc.). That's a different mechanism (message conversion). - **Wrong prefix/suffix** silently yields a 404-on-forward or a missing-template error. ## When to use Server-side rendered pages (traditional MVC apps, admin panels, email HTML). For JSON APIs you skip views and use `@ResponseBody`.

  • What happens if the controller method returns void?
    Spring uses RequestToViewNameTranslator to derive a default logical view name from the request URL (e.g. /home -> "home"). This is implicit and fragile; most teams return the name explicitly. If the method writes to the HttpServletResponse itself, no view is resolved.
  • How is returning "home" different from @RestController returning "home"?
    With @Controller (no @ResponseBody), "home" is a view name resolved to a template. With @RestController (implies @ResponseBody), the literal String "home" is written to the response body via an HttpMessageConverter — no view resolution occurs.

saying these in an interview costs you the question

  • Thinking the returned String is a URL or file path that Spring opens directly
  • Believing the controller's return value carries the model data
  • Confusing view resolution with @ResponseBody/JSON serialization

context

open as a page

Explain the "redirect:" and "forward:" prefixes on a view name. How do they differ, and how do you carry data across a redirect without exposing it as query params?

level: middleimportance: must knowfreq 65%

basics

~10 s

"redirect:/x" sends a 302 telling the browser to request /x again (new request). "forward:/x" hands off server-side to another handler in the same request. To pass data over a redirect safely, use RedirectAttributes.addFlashAttribute.

open as a page

Compare InternalResourceViewResolver (JSP) with ThymeleafViewResolver. How does Spring Boot auto-configure Thymeleaf, and why is Thymeleaf preferred for modern server-side rendering?

level: middleimportance: should knowfreq 45%

basics

~20 s

InternalResourceViewResolver resolves names to JSPs via a servlet forward (prefix/suffix, files under /WEB-INF). ThymeleafViewResolver resolves them to .html templates in classpath:/templates rendered by the Thymeleaf engine. Boot auto-configures Thymeleaf when the starter is on the classpath.

open as a page

What is ContentNegotiatingViewResolver and how does it decide which view to render? Explain content negotiation via Accept header vs path extension vs request parameter.

level: seniorimportance: should knowfreq 35%

basics

~20 s

It's a ViewResolver that picks a view based on the requested media type (content negotiation). It determines the desired MIME type (from Accept header, URL extension, or a request param), then delegates to other ViewResolvers/Views and returns the one matching that media type.

open as a page

You configure multiple ViewResolvers in one application. Explain how DispatcherServlet walks the resolver chain, the role of Ordered/order, and the classic pitfall with InternalResourceViewResolver in a mixed chain.

level: principalimportance: should knowfreq 25%

basics

~20 s

DispatcherServlet holds an ordered list of ViewResolvers and calls each in order until one returns a non-null View. Order comes from the Ordered interface / order property. InternalResourceViewResolver always returns a View (never null), so it must be last or it shadows the others.

open as a page