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
        }
    }
    
}
相关推荐
萤丰信息1 小时前
智慧园区能源革命:从“耗电黑洞”到零碳样本的蜕变
java·大数据·人工智能·科技·安全·能源·智慧园区
曹牧1 小时前
Eclipse为方法添加注释
java·ide·eclipse
我叫张小白。2 小时前
Spring Boot拦截器详解:实现统一的JWT认证
java·spring boot·web·jwt·拦截器·interceptor
Gerardisite4 小时前
如何在微信个人号开发中有效管理API接口?
java·开发语言·python·微信·php
q***69774 小时前
Spring Boot与MyBatis
spring boot·后端·mybatis
闲人编程5 小时前
Python的导入系统:模块查找、加载和缓存机制
java·python·缓存·加载器·codecapsule·查找器
故渊ZY5 小时前
Java 代理模式:从原理到实战的全方位解析
java·开发语言·架构
匿者 衍5 小时前
POI读取 excel 嵌入式图片(支持wps 和 office)
java·excel
一个尚在学习的计算机小白5 小时前
java集合
java·开发语言
IUGEI5 小时前
synchronized的工作机制是怎样的?深入解析synchronized底层原理
java·开发语言·后端·c#