Difference between @Controller vs @RestController in Spring MVC

The key difference between a traditional Spring MVC @Controller and the RESTful web service @RestController is the way the HTTP response body is created. While the traditional MVC controller relies on the View technology, the RESTful web service controller simply returns the object and the object data is written directly to the HTTP response as JSON/XML by registered HttpMessageConverters.

Traditional Spring MVC Workflow
The following image describe a traditional Spring MVC Request workflow:

@ImageSource-https://www.genuitec.com

  • Step 1: The browser or client sends a request to the web application.
  • Step 2: The request lands to the dispachter servlet and consult with handler mapping.
  • Step 3: The Handler mappings defined in the application context file, this has information about which is controller need to be invoked.
  • Step 4: The controller will be invoked and it can request the model for some information using DAOs and Services.
  • Step 5: After Requests are processed by the Controller and the response is returned to the DispatcherServlet with logical view name
  • Step 6: Then return to the view resolver prepared the view based on your configuration decide the which configuration (JSP, Velocity, PDF etc.) to be invoked.

For Example:

@Controller
public class AccountController {
  @RequestMapping(value="/account", method=RequestMethod.GET)
  public ModelAndView get(Long accountId) {
    //Process model object
    return new ModelAndView("account-detail", model) ;
  }
}

Spring MVC REST Workflow
The following image describe a Spring MVC REST workflow:

@ImageSource-https://www.genuitec.com

  • Step 1: The client sends a request to a web service in URI form.
  • Step 2: The request lands to the dispachter servlet and consult with handler mapping.
  • Step 3: The Handler mappings defined in the application context file, this has information about which is controller need to be invoked.
  • Step 4: The controller will be invoked and process model.
  • Step 5: Requests are processed by the Controller and the response is returned to the DispatcherServlet which then dispatches to the view.

In Traditional Spring MVC Workflow, notice that controller return the ModelAndView object with logical view name to dispactcher servlet, it is forwarded to the ViewResolver in step 6. But in the Spring MVC REST Workflow, Spring lets you return data directly from the controller, without looking for a view, using the @ResponseBody annotation on a method. As of Spring Version 4.0, this process has been more simplified by the @RestController annotation.

For Example:

Using the @ResponseBody Annotation
If any handler method of controller class is annotated with @ResponseBody, Spring converts the return value of this method and writes it to the http response automatically.

What is Behind the @ResponseBody
There is a list of HttpMessageConverters registered in the background when we enable Spring web mvc feature to the web application by using @EnableWebMvc or <mvc:annotation-driven> namespace. HTTPMessageConverter is responsible to convert the request body to a specific class and back to the response body again, depending on a predefined mime type.

Create the following @Controller class:

/**
 * 
 */
package com.doj.restapi.web.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.doj.restapi.bean.Account;
import com.doj.restapi.service.IAccountService;

/**
 * @author Dinesh.Rajput
 *
 */
@Controller
public class AccountController {
 
 @Autowired
 IAccountService accountService;
 
 @RequestMapping(value = "/", method = RequestMethod.GET)
 public @ResponseBody String home (){
  return "Spring REST Dinesh on Java!!!";
 }
 
 @RequestMapping(value = "/accounts", method = RequestMethod.GET)
 public @ResponseBody List<Account> all (){
  return accountService.list();
 }
 
 @RequestMapping(value = "/account", method = RequestMethod.POST)
 public @ResponseBody Account create (@RequestBody Account account){
  return accountService.create(account);
 }
 
 @RequestMapping(value = "/account/{accountId}", method = RequestMethod.GET)
 public @ResponseBody Account get (@PathVariable Long accountId){
  return accountService.get(accountId);
 }
 
 @RequestMapping(value = "/account", method = RequestMethod.PUT)
 public @ResponseBody Account update (@RequestBody Account account){
  return accountService.update(account);
 }
 
 @RequestMapping(value = "/account/{accountId}", method = RequestMethod.DELETE)
 public @ResponseBody void delete (@PathVariable Long accountId){
  accountService.delete(accountId);
 }
}

Notice the @ResponseBody added to each of the @RequestMapping methods in the return value.

Using the @RestController Annotation
@RestController annotation is introduced as of Spring 4.0, it is actually combination of @Controller and @ResponseBody. It is a convenience way to use this annotation instead of using @Controller and @ResponseBody annotations. By annotating the controller class with @RestController annotation, you no longer need to add @ResponseBody to all the request mapping methods. The @ResponseBody annotation is active by default.

@ImageSource-https://www.genuitec.com

Let’s use @RestController in our example, all we need to do is modify the @Controller to @RestController and remove the @ResponseBody from each method. As following:

/**
 * 
 */
package com.doj.restapi.web.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.doj.restapi.bean.Account;
import com.doj.restapi.service.IAccountService;

/**
 * @author Dinesh.Rajput
 *
 */
@RestController
public class AccountController {
 
 @Autowired
 IAccountService accountService;
 
 @GetMapping("/")
 public String home (){
  return "Spring REST Dinesh on Java!!!";
 }
 
 @GetMapping("/accounts")
 public List<Account> all (){
  return accountService.list();
 }
 
 @PostMapping("/account")
 public Account create (@RequestBody Account account){
  return accountService.create(account);
 }
 
 @GetMapping("/account/{accountId}")
 public Account get (@PathVariable Long accountId){
  return accountService.get(accountId);
 }
 
 @PutMapping("/account")
 public Account update (@RequestBody Account account){
  return accountService.update(account);
 }
 
 @DeleteMapping("/account/{accountId}")
 public void delete (@PathVariable Long accountId){
  accountService.delete(accountId);
 }
}

As per as above controller file with @RestController annotation, we can see, using this annotation is quite simple and is the preferred method for creating MVC RESTful web services if we are using Spring v4.0 and above.

Previous
Dinesh Rajput

Dinesh Rajput is the chief editor of a website Dineshonjava, a technical blog dedicated to the Spring and Java technologies. It has a series of articles related to Java technologies. Dinesh has been a Spring enthusiast since 2008 and is a Pivotal Certified Spring Professional, an author of a book Spring 5 Design Pattern, and a blogger. He has more than 10 years of experience with different aspects of Spring and Java design and development. His core expertise lies in the latest version of Spring Framework, Spring Boot, Spring Security, creating REST APIs, Microservice Architecture, Reactive Pattern, Spring AOP, Design Patterns, Struts, Hibernate, Web Services, Spring Batch, Cassandra, MongoDB, and Web Application Design and Architecture. He is currently working as a technology manager at a leading product and web development company. He worked as a developer and tech lead at the Bennett, Coleman & Co. Ltd and was the first developer in his previous company, Paytm. Dinesh is passionate about the latest Java technologies and loves to write technical blogs related to it. He is a very active member of the Java and Spring community on different forums. When it comes to the Spring Framework and Java, Dinesh tops the list!

Share
Published by
Dinesh Rajput

Recent Posts

Strategy Design Patterns using Lambda

Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…

2 years ago

Decorator Pattern using Lambda

Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…

2 years ago

Delegating pattern using lambda

Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…

2 years ago

Spring Vs Django- Know The Difference Between The Two

Technology has emerged a lot in the last decade, and now we have artificial intelligence;…

2 years ago

TOP 20 MongoDB INTERVIEW QUESTIONS 2022

Managing a database is becoming increasingly complex now due to the vast amount of data…

2 years ago

Scheduler @Scheduled Annotation Spring Boot

Overview In this article, we will explore Spring Scheduler how we could use it by…

3 years ago