作者:mzyzzyk | 来源:互联网 | 2023-10-13 12:15
背景这篇文章介绍的异常处理思路不错,本文试图给出一种具体实现,当然可能和作者的思路有所不同。框架地址:https:github.comhappyframeworkHappyFramew
背景
这篇文章介绍的异常处理思路不错,本文试图给出一种具体实现,当然可能和作者的思路有所不同。
框架地址:https://github.com/happyframework/HappyFramework。
框架介绍
关于异常的一些想法:
- 异常不能跨越“边界类”。
- 在边界类之下,异步不能被“吞掉”。
- 系统在不同场景或分层中,需要的不同的处理“策略”。
- 每种策略都是一个可扩展的“管道”。
- 可以和 AOP 进行集成。
- 异常可以用来给业务用户提供“提醒”。
- 异常可以给运维用户提供“日志”。
我希望异常处理框架以某种机制支持上面的各种想法。
针对边界类的处理场景
模拟的边界类
1 package com.happyframework.exception.handling;
2
3 import org.springframework.stereotype.Controller;
4
5 import com.happyframework.exception.handling.springframework.HandleException;
6
7 @Controller
8 public class TestController {
9
10 @HandleException("UI")
11 public void test() {
12 throw new RuntimeException("业务失败");
13 }
14
15 }
因为边界类需要特殊的异常处理策略,这里指定了的策略名字为:“UI”。
“UI”策略对应的管道配置
1 xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:p="http://www.springframework.org/schema/p"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xmlns:mvc="http://www.springframework.org/schema/mvc"
7 xmlns:aop="http://www.springframework.org/schema/aop"
8 xmlns:util="http://www.springframework.org/schema/util"
9 xsi:schemaLocation="http://www.springframework.org/schema/beans
10 http://www.springframework.org/schema/beans/spring-beans.xsd
11 http://www.springframework.org/schema/context
12 http://www.springframework.org/schema/context/spring-context.xsd
13 http://www.springframework.org/schema/mvc
14 http://www.springframework.org/schema/mvc/spring-mvc.xsd
15 http://www.springframework.org/schema/aop
16 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
17 http://www.springframework.org/schema/util
18 http://www.springframework.org/schema/util/spring-util-3.0.xsd">
19
20 <context:component-scan base-package="com.happyframework.exception.handling.springframework" />
21 <context:component-scan base-package="com.happyframework.exception.handling" />
22
23 <aop:aspectj-autoproxy/>
24
25 <bean class="com.happyframework.exception.handling.springframework.ExceptionHandlerDefination">
26 <property name="policy" value="UI"/>
27 <property name="handler">
28 <bean class="com.happyframework.exception.handling.ConsoleLoggingHandler"/>
29 property>
30 bean>
31 <bean class="com.happyframework.exception.handling.springframework.ExceptionHandlerDefination">
32 <property name="policy" value="UI"/>
33 <property name="handler">
34 <bean class="com.happyframework.exception.handling.ConsoleNotificationHandler"/>
35 property>
36 bean>
37 beans>
38
为管道定义了两个处理器:日志处理器和提醒处理器,因为是测试的处理器,实现就比较简单,真实项目中可以决定:哪些异常需要日志?哪些信息提醒给用户?
运行输出
1 记录日志:java.lang.RuntimeException: 业务失败
2 提示消息:java.lang.RuntimeException: 业务失败
“UI”策略导致异常被吞掉了,这也是我们期望的行为,后面会介绍如何在处理器中吞掉异常。
核心 API 介绍
主要类型
代码可以去 https://github.com/happyframework/HappyFramework 下载。
重点说一下 ExceptionHandlerChain
1 package com.happyframework.exception.handling;
2
3 public interface ExceptionHandlerChain {
4
5 Throwable getException();
6
7 void setNewException(final Throwable newException);
8
9 boolean isExceptionHandled();
10
11 void setExceptionHandled(final boolean exceptionHandled);
12
13 void proceed();
14
15 }
ExceptionHandlerChain 是作为参数传递给 ExceptionHandler:
1 package com.happyframework.exception.handling;
2
3 public interface ExceptionHandler {
4
5 void handle(final ExceptionHandlerChain chain);
6
7 }
ExceptionHandlerChain 的成员的主要意图是:
- Throwable getException():返回正在处理的异常。
- void setNewException(final Throwable newException):替换或包装异常的时候调用此方法。
- boolean isExceptionHandled():异常是否被处理过。
- void setExceptionHandled(final boolean exceptionHandled):吞掉异常的时候调用此方法。
- void proceed():执行下一个处理器。
一个简单的异常处理器
1 package com.happyframework.exception.handling;
2
3 final class ConsoleNotificationHandler implements ExceptionHandler {
4
5 @Override
6 public final void handle(final ExceptionHandlerChain chain) {
7 System.out.println("提示消息:" + chain.getException());
8
9 chain.setExceptionHandled(true);
10 chain.proceed();
11 }
12
13 }
备注
第一次用 Java 写东西,感觉挺不错的。