Skip to content

Commit a3f493e

Browse files
committed
init
0 parents  commit a3f493e

File tree

11 files changed

+459
-0
lines changed

11 files changed

+459
-0
lines changed

.editorconfig

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# SCX EditorConfig v1.0
2+
root = true
3+
4+
[*]
5+
# 字符集
6+
charset = utf-8
7+
# 行分割符
8+
end_of_line = lf
9+
# 缩进样式
10+
indent_style = space
11+
# 缩进
12+
indent_size = 4
13+
# 制表符大小
14+
tab_width = 4
15+
# 去除行尾空白字符
16+
trim_trailing_whitespace = true
17+
# 在文件末尾插入换行符
18+
insert_final_newline = true
19+
# 强制换行位置
20+
max_line_length = 120
21+
22+
[*.java]
23+
# 简单的 块 在同一行
24+
ij_java_keep_simple_blocks_in_one_line = false
25+
# 简单的 方法 在同一行
26+
ij_java_keep_simple_methods_in_one_line = false
27+
# 简单的 lambda 在同一行
28+
ij_java_keep_simple_lambdas_in_one_line = true
29+
# 简单的 类 在同一行
30+
ij_java_keep_simple_classes_in_one_line = true
31+
# 'if()' 语句 强制加大括号
32+
ij_java_if_brace_force = always
33+
# 'for()' 语句 强制加大括号
34+
ij_java_for_brace_force = always
35+
# 'while()' 语句 强制加大括号
36+
ij_java_while_brace_force = always
37+
# 'do...while()' 语句 强制加大括号
38+
ij_java_do_while_brace_force = always
39+
40+
[*.js]
41+
# 使用使用 双引号
42+
ij_javascript_use_double_quotes = true
43+
# 强制 引号样式
44+
ij_javascript_force_quote_style = true
45+
# 在语句末尾使用 分号
46+
ij_javascript_use_semicolon_after_statement = true
47+
# 强制 分号样式
48+
ij_javascript_force_semicolon_style = true
49+
# 'if()' 语句 强制加大括号
50+
ij_javascript_if_brace_force = always
51+
# 'for()' 语句 强制加大括号
52+
ij_javascript_for_brace_force = always
53+
# 'while()' 语句 强制加大括号
54+
ij_javascript_while_brace_force = always
55+
# 'do...while()' 语句 强制加大括号
56+
ij_javascript_do_while_brace_force = always
57+
58+
[*.html]
59+
# 引号样式
60+
ij_html_quote_style = double
61+
# 强制引号
62+
ij_html_enforce_quotes = true
63+
64+
[*.css]
65+
# 使用 双引号
66+
ij_css_use_double_quotes = true
67+
# 强制引号格式
68+
ij_css_enforce_quotes_on_format = true
69+
70+
[*.json]
71+
# 缩进
72+
indent_size = 2
73+
74+
[*.md]
75+
# 去除行尾空白字符 (MarkDown 行尾空白有特殊含义)
76+
trim_trailing_whitespace = false
77+
78+
[*.{yaml,yml}]
79+
# 缩进
80+
indent_size = 2

.github/dependabot.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: maven
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
open-pull-requests-limit: 99
8+
9+
- package-ecosystem: github-actions
10+
directory: /
11+
schedule:
12+
interval: weekly
13+
open-pull-requests-limit: 99

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: CI
2+
on:
3+
- push
4+
- pull_request
5+
- workflow_dispatch
6+
jobs:
7+
ci:
8+
name: CI
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: 检出代码
12+
uses: actions/checkout@v6
13+
14+
- name: 配置 Java
15+
uses: actions/setup-java@v5
16+
with:
17+
java-version: 25
18+
distribution: temurin
19+
cache: maven
20+
21+
- name: Maven 构建
22+
run: mvn package
23+
24+
- name: 上传构建产物
25+
uses: actions/upload-artifact@v5
26+
with:
27+
name: scx-exception-artifact
28+
path: ./target/

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
### Maven ###
2+
target/
3+
4+
### IntelliJ IDEA ###
5+
.idea/
6+
*.iws
7+
*.iml
8+
*.ipr

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 scx567888
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<p align="center">
2+
<img src="https://scx.dev/scx-logo/scx-exception-logo.svg" width="300px" alt="scx-exception-logo"/>
3+
</p>
4+
<p align="center">
5+
<a target="_blank" href="https://github.com/scx-projects/scx-exception/actions/workflows/ci.yml">
6+
<img src="https://github.com/scx-projects/scx-exception/actions/workflows/ci.yml/badge.svg" alt="CI"/>
7+
</a>
8+
<a target="_blank" href="https://central.sonatype.com/artifact/dev.scx/scx-exception">
9+
<img src="https://img.shields.io/maven-central/v/dev.scx/scx-exception?color=ff69b4" alt="maven-central"/>
10+
</a>
11+
<a target="_blank" href="https://github.com/scx-projects/scx-exception">
12+
<img src="https://img.shields.io/github/languages/code-size/scx-projects/scx-exception?color=orange" alt="code-size"/>
13+
</a>
14+
<a target="_blank" href="https://github.com/scx-projects/scx-exception/issues">
15+
<img src="https://img.shields.io/github/issues/scx-projects/scx-exception" alt="issues"/>
16+
</a>
17+
<a target="_blank" href="https://github.com/scx-projects/scx-exception/blob/master/LICENSE">
18+
<img src="https://img.shields.io/github/license/scx-projects/scx-exception" alt="license"/>
19+
</a>
20+
</p>

