Đây có phải là cách người ta mong đợi Spring MVC sẽ hoạt động không?
Kể từ Spring 4.3.7, đây là cách Spring MVC hoạt động: nó sử dụng các HandlerExceptionResolver
phiên bản để xử lý các ngoại lệ do các phương thức xử lý ném ra.
Theo mặc định, cấu hình MVC web đăng ký một HandlerExceptionResolver
bean duy nhất , a HandlerExceptionResolverComposite
,
đại biểu cho một danh sách khác HandlerExceptionResolvers
.
Những trình giải quyết khác là
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
đã đăng ký theo thứ tự đó. Đối với mục đích của câu hỏi này, chúng tôi chỉ quan tâm đến ExceptionHandlerExceptionResolver
.
An AbstractHandlerMethodExceptionResolver
giải quyết các ngoại lệ thông qua @ExceptionHandler
các phương thức.
Tại khởi bối cảnh, mùa xuân sẽ tạo ra một ControllerAdviceBean
cho mỗi @ControllerAdvice
lớp chú thích nó phát hiện. Các ExceptionHandlerExceptionResolver
sẽ lấy những từ ngữ cảnh, và sắp xếp chúng bằng cách sử dụng AnnotationAwareOrderComparator
mà
là một phần mở rộng OrderComparator
hỗ trợ Ordered
giao diện của Spring cũng như @Order
và @Priority
các chú thích, với giá trị thứ tự được cung cấp bởi một phiên bản Đã đặt hàng ghi đè giá trị chú thích được xác định tĩnh (nếu có).
Sau đó, nó sẽ đăng ký một ExceptionHandlerMethodResolver
cho mỗi ControllerAdviceBean
trường hợp này (ánh xạ @ExceptionHandler
các phương thức có sẵn với các loại ngoại lệ mà chúng có ý định xử lý). Chúng cuối cùng được thêm theo cùng một thứ tự vào a LinkedHashMap
(bảo toàn thứ tự lặp lại).
Khi một ngoại lệ xảy ra, hàm ExceptionHandlerExceptionResolver
sẽ lặp qua những cái này ExceptionHandlerMethodResolver
và sử dụng cái đầu tiên có thể xử lý ngoại lệ.
Vì vậy, vấn đề ở đây là: nếu bạn có một @ControllerAdvice
với @ExceptionHandler
for Exception
được đăng ký trước một @ControllerAdvice
lớp khác với một @ExceptionHandler
ngoại lệ cụ thể hơn, chẳng hạn như IOException
, cái đầu tiên đó sẽ được gọi. Như đã đề cập trước đó, bạn có thể kiểm soát thứ tự đăng ký đó bằng cách @ControllerAdvice
triển khai lớp chú thích của bạn Ordered
hoặc chú thích nó bằng @Order
hoặc @Priority
và đặt cho nó một giá trị thích hợp.
@ExceptionHandler
phương thức trong a@ControllerAdvice
, phương thức xử lý lớp cha cụ thể nhất của ngoại lệ đã ném được chọn.