skip to content

How do @Controller and @RestController relate to stereotype annotations, and what does @RestController add?

level: middleimportance: should knowfreq 55%

answer

  1. @Controller = @Component + MVC routing
  2. @RestController = @Controller + @ResponseBody
  3. @ResponseBody -> HttpMessageConverters serialize body (JSON)
  4. @Controller default return = view name
  5. composed annotation example

basics

~20 s

@Controller is a @Component specialization Spring MVC detects to route web requests to handler methods. @RestController is a composed annotation = @Controller + @ResponseBody, so every handler's return value is serialized directly to the response body (typically JSON) instead of resolving a view.

solid answer

~40 s

@Controller (org.springframework.stereotype.Controller) is a stereotype specialization of @Component; besides being registered as a bean, Spring MVC's RequestMappingHandlerMapping recognizes it and maps its @RequestMapping/@GetMapping methods to HTTP requests. By default a @Controller method's String return value is treated as a view name resolved by a ViewResolver. @RestController (org.springframework.web.bind.annotation.RestController) is itself meta-annotated with @Controller and @ResponseBody — a composed annotation. @ResponseBody makes each handler's return value written directly to the HTTP response body via HttpMessageConverters (e.g., Jackson to JSON) rather than resolved as a view. So @RestController is the idiomatic choice for REST/JSON APIs, while @Controller suits server-rendered views (Thymeleaf) — where you'd add @ResponseBody selectively for API methods.

code

java · 21 lines
java
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

@RestController // = @Controller + @ResponseBody
@RequestMapping("/api/users")
class UserApi {
    @GetMapping("/{id}")
    User get(@PathVariable Long id) {
        return new User(id, "Ada"); // serialized to JSON, not a view
    }
}

@Controller // server-rendered views
class PageController {
    @GetMapping("/home")
    String home(Model model) {
        model.addAttribute("title", "Home");
        return "home"; // resolved to a view template named "home"
    }
}

go deeper

for a junior

Know @RestController is for JSON APIs and @Controller for web pages.

for a middle

Explain @RestController = @Controller + @ResponseBody and the view-name vs body-serialization difference.

for a senior

Discuss HttpMessageConverters/content negotiation and the composed-annotation mechanics.

for a principal

Cite it as the canonical meta-annotation-composition example and reason about API vs MVC layering conventions.

**`@Controller`** (`org.springframework.stereotype.Controller`) is a stereotype: it's meta-annotated with `@Component`, so component scanning registers the class as a bean. Its special role is in **Spring MVC**: `RequestMappingHandlerMapping` specifically looks for beans annotated with `@Controller` and inspects them for `@RequestMapping` (and shortcuts `@GetMapping`, `@PostMapping`, etc.) to build the URL-to-method routing table. A plain `@Component` is **not** treated as a web controller. **Default view semantics:** in a classic `@Controller`, a handler that returns a `String` is interpreted as a **logical view name**, passed to a `ViewResolver` (e.g., Thymeleaf/JSP) to render HTML. Model data is added via a `Model`/`ModelAndView`. **`@ResponseBody`:** placing `@ResponseBody` on a handler method (or its return) tells Spring MVC to skip view resolution and instead serialize the return value straight into the HTTP response body using registered **`HttpMessageConverter`s** — e.g., `MappingJackson2HttpMessageConverter` for JSON, based on content negotiation. **`@RestController`** (`org.springframework.web.bind.annotation.RestController`) is a **composed annotation**: it is meta-annotated with both `@Controller` and `@ResponseBody`. Therefore: - It's a stereotype (scanned as a bean) and an MVC controller. - Every handler method implicitly has `@ResponseBody`, so return values are serialized to the body (JSON by default). No view resolution. **When to use which:** - **`@RestController`** — REST/JSON (or XML) APIs returning data objects. - **`@Controller`** — server-side rendered pages; add `@ResponseBody` on the specific methods that should return raw data. **Gotchas:** - Because `@RestController` includes `@ResponseBody`, returning a `String` from it writes the literal string as the body (text), **not** a view name — a common surprise when migrating from `@Controller`. - Both still require component scanning to reach the class's package. - `@RestController` is a great real-world example of Spring's meta-annotation composition pattern (same mechanism used by custom stereotypes). - For error handling, `@ControllerAdvice`/`@RestControllerAdvice` follow the same composition (the latter adds `@ResponseBody`).

  • You return the String "users" from a @RestController method. What happens?
    It's written to the response body as the literal text "users" (because @ResponseBody is implied), not resolved as a view named users.
  • Is @RestController a stereotype? Why?
    Yes — it is meta-annotated with @Controller, which is meta-annotated with @Component, so it is transitively a @Component and is picked up by component scanning.

saying these in an interview costs you the question

  • Saying @RestController resolves view names
  • Thinking a plain @Component can serve MVC requests
  • Claiming @RestController is unrelated to @Controller
  • Believing @ResponseBody is required per-method on a @RestController

context