pom.xml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>dev.scx</groupId>
8+
<artifactId>scx-parent</artifactId>
9+
<version>1</version>
10+
<relativePath/>
11+
</parent>
12+
13+
<artifactId>scx-exception</artifactId>
14+
<version>0.0.1</version>
15+
<packaging>jar</packaging>
16+
17+
<name>SCX Exception</name>
18+
<description>
19+
SCX Exception
20+
</description>
21+
<url>https://github.com/scx-projects/scx-exception</url>
22+
23+
<licenses>
24+
<license>
25+
<name>MIT License</name>
26+
<url>https://github.com/scx-projects/scx-exception/blob/master/LICENSE</url>
27+
</license>
28+
</licenses>
29+
30+
<developers>
31+
<developer>
32+
<id>scx567888</id>
33+
<name>scx567888</name>
34+
<email>scx567888@outlook.com</email>
35+
</developer>
36+
</developers>
37+
38+
<scm>
39+
<connection>scm:git:https://github.com/scx-projects/scx-exception.git</connection>
40+
<developerConnection>scm:git:https://github.com/scx-projects/scx-exception.git</developerConnection>
41+
<url>https://github.com/scx-projects/scx-exception</url>
42+
</scm>
43+
44+
<build>
45+
<plugins>
46+
47+
<!-- 此插件用于将项目打包为 可执行 jar 包-->
48+
<plugin>
49+
<groupId>org.apache.maven.plugins</groupId>
50+
<artifactId>maven-jar-plugin</artifactId>
51+
<configuration>
52+
<archive>
53+
<manifest>
54+
<!-- 因为 scx 并不是可执行 jar 包, 所以此处不添加 classpath 到描述文件中 -->
55+
<addClasspath>false</addClasspath>
56+
</manifest>
57+
</archive>
58+
<!-- 此处因为没有类似 maven-source-plugin 插件中 excludeResources 的选项 -->
59+
<!-- 所以在这里手动排除资源文件, 具体文件说明见下方 -->
60+
<excludes>
61+
<!-- 默认 git 占位空文件 -->
62+
<exclude>/.gitkeep</exclude>
63+
</excludes>
64+
</configuration>
65+
</plugin>
66+
67+
</plugins>
68+
</build>
69+
70+
<dependencies>
71+
72+
<!-- TestNG 测试包 -->
73+
<dependency>
74+
<groupId>org.testng</groupId>
75+
<artifactId>testng</artifactId>
76+
<version>${testng.version}</version>
77+
<scope>test</scope>
78+
</dependency>
79+
80+
</dependencies>
81+
82+
<properties>
83+
84+
<!-- *********************** 以下为依赖包版本 *********************** -->
85+
<testng.version>7.11.0</testng.version>
86+
87+
</properties>
88+
89+
</project>
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package dev.scx.exception;
2+
3+
/// ScxWrappedException 是一个通用的运行时异常包装器, 主要用途 :
4+
///
5+
/// - 1. 将受检异常包装为运行时异常.
6+
/// - 2. 对动态可执行单元 (如高阶函数, 装饰器模式) 进行异常隔离和标记.
7+
///
8+
/// ### 设计动机
9+
///
10+
/// 设想一下有如下方法
11+
/// ```java
12+
/// public void read(Func<byte[]> bytesConsumer, int length) throws IOException {
13+
/// // someCode
14+
/// }
15+
/// ```
16+
/// 当我们在调用时就会遇到如下问题, 也就是异常来源的模糊性问题.
17+
/// ```java
18+
/// try {
19+
/// read(bytes -> {
20+
/// // someCode maybe throw IOException
21+
/// }, 1024);
22+
/// } catch (IOException e) {
23+
/// // 该如何区分这个 IOException 是 read 本身的 还是 bytesConsumer 的 ?
24+
/// e.printStackTrace();
25+
/// }
26+
/// ```
27+
///
28+
/// 针对这种情况 我们创建 `ScxWrappedException` 用于包装 `bytesConsumer` 的异常, 以便调用者能够正确区分.
29+
///
30+
/// ### 用法展示, 这里我展示 `两种推荐用法` .
31+
///
32+
/// #### 用法 1 : 包装所有异常.
33+
///
34+
/// 案例 1 :
35+
/// ```java
36+
/// public void read(Func<byte[]> bytesConsumer, int length) throws ScxWrappedException, IOException {
37+
/// // someCode
38+
/// try {
39+
/// bytesConsumer.apply(new byte[]{1,2,3});
40+
/// } catch (Exception e) {
41+
/// throw new ScxWrappedException(e);
42+
/// }
43+
/// // someCode
44+
/// }
45+
/// ```
46+
///
47+
/// - 优点 : 异常隔离层级清晰, 调用方心智负担小.
48+
/// - 缺点 : 对于调用方 总是需要处理 ScxWrappedException 异常.
49+
///
50+
/// #### 用法 2 : 只包装可能引发混淆的异常.
51+
///
52+
/// 案例 1 : `动态可执行单元` 只抛出 RuntimeException.
53+
///
54+
/// ```java
55+
/// // 假设 NoPermissionException 是一个 RuntimeException.
56+
/// public void checkPermission(Func<String[], RuntimeException> permissionsSupplier, String department) throws ScxWrappedException, NoPermissionException {
57+
/// // someCode
58+
/// try {
59+
/// permissionsSupplier.apply();
60+
/// } catch (NoPermissionException e) {
61+
/// // 只包装可能混淆的异常
62+
/// throw new ScxWrappedException(e);
63+
/// } catch (RuntimeException e) {
64+
/// // 此处的 catch 代码块也可以直接删除, 此处为了演示.
65+
/// throw e;
66+
/// }
67+
/// // someCode
68+
/// }
69+
/// ```
70+
///
71+
/// 案例 2 : `动态可执行单元` 支持抛出 泛型异常 (包含受检异常).
72+
///
73+
/// ```java
74+
/// public <X extends Exception> void read(Func<byte[], X> bytesConsumer, int length) throws X, ScxWrappedException, IOException {
75+
/// // someCode
76+
/// try {
77+
/// bytesConsumer.apply(new byte[]{1,2,3});
78+
/// } catch (Exception e) {
79+
/// // 包装易混淆异常
80+
/// if(e instanceof IOException) {
81+
/// throw new ScxWrappedException(e);
82+
/// }
83+
/// // 其他异常直接抛出
84+
/// throw e;
85+
/// }
86+
/// // someCode
87+
/// }
88+
/// ```
89+
///
90+
/// - 优点 : 对于不会混淆的异常 会直接穿透到调用者. 在异常层级上会更干净, 而且更符合所谓的函数式哲学.
91+
/// - 缺点 : 模糊了异常的层级, 对调用者来说 有些异常会包装有些不会包装, 可能造成一定程度的心智负担.
92+
/// - 小提示 1 : 在案例 2 中, 实际使用过程中 X 会被推断为 bytesConsumer 抛出的所有异常的最小共同父类.
93+
/// - 小提示 2 : 如果你的 `动态可执行单元` 永远不会抛出令人混淆的异常, 那么你实际上不需要这个类.
94+
///
95+
/// @author scx567888
96+
/// @version 0.0.1
97+
public final class ScxWrappedException extends RuntimeException {
98+
99+
public ScxWrappedException(String message, Throwable cause) {
100+
// 包装类 不允许空 cause
101+
if (cause == null) {
102+
throw new NullPointerException("cause must not be null");
103+
}
104+
super(message, cause);
105+
}
106+
107+
public ScxWrappedException(Throwable cause) {
108+
// 包装类 不允许空 cause
109+
if (cause == null) {
110+
throw new NullPointerException("cause must not be null");
111+
}
112+
super(cause);
113+
}
114+
115+
/// 获取真正的异常
116+
public Throwable getRootCause() {
117+
var cause = this.getCause();
118+
if (cause instanceof ScxWrappedException wrappedException) {
119+
return wrappedException.getRootCause();
120+
}
121+
return cause;
122+
}
123+
124+
}

src/main/resources/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)