1 Commits

Author SHA1 Message Date
4638853da6 refactor(exception)!: 重构多场景异常相关代码
- `IExceptionType` 不继承自 `IExceptionFactory`,具体表示异常场景的枚举,可按需实现这两个接口
- 简化 `IMultiTypesException` 接口定义,不与 `IExceptionType` 强制绑定
- 修改相关文档与描述

通过以上修改,使表示异常场景的枚举可以与异常类分开定义,使不同的异常可以复用同一套场景枚举。不强制作为单一异常的工厂,在被不同的异常复用时,可以更灵活地定义不同的工厂方法。
2025-08-01 17:30:36 +08:00
8 changed files with 52 additions and 87 deletions

View File

@@ -77,7 +77,7 @@ System.out.println(result); // Output: Return string
```java
public final class LoginException
extends RuntimeException
implements IMultiTypesException<LoginException, LoginException.Type, String> {
implements IMultiTypesException<LoginException.Type> {
private static final long serialVersionUID = 881293090625085616L;
private final Type type;
private LoginException(@Nonnull Type type, @Nonnull String message) {
@@ -104,7 +104,7 @@ public final class LoginException
// ...
public enum Type implements IExceptionType<LoginException, String> {
public enum Type implements IExceptionType<String>, IExceptionFactory<LoginException> {
DEFAULT("00", "当前会话未登录"),
NOT_TOKEN("10", "未提供token"),
INVALID_TOKEN("20", "token无效"),

View File

@@ -20,7 +20,8 @@ import javax.annotation.Nonnull;
/**
* 异常工厂
*
* @author ZhouXY
* @param <X> 异常类型
* @author ZhouXY108 <luquanlion@outlook.com>
*/
public interface IExceptionFactory<X extends Exception> {
/**

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.commons.exception;
import xyz.zhouxy.plusone.commons.annotation.Virtual;
import xyz.zhouxy.plusone.commons.base.IWithCode;
/**
* 异常场景
*
* @param <TCode> 场景编码
* @author ZhouXY108 <luquanlion@outlook.com>
*/
public interface IExceptionType<TCode> extends IWithCode<TCode> {
/**
* 默认异常信息
*/
String getDefaultMessage();
@Virtual
default String getDescription() {
return getDefaultMessage();
}
}

View File

@@ -15,13 +15,8 @@
*/
package xyz.zhouxy.plusone.commons.exception;
import java.io.Serializable;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.annotation.Virtual;
import xyz.zhouxy.plusone.commons.base.IWithCode;
/**
* IMultiTypesException
*
@@ -38,7 +33,7 @@ import xyz.zhouxy.plusone.commons.base.IWithCode;
* <pre>
* public final class LoginException
* extends RuntimeException
* implements IMultiTypesException&lt;LoginException, LoginException.Type, String&gt; {
* implements IMultiTypesException&lt;LoginException.Type&gt; {
* private static final long serialVersionUID = 881293090625085616L;
* private final Type type;
* private LoginException(&#64;Nonnull Type type, &#64;Nonnull String message) {
@@ -65,7 +60,7 @@ import xyz.zhouxy.plusone.commons.base.IWithCode;
*
* // ...
*
* public enum Type implements IExceptionType&lt;LoginException, String&gt; {
* public enum Type implements IExceptionType&lt;String&gt;, IExceptionFactory&lt;LoginException&gt; {
* DEFAULT("00", "当前会话未登录"),
* NOT_TOKEN("10", "未提供token"),
* INVALID_TOKEN("20", "token无效"),
@@ -122,15 +117,11 @@ import xyz.zhouxy.plusone.commons.base.IWithCode;
* throw LoginException.Type.TOKEN_TIMEOUT.create();
* </pre>
*
* @param <X> 具体异常类
* @param <T> 异常场景
* @author ZhouXY108 <luquanlion@outlook.com>
* @since 1.0.0
*/
public interface IMultiTypesException<
X extends Exception,
T extends IMultiTypesException.IExceptionType<X, TCode>,
TCode extends Serializable> {
public interface IMultiTypesException<T extends IExceptionType<?>> {
/**
* 异常类型
@@ -139,31 +130,4 @@ public interface IMultiTypesException<
*/
@Nonnull
T getType();
/**
* 获取异常类型编码
*
* @return 异常类型编码
*/
default @Nonnull TCode getTypeCode() {
return getType().getCode();
}
/**
* 异常类型
*/
public static interface IExceptionType<X extends Exception, TCode extends Serializable>
extends IWithCode<TCode>, IExceptionFactory<X> {
/**
* 默认异常信息
*/
String getDefaultMessage();
@Virtual
default String getDescription() {
return getDefaultMessage();
}
}
}

View File

@@ -21,7 +21,6 @@ import java.time.format.DateTimeParseException;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.exception.business.RequestParamsException;
import xyz.zhouxy.plusone.commons.exception.IMultiTypesException.IExceptionType;
/**
* 解析失败异常
@@ -39,7 +38,7 @@ import xyz.zhouxy.plusone.commons.exception.IMultiTypesException.IExceptionType;
*/
public final class ParsingFailureException
extends Exception
implements IMultiTypesException<ParsingFailureException, ParsingFailureException.Type, String> {
implements IMultiTypesException<ParsingFailureException.Type> {
private static final long serialVersionUID = 795996090625132616L;
private final Type type;
@@ -171,7 +170,7 @@ public final class ParsingFailureException
/** XML 解析失败 */
public static final Type XML_PARSING_FAILURE = Type.XML_PARSING_FAILURE;
public enum Type implements IExceptionType<ParsingFailureException, String> {
public enum Type implements IExceptionType<String>, IExceptionFactory<ParsingFailureException> {
DEFAULT("00", "解析失败"),
NUMBER_PARSING_FAILURE("10", "数字转换失败"),
DATE_TIME_PARSING_FAILURE("20", "时间解析失败"),

View File

@@ -18,7 +18,8 @@ package xyz.zhouxy.plusone.commons.exception.business;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.exception.IMultiTypesException.IExceptionType;
import xyz.zhouxy.plusone.commons.exception.IExceptionFactory;
import xyz.zhouxy.plusone.commons.exception.IExceptionType;
import xyz.zhouxy.plusone.commons.exception.IMultiTypesException;
/**
@@ -35,7 +36,7 @@ import xyz.zhouxy.plusone.commons.exception.IMultiTypesException;
*/
public final class InvalidInputException
extends RequestParamsException
implements IMultiTypesException<InvalidInputException, InvalidInputException.Type, String> {
implements IMultiTypesException<InvalidInputException.Type> {
private static final long serialVersionUID = -28994090625082516L;
private final Type type;
@@ -109,7 +110,7 @@ public final class InvalidInputException
return this.type;
}
public enum Type implements IExceptionType<InvalidInputException, String> {
public enum Type implements IExceptionType<String>, IExceptionFactory<InvalidInputException> {
DEFAULT("00", "用户输入内容非法"),
CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS("01", "包含非法恶意跳转链接"),
CONTAINS_ILLEGAL_WORDS("02", "包含违禁敏感词"),

View File

@@ -38,7 +38,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS.create();
});
assertSame(InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS, e.getType());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS.getCode(), e.getTypeCode());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS.getDefaultMessage(), e.getMessage());
assertNull(e.getCause());
}
@@ -50,7 +49,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.create(message);
});
assertSame(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS, e.getType());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -62,7 +60,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.PICTURE_CONTAINS_ILLEGAL_INFORMATION.create(message);
});
assertSame(InvalidInputException.Type.PICTURE_CONTAINS_ILLEGAL_INFORMATION, e.getType());
assertEquals(InvalidInputException.Type.PICTURE_CONTAINS_ILLEGAL_INFORMATION.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -77,7 +74,6 @@ public class InvalidInputExceptionTests {
});
assertSame(InvalidInputException.Type.INFRINGE_COPYRIGHT, e.getType());
assertEquals(InvalidInputException.Type.INFRINGE_COPYRIGHT.getCode(), e.getTypeCode());
log.info("{}", e.getMessage());
assertEquals(nfe.toString(), e.getMessage());
assertSame(nfe, e.getCause());
@@ -92,7 +88,6 @@ public class InvalidInputExceptionTests {
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -106,7 +101,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS.create(message, nfe);
});
assertSame(InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS, e.getType());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_AND_MALICIOUS_LINKS.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertSame(nfe, e.getCause());
}
@@ -120,7 +114,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.create(message, nfe);
});
assertSame(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS, e.getType());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertSame(nfe, e.getCause());
}
@@ -134,7 +127,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.create(message, npe);
});
assertSame(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS, e.getType());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -148,7 +140,6 @@ public class InvalidInputExceptionTests {
throw InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.create(message, nfe);
});
assertSame(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS, e.getType());
assertEquals(InvalidInputException.Type.CONTAINS_ILLEGAL_WORDS.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -167,7 +158,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException();
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertEquals(InvalidInputException.Type.DEFAULT.getDefaultMessage(), e.getMessage());
assertNull(e.getCause());
}
@@ -179,7 +169,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException(message);
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -191,7 +180,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException(message);
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -206,7 +194,6 @@ public class InvalidInputExceptionTests {
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
log.info("{}", e.getMessage());
assertEquals(nfe.toString(), e.getMessage());
assertSame(nfe, e.getCause());
@@ -221,7 +208,6 @@ public class InvalidInputExceptionTests {
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -235,7 +221,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException(message, nfe);
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertSame(nfe, e.getCause());
}
@@ -249,7 +234,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException(message, nfe);
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertSame(nfe, e.getCause());
}
@@ -263,7 +247,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException(message, npe);
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -277,7 +260,6 @@ public class InvalidInputExceptionTests {
throw new InvalidInputException(message, nfe);
});
assertSame(InvalidInputException.Type.DEFAULT, e.getType());
assertEquals(InvalidInputException.Type.DEFAULT.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}

View File

@@ -41,7 +41,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.DATE_TIME_PARSING_FAILURE.create();
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getDefaultMessage(), e.getMessage());
assertNull(e.getCause());
}
@@ -53,7 +52,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.JSON_PARSING_FAILURE.create(message);
});
assertSame(ParsingFailureException.Type.JSON_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.Type.JSON_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -65,7 +63,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.XML_PARSING_FAILURE.create(message);
});
assertSame(ParsingFailureException.XML_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.XML_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -80,7 +77,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
log.info("{}", e.getMessage());
assertEquals(nfe.toString(), e.getMessage());
assertSame(nfe, e.getCause());
@@ -95,7 +91,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -109,7 +104,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.NUMBER_PARSING_FAILURE.create(message, nfe);
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertSame(nfe, e.getCause());
}
@@ -123,7 +117,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.DATE_TIME_PARSING_FAILURE.create(message, nfe);
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertSame(nfe, e.getCause());
}
@@ -137,7 +130,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.DATE_TIME_PARSING_FAILURE.create(message, npe);
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -151,7 +143,6 @@ public class ParsingFailureExceptionTests {
throw ParsingFailureException.DATE_TIME_PARSING_FAILURE.create(message, nfe);
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -175,7 +166,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(dtpe.getMessage(), e.getMessage());
assertSame(dtpe, e.getCause());
}
@@ -189,7 +179,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getDefaultMessage(), e.getMessage());
assertNull(e.getCause());
}
@@ -206,7 +195,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertSame(dtpe, e.getCause());
}
@@ -223,7 +211,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertSame(dtpe, e.getCause());
}
@@ -238,7 +225,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -253,7 +239,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.DATE_TIME_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.DATE_TIME_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}
@@ -277,7 +262,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(dtpe.getMessage(), e.getMessage());
assertSame(dtpe, e.getCause());
}
@@ -291,7 +275,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getDefaultMessage(), e.getMessage());
assertNull(e.getCause());
}
@@ -308,7 +291,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertSame(dtpe, e.getCause());
}
@@ -325,7 +307,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertSame(dtpe, e.getCause());
}
@@ -340,7 +321,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertEquals(message, e.getMessage());
assertNull(e.getCause());
}
@@ -355,7 +335,6 @@ public class ParsingFailureExceptionTests {
});
assertSame(ParsingFailureException.NUMBER_PARSING_FAILURE, e.getType());
assertEquals(ParsingFailureException.NUMBER_PARSING_FAILURE.getCode(), e.getTypeCode());
assertNull(e.getMessage());
assertNull(e.getCause());
}