Mastering Global Exception Handling in Spring MVC with @RestControllerAdvice
This guide explains how Spring MVC's @ControllerAdvice, @RestControllerAdvice, and @ExceptionHandler annotations enable both local and global exception handling, including selective handling by custom annotations, specific controllers, or packages, with practical code examples for Java developers.
Environment: Spring 5.3.23
1. Introduction
Spring MVC provides a flexible exception‑handling mechanism based on the @ControllerAdvice and @ExceptionHandler annotations. @ControllerAdvice defines a global exception‑handling class, while @ExceptionHandler specifies the exception types to handle. In RESTful projects the preferred annotation is @RestControllerAdvice, which combines @ControllerAdvice with @ResponseBody so that returned objects are automatically serialized to JSON.
2. Application Cases
Controller‑level Exception Handling
@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();
}
}This method handles exceptions only for the TestController. It is convenient for a single controller but becomes cumbersome when many controllers exist.
Global Exception Handling
@RestControllerAdvice
public class TestControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "我是全局异常:" + e.getMessage();
}
}The global handler works when the controller does not define its own @ExceptionHandler. Local handlers have higher priority than global ones.
Handling Only Specific Annotations
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AppAnnotation {}Controllers annotated with @AppAnnotation:
@AppAnnotation
@RestController
public class AnnotationController {
@GetMapping("/an/get/{id}")
public Object an(@PathVariable Integer id) {
if (id < 10) {
throw new RuntimeException("发生错误了");
}
return "自定义Annotation注解: " + id;
}
}Controllers without the annotation:
@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();
}
}Only the controller with @AppAnnotation is intercepted by the advice.
Handling Specific Controllers
@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();
}
}The advice applies only to UserController; exceptions from PersonController are not handled.
Handling Controllers in Specific Packages
@RestControllerAdvice(basePackages = {"com.pack.pkg1"})
public class PackageControllerAdvice {
@ExceptionHandler
public Object handle(Exception e) {
return "指定包下的全局异常:" + e.getMessage();
}
}When a controller in com.pack.pkg1 throws an exception, the advice handles it; controllers in other packages are unaffected.
Conclusion: Local (controller‑level) exception handling takes precedence over global exception handling.
Additional reference images about the parameters and return types accepted by @ExceptionHandler methods:
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
