记得上下班打卡 | git大法好,push需谨慎

Commit 6fc379f3 authored by 姜秀龙's avatar 姜秀龙

接口分级相关 order adam 配置

parent d1fb9e76
package com.liquidnet.common.swagger.annotation;
import java.lang.annotation.*;
/**
* 接口分级注解
* 用于标识接口的重要性级别
*
* @author system
* @since 2024-10-29
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLevel {
/**
* 接口级别 - 默认为L99(未配置),强制开发者明确指定级别
*/
Level level() default Level.L99;
/**
* 描述信息
*/
String description() default "";
/**
* 接口级别枚举 - 数字越小越重要
*/
enum Level {
L1(1, "核心", "核心业务功能,必须稳定,影响系统可用性"),
L2(2, "重要", "重要业务功能,影响用户体验"),
L3(3, "普通", "常规业务功能"),
L4(4, "低级", "非核心功能,影响范围小"),
L88(88, "无需分级", "该接口明确标记为无需分级或暂不分级"),
L99(99, "未配置", "该接口尚未配置分级信息");
private final int value;
private final String desc;
private final String detail;
Level(int value, String desc, String detail) {
this.value = value;
this.desc = desc;
this.detail = detail;
}
public int getValue() { return value; }
public String getDesc() { return desc; }
public String getDetail() { return detail; }
/**
* 判断是否为未配置级别
*/
public boolean isUnconfigured() {
return this == L99;
}
/**
* 判断是否为无需分级
*/
public boolean isNoGrading() {
return this == L88;
}
/**
* 根据数字值获取级别
*/
public static Level fromValue(int value) {
for (Level level : values()) {
if (level.value == value) {
return level;
}
}
return L99; // 默认返回未配置
}
/**
* 获取所有业务级别(排除L88和L99)
*/
public static Level[] getBusinessLevels() {
return new Level[]{L1, L2, L3, L4};
}
}
}
\ No newline at end of file
package com.liquidnet.common.swagger.config;
import com.liquidnet.common.swagger.annotation.ApiLevel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.service.StringVendorExtension;
import springfox.documentation.service.VendorExtension;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* Swagger插件 - 将ApiLevel信息显示在Swagger文档中
*
* @author system
* @since 2024-10-29
*/
@Component
@Order(1000)
@Slf4j
public class ApiLevelSwaggerPlugin implements OperationBuilderPlugin {
@Override
public void apply(OperationContext context) {
// 获取方法上的ApiLevel注解
Optional<ApiLevel> methodApiLevel = context.findAnnotation(ApiLevel.class);
// 如果方法上没有,尝试获取类上的注解(继承逻辑)
if (!methodApiLevel.isPresent()) {
methodApiLevel = context.findControllerAnnotation(ApiLevel.class);
}
// 获取当前的notes(描述)
String currentNotes = context.operationBuilder().build().getNotes();
String levelInfo;
if (methodApiLevel.isPresent()) {
ApiLevel apiLevel = methodApiLevel.get();
// 所有配置的级别都是正常的分级,包括L0
levelInfo = String.format("【接口级别:%s - %s】",
apiLevel.level().name(),
apiLevel.level().getDesc());
if (apiLevel.description() != null && !apiLevel.description().isEmpty()) {
levelInfo += " " + apiLevel.description();
}
addExtensions(context, apiLevel.level().name(), apiLevel.level().getDesc(),
apiLevel.level().getDetail(), apiLevel.description());
} else {
// 完全没有注解的情况,使用L99级别
ApiLevel.Level unconfiguredLevel = ApiLevel.Level.L99;
levelInfo = String.format("【接口级别:%s - %s】",
unconfiguredLevel.name(),
unconfiguredLevel.getDesc());
addExtensions(context, unconfiguredLevel.name(), unconfiguredLevel.getDesc(),
unconfiguredLevel.getDetail(), null);
}
// 将级别信息添加到notes中
String newNotes = currentNotes != null ?
levelInfo + "\n\n" + currentNotes : levelInfo;
context.operationBuilder().notes(newNotes);
}
/**
* 添加扩展字段到Swagger JSON
*/
private void addExtensions(OperationContext context, String level, String levelDesc,
String levelDetail, String description) {
try {
List<VendorExtension> extensions = new ArrayList<>();
extensions.add(new StringVendorExtension("x-api-level", level));
extensions.add(new StringVendorExtension("x-api-level-desc", levelDesc));
extensions.add(new StringVendorExtension("x-api-level-detail", levelDetail));
if (description != null && !description.trim().isEmpty()) {
extensions.add(new StringVendorExtension("x-api-description", description));
}
context.operationBuilder().extensions(extensions);
} catch (Exception e) {
log.debug("扩展字段设置失败: {}", e.getMessage());
}
}
@Override
public boolean supports(DocumentationType delimiter) {
// 支持Swagger 2.0,如果有OAS 3.0也尝试支持
if (DocumentationType.SWAGGER_2.equals(delimiter)) {
return true;
}
// 尝试支持OAS 3.0(如果可用)
try {
return "OAS_30".equals(delimiter.getName());
} catch (Exception e) {
return false;
}
}
}
\ No newline at end of file
package com.liquidnet.common.swagger.controller;
import com.liquidnet.common.swagger.annotation.ApiLevel;
import com.liquidnet.common.swagger.dto.ApiLevelInfoDto;
import com.liquidnet.common.swagger.dto.ApiLevelStatisticsDto;
import com.liquidnet.common.swagger.service.ApiLevelStatisticsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 接口分级统计控制器
*
* @author system
* @since 2024-10-29
*/
@Api(tags = "系统管理-接口分级统计")
@RestController
@RequestMapping("/levelStatistics")
@Slf4j
@ApiLevel(level = ApiLevel.Level.L2, description = "接口分级统计管理")
public class ApiLevelStatisticsController {
@Autowired
private ApiLevelStatisticsService apiLevelStatisticsService;
@GetMapping("/overview")
@ApiOperation("获取接口分级统计概览(理想是获取所有服务的数据, 但是现在还做不到预留吧)")
@ApiLevel(level = ApiLevel.Level.L3, description = "查看系统所有接口的分级统计信息")
public ApiLevelStatisticsDto getApiLevelStatistics() {
try {
return apiLevelStatisticsService.getApiLevelStatistics();
} catch (Exception e) {
log.error("获取接口分级统计失败", e);
throw new RuntimeException("获取接口分级统计失败: " + e.getMessage());
}
}
@GetMapping("/levels")
@ApiOperation("获取所有接口级别定义")
@ApiLevel(level = ApiLevel.Level.L4, description = "查看接口级别定义说明")
public List<ApiLevelInfoDto> getApiLevels() {
List<ApiLevelInfoDto> levels = new ArrayList<>();
for (ApiLevel.Level level : ApiLevel.Level.values()) {
ApiLevelInfoDto levelInfo = new ApiLevelInfoDto();
levelInfo.setCode(level.name()); // L1, L2, L3, L4, L88, L99
levelInfo.setValue(level.getValue()); // 1, 2, 3, 4, 88, 99
levelInfo.setLabel(level.getDesc()); // 核心, 重要, 普通, 低级, 无需分级, 未配置
levelInfo.setDescription(level.getDetail()); // 详细描述
levelInfo.setIsUnconfigured(level.isUnconfigured()); // 是否为未配置
levelInfo.setIsNoGrading(level.isNoGrading()); // 是否为无需分级
// 判断是否为业务级别 (L1-L4)
boolean isBusinessLevel = level.getValue() >= 1 && level.getValue() <= 4;
levelInfo.setIsBusinessLevel(isBusinessLevel);
levels.add(levelInfo);
}
return levels;
}
@GetMapping("/service")
@ApiOperation("获取本服务接口分级统计信息")
@ApiLevel(level = ApiLevel.Level.L3, description = "获取当前服务的接口分级统计,包含按级别分组的接口列表")
public Map<String, Object> getServiceStatistics() {
try {
ApiLevelStatisticsDto fullStats = apiLevelStatisticsService.getApiLevelStatistics();
Map<String, Object> serviceStats = new HashMap<>();
// 基础统计信息
serviceStats.put("totalCount", fullStats.getTotalCount());
serviceStats.put("levelStatistics", fullStats.getLevelStatistics());
// 按级别分组的接口列表 - 动态初始化所有级别
Map<String, List<Map<String, Object>>> apisByLevel = new HashMap<>();
for (ApiLevel.Level level : ApiLevel.Level.values()) {
apisByLevel.put(level.name(), new ArrayList<>());
}
// 将接口按级别分组
for (ApiLevelStatisticsDto.ApiInfo api : fullStats.getApiList()) {
Map<String, Object> apiInfo = new HashMap<>();
apiInfo.put("url", api.getUrl());
apiInfo.put("method", api.getHttpMethod());
apiInfo.put("controller", api.getControllerName());
apiInfo.put("methodName", api.getMethodName());
apiInfo.put("description", api.getApiDescription());
// 现在所有接口都有级别(包括L99未配置)
String levelKey = api.getLevel().name();
apisByLevel.get(levelKey).add(apiInfo);
}
serviceStats.put("apisByLevel", apisByLevel);
return serviceStats;
} catch (Exception e) {
log.error("获取服务统计失败", e);
throw new RuntimeException("获取服务统计失败: " + e.getMessage());
}
}
}
\ No newline at end of file
package com.liquidnet.common.swagger.dto;
import lombok.Data;
/**
* 接口级别信息DTO
*
* @author system
* @since 2024-10-29
*/
@Data
public class ApiLevelInfoDto {
/**
* 级别代码 (L1, L2, L3, L4, L88, L99)
*/
private String code;
/**
* 级别数值 (1, 2, 3, 4, 88, 99)
*/
private Integer value;
/**
* 级别标签 (核心, 重要, 普通, 低级, 无需分级, 未配置)
*/
private String label;
/**
* 级别详细描述
*/
private String description;
/**
* 是否为未配置级别
*/
private Boolean isUnconfigured;
/**
* 是否为无需分级级别
*/
private Boolean isNoGrading;
/**
* 是否为业务级别 (L1-L4)
*/
private Boolean isBusinessLevel;
}
\ No newline at end of file
package com.liquidnet.common.swagger.dto;
import com.liquidnet.common.swagger.annotation.ApiLevel;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 接口分级统计数据传输对象
*
* @author system
* @since 2024-10-29
*/
@Data
public class ApiLevelStatisticsDto {
/**
* 接口总数
*/
private Integer totalCount;
/**
* 接口列表
*/
private List<ApiInfo> apiList;
/**
* 级别统计 (级别名称 -> 数量)
*/
private Map<String, Integer> levelStatistics;
/**
* 服务统计 (服务名称 -> (级别名称 -> 数量))
*/
private Map<String, Map<String, Integer>> serviceStatistics;
/**
* 接口信息
*/
@Data
public static class ApiInfo {
/**
* 服务名称
*/
private String serviceName;
/**
* 控制器名称
*/
private String controllerName;
/**
* 方法名称
*/
private String methodName;
/**
* 接口URL
*/
private String url;
/**
* HTTP方法
*/
private String httpMethod;
/**
* 接口级别
*/
private ApiLevel.Level level;
/**
* 分级描述
*/
private String description;
/**
* API描述
*/
private String apiDescription;
}
}
\ No newline at end of file
......@@ -115,6 +115,8 @@ spring:
# -----------------------------------------------------------
global-auth:
exclude-url-pattern: # 模式I(与模式II互斥)
- ${liquidnet.info.context}/levelTest/**
- ${liquidnet.info.context}/levelStatistics/**
- ${liquidnet.info.context}/doc.html
- ${liquidnet.info.context}/webjars/**
- ${liquidnet.info.context}/swagger-resources/**
......
......@@ -108,6 +108,8 @@ spring:
# -----------------------------------------------------------
global-auth:
exclude-url-pattern:
- ${liquidnet.info.context}/levelTest/**
- ${liquidnet.info.context}/levelStatistics/**
- ${liquidnet.info.context}/doc.html
- ${liquidnet.info.context}/webjars/**
- ${liquidnet.info.context}/swagger-resources/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment