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
        }
    }
    
}
相关推荐
gelald4 分钟前
SpringBoot - 自动配置原理
java·spring boot·后端
@yanyu6664 分钟前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
殷紫川5 分钟前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月10 分钟前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
chenjingming66614 分钟前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
殷紫川19 分钟前
深入拆解 Java volatile:从内存屏障到无锁编程的实战指南
java
eddieHoo26 分钟前
查看 Tomcat 的堆内存参数
java·tomcat
那个失眠的夜27 分钟前
Mybatis延迟加载策略
xml·java·数据库·maven·mybatis
Java成神之路-36 分钟前
SpringMVC 响应实战指南:页面、文本、JSON 返回全流程(Spring系列13)
java·spring·json
殷紫川38 分钟前
深入拆解 synchronized:从偏向锁到重量级锁的升级之旅与优化秘籍
java