skip to content

@Controller vs @RestController

@RestController is just @Controller plus @ResponseBody, which is why one returns view names and the other serializes the return value. A quick question that reveals whether you know what @ResponseBody actually switches on.

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

questions

5

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

level: juniorimportance: must knowfreq 85%

answer

  1. @RestController = @Controller + @ResponseBody
  2. @Controller -> view name -> ViewResolver -> HTML
  3. @ResponseBody -> HttpMessageConverter -> body (JSON)
  4. String from @Controller = view name gotcha
  5. RestController since Spring 4.0

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.

solid answer

~40 s

@Controller is the classic Spring MVC stereotype: its handler methods typically return a logical view name (a String) that a ViewResolver maps to a template (Thymeleaf, JSP) rendered into HTML. @RestController is a convenience annotation meta-annotated with both @Controller and @ResponseBody. @ResponseBody tells Spring to serialize the return value directly into the HTTP response body using an HttpMessageConverter (e.g. Jackson for JSON) rather than interpreting it as a view name. So you use @RestController for REST/JSON APIs and @Controller for server-rendered web pages. With plain @Controller you can still return JSON per-method by adding @ResponseBody to that method. Both are component-scanned as beans and both support @RequestMapping/@GetMapping etc.

code

java · 16 lines
java
// View-returning controller
@Controller
class PageController {
    @GetMapping("/home")
    String home(Model model) {
        model.addAttribute("user", "Alice");
        return "home"; // logical view name -> templates/home.html
    }
}

// JSON API controller (every method is @ResponseBody)
@RestController
class ApiController {
    @GetMapping("/api/user")
    User user() { return new User("Alice"); } // serialized to JSON
}

go deeper

for a junior

Must know the one-line difference: view names vs response bodies, and that @RestController = @Controller + @ResponseBody.

for a middle

Should explain @ResponseBody triggers HttpMessageConverter serialization and know the String-as-view-name gotcha.

for a senior

Should discuss when server-rendering vs REST is appropriate and how ResponseEntity fits both.

for a principal

Frames it as a rendering-strategy decision (SSR vs API), understands the meta-annotation composition and content negotiation implications.

## The two stereotypes Spring MVC handles web requests with **handler methods** on controller beans. How Spring interprets a handler method's *return value* depends on whether `@ResponseBody` semantics are in play. ### @Controller `@Controller` is a **stereotype annotation** (a specialization of `@Component`) marking a class as a web controller. By default, when a handler method returns a `String`, Spring treats it as a **logical view name**. A `ViewResolver` (e.g. `ThymeleafViewResolver`, `InternalResourceViewResolver` for JSP) resolves that name to a `View`, which renders a template — typically producing HTML. The method usually also populates a `Model` with data the template reads. ```java @Controller class PageController { @GetMapping("/home") String home(Model model) { model.addAttribute("user", "Alice"); return "home"; // -> resolves to templates/home.html } } ``` ### @ResponseBody `@ResponseBody` changes the contract: the return value is **not** a view name. Instead Spring runs it through the configured `HttpMessageConverter` chain and writes the serialized result straight into the response body. For an object, `MappingJackson2HttpMessageConverter` produces JSON; for a `String`, `StringHttpMessageConverter` writes the raw text. ### @RestController `@RestController` is simply a **composed annotation** — it is itself meta-annotated with `@Controller` and `@ResponseBody`: ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Controller @ResponseBody public @interface RestController { ... } ``` Applying `@ResponseBody` at the **class level** means every handler method inherits body-serialization behavior. So `@RestController` = "a controller where every method returns response bodies (JSON/XML), never view names." ```java @RestController class ApiController { @GetMapping("/api/user") User user() { return new User("Alice"); } // -> {"name":"Alice"} } ``` ### When to use which - **@Controller** — server-side rendered pages (Thymeleaf/JSP), returning view names; also for methods that redirect (`return "redirect:/login"`) or forward. - **@RestController** — JSON/XML REST APIs consumed by SPAs, mobile apps, or other services. ### Gotchas - With plain `@Controller` a method returning a `String` is a **view name** — a common bug when you meant to return raw text. Add `@ResponseBody` (or return `ResponseEntity`) to send the literal string. - `@RestController` was added in **Spring 4.0**; before that you wrote `@Controller` + `@ResponseBody` on every method. - Both still support `ResponseEntity<T>` returns, which give full control over status/headers regardless of the class stereotype.

  • If you have a plain @Controller and a method returns the String "success", what does the client receive?
    Not the text "success" — Spring treats it as a logical view name and asks the ViewResolver to render a "success" template, likely producing a 404/500 if none exists. To return the literal text, add @ResponseBody or return ResponseEntity<String>.
  • Can you mix view-returning and body-returning methods in one class?
    Yes with @Controller: annotate only the JSON methods with @ResponseBody, leave the rest returning view names. You cannot un-set @ResponseBody on a @RestController, so a RestController is all-body.

saying these in an interview costs you the question

  • Saying @Controller cannot ever return JSON (it can, with per-method @ResponseBody)
  • Thinking @RestController is a totally separate/unrelated annotation rather than @Controller + @ResponseBody
  • Believing a String returned from @RestController becomes a view name (it becomes the raw body)

context

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

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

As an architect, how do you decide between @Controller (server-rendered) and @RestController (API) styles, and what are the consequences of that choice?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Use @RestController for stateless JSON/XML APIs consumed by SPAs, mobile apps, or other services. Use @Controller with view templates when the server renders HTML directly. The choice drives your whole front-end architecture, state handling, and cross-cutting concerns.

open as a page