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
        }
    }
    
}
相关推荐
跟着珅聪学java3 分钟前
spring boot 整合 activiti 教程
android·java·spring
Java水解26 分钟前
Spring JDBC与KingbaseES深度集成:构建高性能国产数据库应用实战
后端·spring
junnhwan1 小时前
【苍穹外卖笔记】Day04--套餐管理模块
java·数据库·spring boot·后端·苍穹外卖·crud
程序员清风1 小时前
Dubbo RPCContext存储一些通用数据,这个用手动清除吗?
java·后端·面试
低音钢琴1 小时前
【SpringBoot从初学者到专家的成长15】MVC、Spring MVC与Spring Boot:理解其差异与联系
spring boot·spring·mvc
摇滚侠2 小时前
Spring Boot 3零基础教程,条件注解,笔记09
java·spring boot·笔记
南瓜小米粥、2 小时前
从可插拔拦截器出发:自定义、注入 Spring Boot、到生效路径的完整实践(Demo 版)
java·spring boot·后端
Huangmiemei9112 小时前
Spring Boot项目的常用依赖有哪些?
java·spring boot·后端
天天摸鱼的java工程师2 小时前
接口联调总卡壳?先问自己:真的搞清楚 HTTP 的 Header 和 Body 了吗?
java·后端
真的想不出名儿2 小时前
上传头像到腾讯云对象存储-前端基于antdv
java·数据库·腾讯云