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
        }
    }
    
}
相关推荐
蘑菇丁26 分钟前
ansible批量生产kerberos票据,并批量分发到所有其他主机脚本
java·ide·eclipse
呼啦啦啦啦啦啦啦啦1 小时前
【Redis】持久化机制
java·redis·mybatis
我想学LINUX2 小时前
【2024年华为OD机试】 (A卷,100分)- 微服务的集成测试(JavaScript&Java & Python&C/C++)
java·c语言·javascript·python·华为od·微服务·集成测试
空の鱼7 小时前
java开发,IDEA转战VSCODE配置(mac)
java·vscode
!!!5257 小时前
日志技术-LogBack入门程序&Log配置文件&日志级别
spring boot
P7进阶路8 小时前
Tomcat异常日志中文乱码怎么解决
java·tomcat·firefox
小丁爱养花8 小时前
Spring MVC:HTTP 请求的参数传递2.0
java·后端·spring
CodeClimb9 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
等一场春雨9 小时前
Java设计模式 九 桥接模式 (Bridge Pattern)
java·设计模式·桥接模式