Mastering Global and Local Exception Handling with @ControllerAdvice in Spring
This article explains how to use @ControllerAdvice and @RestControllerAdvice for both local and global exception handling in Spring, demonstrates limiting handlers by annotation, controller class, or package, and clarifies the precedence rules between local and global handlers.
When an exception occurs in a program, we can use two annotations to handle exception information uniformly.
@ControllerAdvice and @RestControllerAdvice
The difference is that RestControllerAdvice adds @ResponseBody, which writes the method return value directly to the response body, converting objects to JSON.
Source code:
<code>@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
}</code>Method 1: Handle exceptions inside the controller
<code>@RestController
public class TestController {
@GetMapping("/test/{id}")
public Object test(@PathVariable Integer id) {
if (id < 5) {
throw new RuntimeException("运行时异常");
}
return "测试异常处理";
}
@ExceptionHandler
public Object handle(Exception e) {
return e.getMessage();
}
}</code>This handles exceptions only for this controller. For many controllers this becomes cumbersome.
Method 2: Global exception handling
Add @RestControllerAdvice or @ControllerAdvice on a class.
<code>@RestControllerAdvice
public class TestControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "我是全局异常:" + e.getMessage();
}
}</code>Global handling works only when local @ExceptionHandler methods are removed; local handlers have higher priority.
Conclusion: Local exception handling takes precedence over global handling.
Further, you can limit global handlers to specific annotations, controllers, or packages.
1. Handle only specific annotations
Custom annotation:
<code>@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AppAnnotation {
}</code>Controller with annotation:
<code>@AppAnnotation
@RestController
public class AnnotationController {
@GetMapping("/an/get/{id}")
public Object an(@PathVariable Integer id) {
if (id < 10) {
throw new RuntimeException("发生错误了");
}
return "自定义Annotation注解: " + id;
}
}</code>Controller without annotation:
<code>@RestController
public class AnnotationController2 {
@GetMapping("/an/get2/{id}")
public Object an(@PathVariable Integer id) {
if (id < 10) {
throw new RuntimeException("2发生错误了");
}
return "自定义Annotation注解2: " + id;
}
}</code>Global advice limited to that annotation:
<code>@RestControllerAdvice(annotations = {AppAnnotation.class})
public class AnnotationControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "特定注解全局异常:" + e.getMessage();
}
}</code>Only requests to controllers annotated with @AppAnnotation are intercepted.
2. Handle only specific controllers
Define UserController and PersonController, then a global advice limited to UserController:
<code>@RestControllerAdvice(assignableTypes = {UserController.class})
public class SpecificControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "指定Controller全局异常:" + e.getMessage();
}
}</code>Only exceptions from UserController are handled; PersonController exceptions are not.
3. Handle controllers in a specific package
<code>@RestControllerAdvice(basePackages = {"com.pack.pkg1"})
public class PackageControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "指定包下的全局异常:" + e.getMessage();
}
}</code>When UserController resides in com.pack.pkg1, its exceptions are handled; PersonController in com.pack.pkg2 is not.
For more details on @ExceptionHandler parameters and return types, refer to the linked resources.
Accepted parameter types
End of article.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.