@Controller and @RestController Annotations in Spring Boot

Introduction

In Spring Boot, the controller class is responsible for processing incoming REST API requests, preparing a model, and returning the view to be rendered as a response.

The controller classes in Spring are annotated either by the @Controller or the @RestController annotation. These mark controller classes as a request handler to allow Spring to recognize it as a RESTful service during runtime.

In this tutorial, we'll cover the definition of the @Controller and the @RestController annotations, their use-cases, and the difference between the two annotations.

If you are new to Spring Boot, you might also want to check out our full guide on How to Build a Spring Boot REST API.

Spring Boot REST API Workflow

Before defining the two annotations, we'll quickly go through the workflow of how Spring Boot handles REST API requests and processes and returns a response:

First, the request is received by the DispatcherServlet, which is responsible for processing any incoming URI requests and mapping them to their corresponding handlers in the form of controller methods. After the controller method has been executed, the resource is then processed as a response which can either be JSON or XML.

In the diagram above, the two processes encapsulated in the rectangle are the processes actually implemented by a developer. The rest are executed by Spring services that are running in the background, including the DispatcherServlet.

The @Controller Annotation

The @Controller annotation is a specialization of the generic stereotype @Component annotation, which allows a class to be recognized as a Spring-managed component.

The @Controller annotation extends the use-case of @Component and marks the annotated class as a business or presentation layer. When a request is made, this will inform the DispatcherServlet to include the controller class in scanning for methods mapped by the @RequestMapping annotation.

Now, we'll declare the actual controller to define the business logic and handle all the requests related to the model Tree.

First, mark the class with the @Controller annotation together with @RequestMapping and specify the path to /api/tree:

@Controller
@ResponseBody
@RequestMapping("/api/tree")
public class TreeController {

    @Autowired
    private TreeRepository repository;
 
    @GetMapping("/{id}")
    public Tree getTreeById(@PathVariable int id) {
        return repository.findById(id);
    }
  
    @GetMapping
    public Tree getTreeById(@RequestParam String name, 
                            @RequestParam int age) {
        return repository.findFirstByCommonNameIgnoreCaseAndAge(name, age);
    }
}

The @Autowired annotation is used to automatically inject dependencies of the specified type into the current bean. In this case, the TreeRepository bean is injected as a dependency of TreeController.

@GetMapping is a shortcut for @RequestMapping(method = RequestMethod.GET), and is used to map HTTP GET requests to the mapped controller methods.

We've applied a @ResponseBody annotation to the class-level of this controller. When the request handlers return data back, such as return repository.findById(), the response will be serialized to JSON before being returned to the client.

Alternatively, you could've annotated each response type with the @ResponseBody annotation instead:

 @GetMapping("/{id}")
    public @ResponseBody Tree getTreeById(@PathVariable int id) {
        return repository.findById(id);
    }

If we run this application, assuming we've already got a Tree instance saved to the database, with the ID of 1, and hit the localhost:8080/1 endpoint, we'd be greeted with:

{"species":"Salix babylonica","commonName":"Weeping willow", "age":"150"}

Because of the @ResponseBody annotation, the fields from the fetched object are serialized into JSON and returned to the client that requested it.

The @RestController Annotation

The @RestController annotation in Spring is essentially just a combination of @Controller and @ResponseBody. This annotation was added during Spring 4.0 to remove the redundancy of declaring the @ResponseBody annotation in your controller.

That's one less annotation declaration! If you also look at the interface definition of the two annotations to see the difference between the two:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
  //..
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
  //..
}

The RestController interface is annotated by @Controller and @ResponseBody instead of directly annotating it with @Component.

If we replace the annotation of our controller with @RestController, we won't need to change the domain and persistence layer as they still will be compatible with this annotation.

Using the example controller TreeController above, let's compare the changes when we use this annotation:

@RestController
@RequestMapping("/api/tree")
public class TreeController {

    @Autowired
    private TreeRepository repository;
 
    @GetMapping("/{id}")
    public Tree getTreeById(@PathVariable int id) {
        return repository.findById(id);
    }
  
    @GetMapping
    public Tree getTreeById(@RequestParam String name, 
                            @RequestParam int age) {
        return repository.findFirstByCommonNameIgnoreCaseAndAge(name, age);
    }
}
Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Now, all methods have the @ResponseBody annotation applied to them, as @RestController applies it at class-level.

If we run this application, assuming we've already got a Tree instance saved to the database, with the ID of 1, and hit the localhost:8080/1 endpoint, we'd be greeted with:

{"species":"Salix babylonica","commonName":"Weeping willow", "age":"150"}

Conclusion

Essentially, @RestController extends the capabilities of both the @Controller and @ResponseBody annotations.

Other than the fact that @RestController exists to allow Spring controllers to be one line shorter, there aren't any major differences between the two annotations.

The primary function of both annotations is to allow a class to be recognized as a Spring-managed component and to allow handling of HTTP requests using REST API.

Last Updated: July 27th, 2021
Was this article helpful?

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms