Difference Between @RestController and @Controller in Spring (Deep Explanation)
Developers often get confused between @Controller and @RestController in Spring. Although both are used to handle web requests, they are designed for different application architectures: MVC (server-side rendering) and REST APIs.
This in-depth guide explains not only the differences but also:
- Internal Working of Both Annotations
- ViewResolver vs HttpMessageConverter flow
- Real-world project use cases
- Common mistakes & pitfalls
- Architecture diagrams
- Interview-ready explanations
🔍 What Are @Controller and @RestController?
@Controller
Used in traditional Spring MVC applications to return JSP/HTML/Thymeleaf views.
@RestController
Used in REST APIs to return JSON/XML directly to clients.
🆚 Deep Difference Table
| Feature | @Controller | @RestController |
|---|---|---|
| Primary Purpose | MVC — Returns views (HTML/JSP/Thymeleaf) | REST API — Returns JSON/XML |
| Annotation Behavior | Requires @ResponseBody to return JSON |
Internally = @Controller + @ResponseBody |
| Typical Return Value | View name (String) | Object → converted to JSON |
| Handled By | ViewResolver | HttpMessageConverter |
| Common Use Case | Web apps (UI pages) | REST clients (Angular/React/Mobile) |
| Response Type | HTML Page | JSON/XML |
🧠 Internal Flow: How Does @Controller Work?
Client → DispatcherServlet → Controller Method → ViewResolver → HTML/JSP/Thymeleaf
🧠 Internal Flow: How Does @RestController Work?
Client → DispatcherServlet → RestController Method → HttpMessageConverter → JSON Response
@ResponseBody.📘 Example: @Controller
@Controller
public class HomeController {
@GetMapping("/home")
public String homePage(Model model) {
model.addAttribute("title", "Welcome");
return "home"; // → home.html or home.jsp
}
@GetMapping("/api/msg")
@ResponseBody
public String msg() {
return "JSON from Controller using @ResponseBody";
}
}
📘 Example: @RestController
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/hello")
public String hello() {
return "Hello from REST";
}
@GetMapping("/user")
public User getUser() {
return new User(1L, "John", "john@example.com");
}
}
🧩 Hidden Differences Most Developers Don’t Know
1. Error Handling Works Differently
REST controllers use HttpMessageConverters, so exceptions often become JSON error responses.
2. @Controller Supports Server-Side Rendering
Useful when building dashboards, admin panels, or HTML pages.
3. @RestController Avoids View Resolution
This makes performance faster for APIs because no template rendering is involved.
4. Method-Level Overrides Possible
You can use @ResponseBody inside an MVC @Controller to behave like a REST endpoint.
🎯 When Should You Use Which?
Use @Controller When:
- Building HTML-based UI (JSP/Thymeleaf)
- Server-side rendering (SSR)
- Admin dashboards
- Traditional Spring MVC architecture
Use @RestController When:
- Building REST APIs
- Returning JSON/XML
- Microservices architecture
- Frontend frameworks like Angular/React/Vue
- Mobile apps (Android/iOS) requesting data
🚫 Common Mistakes Developers Make
- Trying to return a view from
@RestController→ won’t work - Using
@Controllerunnecessarily for APIs - Forgetting
@ResponseBodyin MVC when returning JSON - Returning large objects → performance issues
🔥 Interview-Worthy Explanation (Short & Clear)
@Controller is used for MVC applications and returns views.
@RestController returns JSON/XML directly and is used for REST APIs.
It is equivalent to @Controller + @ResponseBody.
❓FAQs
1. Can @RestController return a view?
No. It always returns response body (JSON/text/XML).
2. Can @Controller return JSON?
Yes — but you must use @ResponseBody.
3. Which one is better for microservices?
@RestController.
4. Is @RestController slower or faster?
It’s faster for APIs because it skips view rendering.
5. Does @RestController support templating engines?
No. It's designed only for RESTful responses.
✅ Conclusion
The difference between @Controller and @RestController is simple yet crucial. Use @Controller when your output is HTML. Use @RestController when your output is JSON. A clear understanding of both is essential for building clean, scalable Spring Boot applications.