Mastering Global and Local Exception Handling with @ControllerAdvice in Spring
This guide explains how to use @ControllerAdvice and @RestControllerAdvice for unified exception handling in Spring, compares their behavior, demonstrates local versus global handling, and shows advanced filtering by annotation, controller class, or package with practical code examples.
When an exception occurs in a Spring application, you can use @ControllerAdvice or @RestControllerAdvice to handle it uniformly.
The difference is that @RestControllerAdvice implicitly adds @ResponseBody , causing the method return value to be written directly to the HTTP response body (as a string or JSON).
Method 1: Local Exception Handling inside a 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 @ExceptionHandler method is invoked only when an exception is thrown from the same controller. It does not affect other controllers, making it suitable for controller‑specific error handling.
Method 2: Global Exception Handling
<code>@RestControllerAdvice
public class TestControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "我是全局异常:" + e.getMessage();
}
}</code>Applying @RestControllerAdvice (or @ControllerAdvice) makes the handler apply to all controllers. However, if a controller already defines its own @ExceptionHandler, the local handler takes precedence and the global one will not be triggered.
Advanced Scenarios
1. Handle only controllers with a specific annotation
<code>@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AppAnnotation {}
@RestController
@AppAnnotation
public class AnnotationController {
@GetMapping("/an/get/{id}")
public Object an(@PathVariable Integer id) {
if (id < 10) {
throw new RuntimeException("发生错误了");
}
return "自定义Annotation注解: " + id;
}
}
@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;
}
}
@RestControllerAdvice(annotations = {AppAnnotation.class})
public class AnnotationControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "特定注解全局异常:" + e.getMessage();
}
}</code>Only controllers annotated with @AppAnnotation will be processed by this advice.
2. Handle only a specific controller
<code>@RestController
public class UserController {
@GetMapping("/user/{id}")
public Object get(@PathVariable Integer id) {
if (id < 10) {
throw new RuntimeException("用户ID错误");
}
return "Users";
}
}
@RestController
public class PersonController {
@GetMapping("/person/{id}")
public Object get(@PathVariable Integer id) {
if (id < 10) {
throw new RuntimeException("Person ID错误");
}
return "Person";
}
}
@RestControllerAdvice(assignableTypes = {UserController.class})
public class SpecificControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "指定Controller全局异常:" + e.getMessage();
}
}</code>The advice applies only to exceptions thrown from UserController; PersonController exceptions are not intercepted.
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>Only controllers located in com.pack.pkg1 will be covered by this advice.
In summary, local exception handlers have higher priority than global ones, and Spring provides flexible attributes ( annotations , assignableTypes , basePackages ) to narrow the scope of global exception handling.
Parameters accepted by @ExceptionHandler methods (refer to the image above).
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.