springboot返回所有接口详细信息

springboot返回所有接口详细信息

简单来说

就是我们通过访问一个接口能看到我们所有的API接口的数量。

以及路径和请求方法。

这个是我今天再做一个项目的首页的时候。

前端的设计是有一个这样的需求

因此这个数据需要我们从后台来进行一个动态的获取。

这里我们所需要用到的就是

spring-boot-starter-actuator

首先导入依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
java 复制代码
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import org.springframework.context.ApplicationContext;

import java.util.*;

@RestController
@RequestMapping("/uapi/api-list")
@Tag(name = "API列表", description = "API列表")
public class ApiListController {

    private final RequestMappingHandlerMapping handlerMapping;

    @Autowired
    public ApiListController(ApplicationContext context) {
        this.handlerMapping = context.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
    }

    @GetMapping
    @Operation(summary = "获取所有API列表")
    public Map<String, Object> listAllApi() {
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
        List<Map<String, String>> apiList = new ArrayList<>();

        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
            RequestMappingInfo info = entry.getKey();
            Set<String> paths = new HashSet<>();

            // ✅ 只使用 Spring Boot 3 推荐方式
            if (info.getPathPatternsCondition() != null) {
                info.getPathPatternsCondition().getPatterns()
                    .forEach(p -> paths.add(p.getPatternString()));
            }

            Set<RequestMethod> methods = info.getMethodsCondition().getMethods();

            for (String path : paths) {
                if (methods.isEmpty()) {
                    apiList.add(Map.of("method", "ANY", "path", path));
                } else {
                    for (RequestMethod method : methods) {
                        apiList.add(Map.of("method", method.name(), "path", path));
                    }
                }
            }
        }

        Map<String, Object> result = new HashMap<>();
        result.put("count", apiList.size());
        result.put("apis", apiList);
        return result;
    }
}

上面贴出的是springboot3的写法。

这个代码的核心原理就是

通过反射获取 Spring Boot 项目中所有控制器方法的路径和请求方式,然后把这些信息组织成一个列表,返回给用户。通过这种方式,开发者可以查看当前 Spring Boot 项目中的所有公开 API 接口及其支持的请求方法。

这一过程的核心依赖是 Spring Boot 的 RequestMappingHandlerMapping 类,该类负责管理所有请求路径的映射,能够获取每个路径的具体信息。

java 复制代码
Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
  • handlerMapping.getHandlerMethods() 通过 Spring 的 RequestMappingHandlerMapping 类获取所有已经注册的请求映射信息。
  • 这里返回的是一个 MapkeyRequestMappingInfo(包含了路径和请求方法的相关信息),valueHandlerMethod(指向处理该请求的控制器方法)。

后面的就是在对返回的数据进行一个处理。

之后就会返回一个这样的json

这样就完成了我们的需求。

需要注意的是这段代码

java 复制代码
if (info.getPathPatternsCondition() != null) {
    info.getPathPatternsCondition().getPatterns()
        .forEach(p -> paths.add(p.getPatternString()));
}

✅ Spring Boot 3.x 的新方式:使用 getPathPatternsCondition() 获取路径集合(Pattern 类型),然后转成字符串加到 paths 里。

Spring Boot 2.x 是用 getPatternsCondition(),在 3.x 中已经废弃。

后面我贴了一个兼容版本,既可以兼容springboot3也可以兼容springboot2

java 复制代码
@GetMapping("/api-list")
public Map<String, Object> listAllApi() {
    Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
    List<Map<String, String>> apiList = new ArrayList<>();

    for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
        RequestMappingInfo info = entry.getKey();
        Set<String> paths = new HashSet<>();

        // Spring Boot 2.x
        if (info.getPatternsCondition() != null) {
            paths.addAll(info.getPatternsCondition().getPatterns());
        }

        // Spring Boot 3.x
        if (info.getPathPatternsCondition() != null) {
            info.getPathPatternsCondition().getPatterns()
                .forEach(p -> paths.add(p.getPatternString()));
        }

        Set<RequestMethod> methods = info.getMethodsCondition().getMethods();

        for (String path : paths) {
            if (methods.isEmpty()) {
                apiList.add(Map.of("method", "ANY", "path", path));
            } else {
                for (RequestMethod method : methods) {
                    apiList.add(Map.of("method", method.name(), "path", path));
                }
            }
        }
    }

    Map<String, Object> result = new HashMap<>();
    result.put("count", apiList.size());
    result.put("apis", apiList);
    return result;
}
相关推荐
努力的小郑1 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
Victor3562 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3562 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁2 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp2 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
宁瑶琴4 小时前
COBOL语言的云计算
开发语言·后端·golang
普通网友4 小时前
阿里云国际版服务器,真的是学生党的性价比之选吗?
后端·python·阿里云·flask·云计算
IT_陈寒5 小时前
Vue的这个响应式问题,坑了我整整两小时
前端·人工智能·后端
Soofjan5 小时前
Go 内存回收-GC 源码1-触发与阶段
后端
shining6 小时前
[Golang]Eino探索之旅-初窥门径
后端