@RestController vs @Controller annotation

In Spring Boot, which is part of the larger Spring Framework, @RestController and @Controller are two annotations used for different purposes, though they are related to how HTTP requests are handled in a web application. In this tutorial, I will show you the difference between @RestController vs @Controller.

Overview

Below are two simple examples to illustrate the difference between @RestController and @Controller in a Spring Boot application:

@RestController example

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyRestController {

    @GetMapping("/api/hello")
    public String hello() {
        return "Hello, World from REST Controller!";
    }
}

In this @RestController example, the hello() method is mapped to handle GET requests to /api/hello. It returns a simple string, which Spring Boot automatically converts to a response body with content type application/json.

@Controller example

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyWebController {

    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, World from Controller!");
        return "hello";
    }
}

In this @Controller example, the hello() method is also mapped to handle GET requests, but this time to /hello. Instead of returning a simple string, it adds a message to the Model and returns the name of a view template (e.g., hello.html). This view is then rendered by a view resolver (like Thymeleaf) to produce HTML content.

@RestController vs @Controller

@Controller:

  • This annotation is a specialization of @Component, which indicates that the class is a web controller.
  • It is used primarily in Spring MVC applications.
  • When you annotate a class with @Controller, it becomes capable of handling HTTP requests, but you need to use @ResponseBody on the method level if you want the method to return data directly as the response body.
  • It’s often used when you want to create a controller that will return view templates (like JSP, Thymeleaf) and also for creating RESTful web services, where methods return data directly as a response.

@RestController:

  • Introduced in Spring 4.0, @RestController is a convenience annotation that combines @Controller and @ResponseBody.
  • It’s a specialized version of @Controller and is used for creating RESTful web services.
  • When you use @RestController, all the methods in the controller will automatically have @ResponseBody semantics, meaning they all return the response directly as JSON/XML and not a view template.
  • It simplifies the controller implementation for REST API services by eliminating the need to annotate each method with @ResponseBody.

In summary, use @Controller when you’re building a traditional web application and want to return view templates, and use @RestController when you’re building a RESTful web service that returns data directly in the form of JSON or XML.

When to use @Controller instead of @RestController

Here are scenarios where @Controller is preferred over @RestController:

The choice between @Controller and @RestController in Spring Boot depends on the specific requirements of your web application. Here are scenarios where @Controller is preferred over @RestController:

  • Rendering Views: When you want your method to return a view (like a JSP, Thymeleaf, or FreeMarker page), you should use @Controller. This is common in traditional web applications where the server generates HTML pages as responses.
  • Mixed Data Types: If a controller class is expected to handle both view rendering and API responses (i.e., returning both HTML views and data objects like JSON), @Controller is a suitable choice. In such cases, you can use @ResponseBody on specific methods that should return a data object directly.
  • File Upload/Download: In scenarios where you’re dealing with file uploads or downloads, especially when the response is a file (like a PDF or an image) and not a JSON/XML, using @Controller is often more appropriate. This allows for more control over the response content type and headers.
  • Form Data Handling: When you’re handling form submissions and need to bind incoming HTTP request parameters to a model object, then render a view based on that model, @Controller is the right choice. It’s ideal for traditional form submissions that result in a new page load.
  • Integrating with View Technologies: If your application heavily relies on server-side view technologies (like Thymeleaf, JSPs), where views are resolved by the server, @Controller is the preferred annotation. It integrates seamlessly with Spring’s view resolution mechanism.

@RestController is more suited for RESTful web services where the controller’s sole purpose is to handle API requests and send back JSON or XML responses.

How to replace @Controller with @RestController

Transitioning from @Controller to @RestController in an existing Spring Boot application involves a few key adjustments, primarily related to how the application handles and responds to HTTP requests:

  • Annotation Change: Replace the @Controller annotation with @RestController at the class level. This is the most basic change and signifies that the controller is now a REST controller, which implies that the response from the methods will be the response body itself, not a view name.
  • Eliminate @ResponseBody: If you have used @ResponseBody annotations on your handler methods in the @Controller class, you can remove these. With @RestController, every method in the controller class automatically serializes return objects into HttpResponse.
  • Review Response Types: Ensure that all methods in the controller are now returning data types that can be automatically converted to JSON/XML (or your desired format). In @Controller, methods might have returned view names (strings pointing to template files). These need to be replaced with object types that represent the data you want to send back.
  • Adjust Exception Handling: If your @Controller class was using @ExceptionHandler methods to handle exceptions specific to web requests (like returning a custom error page), you might need to adjust this. In a REST context, you’d typically return error information as a JSON payload rather than a view.
  • Content Negotiation and Media Types: If your @Controller was set up for content negotiation (handling different response types like HTML, JSON, XML), you’ll need to adjust this in your @RestController. It is typically set up to handle JSON/XML responses only, but you can configure it to support other types if needed.
  • Refactor View Logic: Any logic in the @Controller that was dedicated to selecting and populating views will need to be removed or repurposed. In a @RestController, the focus is on returning data, not views.
  • Update Client-side Code: If the application has a front-end component, you might need to update it to handle the JSON/XML responses instead of the HTML responses it might have been expecting from a traditional @Controller.
  • Test the Changes: Thoroughly test all endpoints to ensure they behave as expected. Automated tests, if available, should be updated to reflect the new response types and structures.

Remember, transitioning to @RestController is generally done when the focus of the application or particular controllers shifts towards making a RESTful API, typically returning JSON or XML, rather than rendering server-side views.