Home/Learn/Spring Boot/@RestController & @Controller

@RestController & @Controller

Beginner
Web / REST

@RestController combines @Controller and @ResponseBody, turning every handler method into a JSON/XML endpoint without needing explicit serialisation annotations.

Overview

@Controller marks a class as an MVC controller whose methods return view names resolved by a ViewResolver. @RestController is a composed annotation (@Controller + @ResponseBody) that skips view resolution and writes the return value directly to the HTTP response body via HttpMessageConverters. For pure REST APIs you almost always use @RestController. You can still return a ResponseEntity<T> from @RestController methods to control status codes and headers precisely.

@RestController Basics

Every public method in a @RestController is treated as an endpoint. Jackson (included via spring-boot-starter-web) serialises the return value to JSON by default. Returning null yields a 200 with an empty body; use ResponseEntity to return 204 or 404 explicitly.

Java — @RestController example
@RestController
@RequestMapping("/api/products")
public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public List<ProductDTO> listAll() {
        return productService.findAll();  // serialised to JSON array
    }

    @GetMapping("/{id}")
    public ResponseEntity<ProductDTO> getById(@PathVariable Long id) {
        return productService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public ProductDTO create(@RequestBody @Valid CreateProductRequest req) {
        return productService.create(req);
    }
}

@Controller for MVC Views

@Controller methods return a String view name or a ModelAndView. The DispatcherServlet forwards to the ViewResolver (Thymeleaf, JSP, etc.). You can mix — annotate individual methods with @ResponseBody to return JSON from a @Controller.

Java — @Controller for Thymeleaf views
@Controller
@RequestMapping("/products")
public class ProductViewController {

    @GetMapping
    public String list(Model model) {
        model.addAttribute("products", productService.findAll());
        return "products/list";  // resolves to templates/products/list.html
    }

    @GetMapping("/{id}/edit")
    public String editForm(@PathVariable Long id, Model model) {
        model.addAttribute("product", productService.findById(id).orElseThrow());
        return "products/edit";
    }

    // JSON endpoint mixed into a @Controller
    @GetMapping("/search")
    @ResponseBody
    public List<ProductDTO> search(@RequestParam String q) {
        return productService.search(q);
    }
}

Exception Handling with @ControllerAdvice

@RestControllerAdvice (= @ControllerAdvice + @ResponseBody) centralises exception handling across all controllers, avoiding try-catch boilerplate in each endpoint.

Java — @RestControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(EntityNotFoundException ex) {
        return new ErrorResponse("NOT_FOUND", ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
        String msg = ex.getBindingResult().getFieldErrors().stream()
            .map(e -> e.getField() + ": " + e.getDefaultMessage())
            .collect(Collectors.joining(", "));
        return new ErrorResponse("VALIDATION_FAILED", msg);
    }
}

Key Points to Remember

  • 1@RestController = @Controller + @ResponseBody on every method.
  • 2Return values are serialised by HttpMessageConverters (Jackson for JSON by default).
  • 3@Controller returns view names; add @ResponseBody on individual methods for JSON.
  • 4Use ResponseEntity<T> for fine-grained control over status codes and headers.
  • 5@RestControllerAdvice centralises error handling across all controllers.
  • 6Content negotiation is driven by the Accept header — @RestController supports both JSON and XML with the right dependency.

Interview Questions

Sign in to ask Aria
1

What is the difference between @Controller and @RestController?

EasyInfosys
2

When would you use @Controller instead of @RestController?

EasyTCS
3

How does @ResponseStatus interact with ResponseEntity?

MediumAmazon
4

How does Spring select which HttpMessageConverter to use?

MediumGoogle
5

Explain how @RestControllerAdvice works and why it is preferred over try-catch in controllers.

HardNetflix

Ask Aria about @RestController & @Controller

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…