-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(api-doc/web): 重构doc文档枚举展示处理,处理doc 文档全局响应格式
- Loading branch information
Showing
7 changed files
with
309 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
...starter-api-doc/src/main/java/top/continew/starter/apidoc/handler/GenericEnumHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package top.continew.starter.apidoc.handler; | ||
|
||
import cn.hutool.core.util.ClassUtil; | ||
import cn.hutool.core.util.StrUtil; | ||
import com.fasterxml.jackson.databind.type.CollectionType; | ||
import com.fasterxml.jackson.databind.type.SimpleType; | ||
import io.swagger.v3.core.converter.AnnotatedType; | ||
import io.swagger.v3.oas.models.media.Schema; | ||
import io.swagger.v3.oas.models.parameters.Parameter; | ||
import org.springdoc.core.customizers.ParameterCustomizer; | ||
import org.springdoc.core.customizers.PropertyCustomizer; | ||
import org.springframework.core.MethodParameter; | ||
|
||
|
||
import java.lang.reflect.Type; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import top.continew.starter.apidoc.util.DocUtils; | ||
import top.continew.starter.core.enums.BaseEnum; | ||
|
||
/** | ||
* 枚举处理程序 | ||
* 主要实现对 继承了 BaseEnum 类型的枚举参数和属性进行处理 | ||
* | ||
* @Author echo | ||
* @date 2024/08/12 | ||
*/ | ||
public class GenericEnumHandler implements ParameterCustomizer, PropertyCustomizer { | ||
@Override | ||
public Parameter customize(Parameter parameterModel, MethodParameter methodParameter) { | ||
Class<?> parameterType = methodParameter.getParameterType(); | ||
// 判断是否为 BaseEnum 的子类型 | ||
if (!ClassUtil.isAssignable(BaseEnum.class, parameterType)) { | ||
return parameterModel; | ||
} | ||
String description = parameterModel.getDescription(); | ||
if (StrUtil.contains(description, "color:red")) { | ||
return parameterModel; | ||
} | ||
// 自定义枚举描述并封装参数配置 | ||
configureSchema(parameterModel.getSchema(), parameterType); | ||
parameterModel.setDescription(appendEnumDescription(description, parameterType)); | ||
return parameterModel; | ||
} | ||
|
||
@Override | ||
public Schema customize(Schema schema, AnnotatedType type) { | ||
Class<?> rawClass = resolveRawClass(type.getType()); | ||
// 判断是否为 BaseEnum 的子类型 | ||
if (!ClassUtil.isAssignable(BaseEnum.class, rawClass)) { | ||
return schema; | ||
} | ||
// 自定义参数描述并封装参数配置 | ||
configureSchema(schema, rawClass); | ||
schema.setDescription(appendEnumDescription(schema.getDescription(), rawClass)); | ||
return schema; | ||
} | ||
|
||
/** | ||
* 封装 Schema 配置 | ||
* | ||
* @param schema Schema | ||
* @param enumClass 枚举类型 | ||
*/ | ||
private void configureSchema(Schema schema, Class<?> enumClass) { | ||
BaseEnum[] enums = (BaseEnum[]) enumClass.getEnumConstants(); | ||
List<String> valueList = Arrays.stream(enums) | ||
.map(e -> e.getValue().toString()).toList(); | ||
schema.setEnum(valueList); | ||
String enumValueType = DocUtils.getEnumValueTypeAsString(enumClass); | ||
schema.setType(enumValueType); | ||
schema.setFormat(DocUtils.resolveFormat(enumValueType)); | ||
} | ||
|
||
|
||
/** | ||
* 追加枚举描述 | ||
* | ||
* @param originalDescription 原始描述 | ||
* @param enumClass 枚举类型 | ||
* @return 追加后的描述字符串 | ||
*/ | ||
private String appendEnumDescription(String originalDescription, Class<?> enumClass) { | ||
return originalDescription + "<span style='color:red'>" + DocUtils.getDescMap(enumClass) + "</span>"; | ||
} | ||
|
||
/** | ||
* 解析原始类 | ||
* | ||
* @param type 类型 | ||
* @return 原始类的 Class 对象 | ||
*/ | ||
private Class<?> resolveRawClass(Type type) { | ||
if (type instanceof SimpleType) { | ||
return ((SimpleType) type).getRawClass(); | ||
} else if (type instanceof CollectionType) { | ||
return ((CollectionType) type).getContentType().getRawClass(); | ||
} else { | ||
return Object.class; | ||
} | ||
} | ||
} |
132 changes: 132 additions & 0 deletions
132
continew-starter-api-doc/src/main/java/top/continew/starter/apidoc/util/DocUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package top.continew.starter.apidoc.util; | ||
|
||
import cn.hutool.core.collection.CollUtil; | ||
import java.lang.reflect.ParameterizedType; | ||
import java.lang.reflect.Type; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import top.continew.starter.core.enums.BaseEnum; | ||
|
||
/** | ||
* 接口文档工具类 | ||
* | ||
* @Author echo | ||
* @date 2024/07/31 | ||
*/ | ||
public class DocUtils { | ||
|
||
private DocUtils() { | ||
} | ||
|
||
/** | ||
* 获取枚举值类型 | ||
* | ||
* @param enumClass 枚举类型 | ||
* @return 枚举值类型 | ||
*/ | ||
public static String getEnumValueTypeAsString(Class<?> enumClass) { | ||
// 获取枚举类实现的所有接口 | ||
Type[] interfaces = enumClass.getGenericInterfaces(); | ||
// 定义枚举值类型的映射 | ||
Map<Class<?>, String> typeMap = Map.of( | ||
Integer.class, "integer", | ||
Long.class, "long", | ||
Double.class, "number", | ||
String.class, "string" | ||
); | ||
// 遍历所有接口 | ||
for (Type type : interfaces) { | ||
// 检查接口是否为参数化类型并且原始类型为 BaseEnum | ||
if (type instanceof ParameterizedType parameterizedType && parameterizedType.getRawType() == BaseEnum.class) { | ||
Type actualType = parameterizedType.getActualTypeArguments()[0]; | ||
// 检查实际类型参数是否为类类型,并返回对应的字符串类型 | ||
if (actualType instanceof Class<?> actualClass) { | ||
return typeMap.getOrDefault(actualClass, "string"); | ||
} | ||
} | ||
} | ||
// 默认返回 "string" 类型 | ||
return "string"; | ||
} | ||
|
||
/** | ||
* 解析枚举值的格式 | ||
* | ||
* @param enumValueType 枚举值类型 | ||
* @return String 格式化类型 | ||
*/ | ||
public static String resolveFormat(String enumValueType) { | ||
return switch (enumValueType) { | ||
case "integer" -> "int32"; | ||
case "long" -> "int64"; | ||
case "number" -> "double"; | ||
default -> enumValueType; | ||
}; | ||
} | ||
|
||
|
||
/** | ||
* 具有RestController 注释 既检查是否继承了BaseController | ||
* | ||
* @param clazz clazz | ||
* @return boolean | ||
*/ | ||
public static boolean hasRestControllerAnnotation(Class<?> clazz) { | ||
// 如果注释包含 RestController 注解,则返回 true | ||
if (clazz.isAnnotationPresent(RestController.class)) { | ||
return true; | ||
} | ||
// 递归检查父类 | ||
Class<?> superClass = clazz.getSuperclass(); | ||
// 循环检查父类 | ||
while (superClass != null && !superClass.equals(Object.class)) { | ||
// 如果父类包含 RestController 注解,则返回 true | ||
if (hasRestControllerAnnotation(superClass)) { | ||
return true; | ||
} | ||
// 递归检查接口 | ||
superClass = superClass.getSuperclass(); | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* 获取枚举描述 Map | ||
* | ||
* @param enumClass 枚举类型 | ||
* @return 枚举描述 Map | ||
*/ | ||
public static Map<Object, String> getDescMap(Class<?> enumClass) { | ||
BaseEnum[] enums = (BaseEnum[]) enumClass.getEnumConstants(); | ||
return Arrays.stream(enums) | ||
.collect(Collectors.toMap(BaseEnum::getValue, BaseEnum::getDescription, (a, b) -> a, LinkedHashMap::new)); | ||
} | ||
|
||
/** | ||
* 将collection转化为Set集合,但是两者的泛型不同<br> | ||
* <B>{@code Collection<E> ------> Set<T> } </B> | ||
* | ||
* @param collection 需要转化的集合 | ||
* @param function collection中的泛型转化为set泛型的lambda表达式 | ||
* @param <E> collection中的泛型 | ||
* @param <T> Set中的泛型 | ||
* @return 转化后的Set | ||
*/ | ||
public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) { | ||
if (CollUtil.isEmpty(collection) || function == null) { | ||
return CollUtil.newHashSet(); | ||
} | ||
return collection | ||
.stream() | ||
.map(function) | ||
.filter(Objects::nonNull) | ||
.collect(Collectors.toSet()); | ||
} | ||
} |
Oops, something went wrong.