Skip to content

Commit f7d3535

Browse files
committed
异常捕获顺序解析
1 parent 5a64ce0 commit f7d3535

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

Diff for: docs/advanced/springboot-handle-exception-plus.md

+47-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public enum ErrorCode {
7575

7676
**`ErrorReponse.java`(返回给客户端具体的异常对象)**
7777

78+
这个类作为异常信息返回给客户端,里面包括了当出现异常时我们想要返回给客户端的所有信息。
79+
7880
```java
7981
import org.springframework.util.ObjectUtils;
8082

@@ -127,6 +129,8 @@ public class ErrorReponse {
127129

128130
**`BaseException.java`(继承自 `RuntimeException` 的抽象类,可以看做系统中其他异常类的父类)**
129131

132+
系统中的异常类都要继承自这个类。
133+
130134
```java
131135

132136
public abstract class BaseException extends RuntimeException {
@@ -177,7 +181,9 @@ public class ResourceNotFoundException extends BaseException {
177181

178182
**`GlobalExceptionHandler.java`(全局异常捕获)**
179183

180-
`@ExceptionHandler` 捕获异常的过程中,会优先找到最匹配的。
184+
我们定义了两个异常捕获方法。
185+
186+
这里再说明一下,实际上这个类只需要 `handleAppException()` 这一个方法就够了,因为它是本系统所有异常的父类。只要是抛出了继承 `BaseException` 类的异常后都会在这里被处理。
181187

182188
```java
183189
import com.twuc.webApp.web.ExceptionController;
@@ -192,7 +198,9 @@ import javax.servlet.http.HttpServletRequest;
192198
@ControllerAdvice(assignableTypes = {ExceptionController.class})
193199
@ResponseBody
194200
public class GlobalExceptionHandler {
195-
201+
202+
// 也可以将 BaseException 换为 RuntimeException
203+
// 因为 RuntimeException 是 BaseException 的父类
196204
@ExceptionHandler(BaseException.class)
197205
public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
198206
ErrorReponse representation = new ErrorReponse(ex, request.getRequestURI());
@@ -208,6 +216,43 @@ public class GlobalExceptionHandler {
208216

209217
```
210218

219+
**(重要)一点扩展:**
220+
221+
哈哈!实际上我多加了一个算是多余的异常捕获方法`handleResourceNotFoundException()` 主要是为了考考大家当我们抛出了 `ResourceNotFoundException`异常会被下面哪一个方法捕获呢?
222+
223+
答案:
224+
225+
会被`handleResourceNotFoundException()`方法捕获。因为 `@ExceptionHandler` 捕获异常的过程中,会优先找到最匹配的。
226+
227+
下面通过源码简单分析一下:
228+
229+
`ExceptionHandlerMethodResolver.java``getMappedMethod`决定了具体被哪个方法处理。
230+
231+
```java
232+
233+
@Nullable
234+
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
235+
List<Class<? extends Throwable>> matches = new ArrayList<>();
236+
//找到可以处理的所有异常信息。mappedMethods 中存放了异常和处理异常的方法的对应关系
237+
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
238+
if (mappedException.isAssignableFrom(exceptionType)) {
239+
matches.add(mappedException);
240+
}
241+
}
242+
// 不为空说明有方法处理异常
243+
if (!matches.isEmpty()) {
244+
matches.sort(new ExceptionDepthComparator(exceptionType));
245+
// 返回处理异常的方法
246+
return this.mappedMethods.get(matches.get(0));
247+
}
248+
else {
249+
return null;
250+
}
251+
}
252+
```
253+
254+
从源代码看出:**`getMappedMethod()`会首先找到可以匹配处理异常的所有方法信息,然后对其进行从小到大的排序,最后取最小的那一个匹配的方法(即匹配度最高的那个)。**
255+
211256
## 写一个抛出异常的类测试
212257

213258
**`Person.java`**

Diff for: source-code/basis/springboot-handle-exception-improved/src/main/java/com/twuc/webApp/WebAppApplication.java

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
@SpringBootApplication
77
public class WebAppApplication {
8+
89
public static void main(String[] args) {
910
SpringApplication.run(WebAppApplication.class, args);
1011
}

0 commit comments

Comments
 (0)