What is the difference between @Controller and @RestController in Spring MVC?
answer
- @RestController = @Controller + @ResponseBody
- @Controller -> view name -> ViewResolver -> HTML
- @ResponseBody -> HttpMessageConverter -> body (JSON)
- String from @Controller = view name gotcha
- 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// 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
Must know the one-line difference: view names vs response bodies, and that @RestController = @Controller + @ResponseBody.
Should explain @ResponseBody triggers HttpMessageConverter serialization and know the String-as-view-name gotcha.
Should discuss when server-rendering vs REST is appropriate and how ResponseEntity fits both.
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)