Both @ControllerAdvice
and @RestControllerAdvice
are annotations in Spring that provide centralized exception handling, model binding, and other cross-cutting concerns across multiple controllers. However, there is a key difference in how they handle the response format, particularly in RESTful web services.
1. @ControllerAdvice
:
- Purpose: It is used for handling exceptions and applying cross-cutting logic across all controllers (whether REST or non-REST).
- Response Type: It typically works with controllers that use
@Controller
, where the view layer (like HTML, JSP, or Thymeleaf) is returned. By default, the methods in@ControllerAdvice
return view names and can useModelAndView
for rendering views. - When to Use: Use it when you have both REST and non-REST (traditional MVC) controllers in your application and you want to handle exceptions, model binding, or other concerns for both.
Example:
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class GlobalControllerAdvice {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex, Model model) {
ModelAndView mav = new ModelAndView();
mav.addObject("message", ex.getMessage());
mav.setViewName("error");
return mav; // Will render "error" view (HTML page)
}
}
In this case, @ControllerAdvice
is designed to handle both REST and non-REST responses, and here it’s returning a view (error.jsp
, for instance).
2. @RestControllerAdvice
:
- Purpose: It is specifically designed for RESTful services (APIs) and provides a way to handle exceptions and apply other cross-cutting logic for controllers annotated with
@RestController
. - Response Type: Since it is intended for REST controllers, it always returns the response as JSON (or other suitable HTTP response types like XML if configured). It combines
@ControllerAdvice
and@ResponseBody
, meaning that the response from the exception handler is directly written to the HTTP response body, usually in JSON format. - When to Use: Use it when you’re developing a REST API and want to centralize exception handling or cross-cutting logic for controllers that return JSON or other HTTP response data formats.
Example:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalRestControllerAdvice {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
In this case, @RestControllerAdvice
ensures that the response is automatically serialized into JSON or another appropriate format and returned to the client. No view is rendered here.
Key Differences:
Aspect | @ControllerAdvice | @RestControllerAdvice |
---|---|---|
Target Controllers | Works with both @Controller and @RestController | Specifically designed for @RestController |
Response Type | Returns views (like HTML, JSP) and uses ModelAndView | Returns data directly (e.g., JSON, XML) via @ResponseBody |
Usage | Typically used for traditional MVC applications | Used in RESTful APIs where JSON or XML is the response format |
Implicit Behavior | Does not add @ResponseBody implicitly | Combines @ControllerAdvice with @ResponseBody to return data directly |
When to Use Which:
- Use
@ControllerAdvice
when you are building a traditional web application with a view layer (e.g., HTML, Thymeleaf, JSP) and want to handle exceptions or other concerns across multiple controllers. - Use
@RestControllerAdvice
when building RESTful web services, and you want centralized exception handling for controllers that return JSON or XML responses.
By choosing the appropriate advice annotation based on your application’s needs, you can ensure that your exceptions are handled in a consistent and appropriate manner for the type of controllers you’re using.