SpringBoot根据URL路径调用Controller控制器

通过web上下文获取到所有 RequestMapping 的方法集合,根据 HandlerMethod 提供的方法调用对应 Method 的反射方法。

java 复制代码
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
@RequiredArgsConstructor
public class UrlToController implements CommandLineRunner {

    /**
     * 上下文
     */
    @Autowired
    WebApplicationContext applicationContext;

    private final HashMap<String, HandlerMethod> requestMapping = new HashMap<>();

    @Override
    public void run(String... args) throws Exception {
        loadControllerMethods();
    }

    /**
     * 加载控制器方法
     */
    public void loadControllerMethods() {
        // 获取RequestMappingHandlerMapping实例
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 获取映射的方法集合
        Map<RequestMappingInfo, HandlerMethod> methodMap = mapping.getHandlerMethods();
        // 遍历方法集合,提取路径模式和方法的映射关系
        methodMap.forEach((key, value) -> {
            // 初始化路径模式集合
            Set<PathPattern> patterns = null;
            // 检查路径模式条件是否存在
            if (key != null && key.getPathPatternsCondition() != null) {
                patterns = key.getPathPatternsCondition().getPatterns();
            }
            // 检查路径模式集合是否非空
            if (patterns != null && !patterns.isEmpty()) {
                // 获取第一个路径模式
                PathPattern pathPattern = patterns.iterator().next();
                // 提取并保存路径模式字符串及其对应的处理方法
                if (pathPattern != null) {
                    String urlPath = pathPattern.getPatternString();
                    requestMapping.put(urlPath, value);
                }
            }
        });

//        Object invoke = invokeControllerMethod("/CustomMenu/selectListByType/{type}");
//        System.out.println(invoke);
//        System.out.println(requestMapping);
    }


    /**
     * 根据URL路径调用控制器方法
     *
     * 该方法首先检查是否已为给定的URL路径注册了处理方法如果已注册,
     * 它会从应用程序上下文中获取控制器实例,然后调用该控制器的相应方法
     * 如果未注册或调用过程中发生异常,将返回错误信息或null
     *
     * @param urlPath URL路径,用于查找相应的处理方法
     * @param args    传递给控制器方法的参数,可变参数列表
     * @return 控制器方法的返回值,或在异常情况下的错误信息,如果未找到处理方法则返回null
     */
    public Object invokeControllerMethod(String urlPath, Object... args) {
        if (requestMapping.containsKey(urlPath)) { // 检查是否有对应的处理方法
            try {
                HandlerMethod handlerMethod = requestMapping.get(urlPath); // 获取处理方法
                Object controller = applicationContext.getBean(handlerMethod.getBeanType()); // 获取控制器实例
                return handlerMethod.getMethod().invoke(controller, args); // 调用控制器方法,并返回结果
            } catch (Exception e) {
                e.printStackTrace(); // 打印异常堆栈跟踪
                return e.getMessage(); // 返回异常信息
            }
        } else  {
            return null; // 如果没有对应的处理方法,返回null
        }
    }
    
}
相关推荐
Amarantine、沐风倩✨31 分钟前
设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)
java·物联网·音视频·webrtc·html5·视频编解码·七牛云存储
路在脚下@2 小时前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
啦啦右一2 小时前
Spring Boot | (一)Spring开发环境构建
spring boot·后端·spring
森屿Serien2 小时前
Spring Boot常用注解
java·spring boot·后端
苹果醋33 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader3 小时前
深入解析 Apache APISIX
java·apache
菠萝蚊鸭3 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪4 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0074 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生4 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl