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.
- Spring MVC Web Tutorial
- Spring MVC Interview Questions
- MVC Design Pattern
- Spring MVC DispatcherServlet
- Spring MVC WebApplicationContext and Root Application Context
- Spring MVC @Controller Annotation
- Spring MVC @RequestMapping Annotation
- Spring MVC @RequestParam Annotation
- Spring MVC ContextLoaderListener
- Spring MVC @RequestParam and @PathVariable annotations
- Spring MVC Hello World Example
- Spring MVC Exception Handling Example
- Spring MVC with Hibernate CRUD Example
- Spring MVC Tiles Plugin with Example
- Spring MVC Interceptor with example
- Spring MVC with MongoDB CRUD Example
- Spring MVC Internationalization & Localization with Example
It is my opinion that Spring Boot is one of the best things that happened in the Java community in years. It makes development faster, more focussed and easier to learn.
With @Controller annotation, you still have that control that you can annotate individual methods with @ResponseBody annotation.
With @RestController annotation, all the handler methods of the class write their result to the response body.