http-plugin支持url pathVariable解析和变量提取

一、背景

jvm-sandbox-repeater提供了http-plugin的基本实现,通过拦截javax.servlet.http.HttpServlet#service 方法从而拿到http的请求和返回,本次我们将扩展该插件实现,支持springMVC path url的变量解析和提取

首先我们定义一个controller, 带路径变量的

java 复制代码
@RequestMapping("/api/test")
@RestController
public class TestController {

    @ResponseBody
    @RequestMapping("testPathVariable/{v}")
    public Result testPathVariable(@PathVariable String v)  {
        System.out.println(v);
        return Result.buildSuccess("成功");
    }
}

我们请求该url, 执行shell命令

shell 复制代码
curl 'http://127.0.0.1:8080/api/test/testPathVariable/111'

那么对于这种的, 流量采集之后的路径是 /api/test/testPathVariable/111, 其中111其实是变量

因为我们涉及到很多配置,需要以路径来作为标识,因此理想的效果应该如下, 也就是 /api/test/testPathVariable/{v}

至此,应该理解我想要达到的效果了;

二、springMVC 关键代码解析

springMvc启动的时候,会初始化handlerMappings, HandlerMapping 是一个非常重要的组件,它的作用是将URL请求映射到相应的处理程序上。具体来说,HandlerMapping 会根据URL请求的路径、请求参数等信息,确定需要执行哪个处理程序,并将该处理程序返回给 DispatcherServlet。然后 DispatcherServlet 再将请求分配给相应的处理程序,处理程序处理完请求后,将结果返回给 DispatcherServlet,DispatcherServlet 再将结果返回给客户端。 其中handlerMapping有多种实现,见截图

我们通过debug发现,DispatcherServlet#doDispatch 中会调用 org.springframework.web.servlet.DispatcherServlet#getHandler 来获取执行链,最终会执行到org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch里,其中有一段非常重要的逻辑跟每次业务有关系

再看 org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#extractMatchDetails(org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition, java.lang.String, javax.servlet.http.HttpServletRequest)

ini 复制代码
private void extractMatchDetails(
      PathPatternsRequestCondition condition, String lookupPath, HttpServletRequest request) {

   PathPattern bestPattern;
   Map<String, String> uriVariables;
   if (condition.isEmptyPathMapping()) {
      bestPattern = condition.getFirstPattern();
      uriVariables = Collections.emptyMap();
   }
   else {
      PathContainer path = ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication();
      bestPattern = condition.getFirstPattern();
      PathPattern.PathMatchInfo result = bestPattern.matchAndExtract(path);
      Assert.notNull(result, () ->
            "Expected bestPattern: " + bestPattern + " to match lookupPath " + path);
      uriVariables = result.getUriVariables();
      request.setAttribute(MATRIX_VARIABLES_ATTRIBUTE, result.getMatrixVariables());
   }
   //这里将相关的urlPattern都放到请求的扩展属性里了
   request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern.getPatternString());
   request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
}

至此,我们就可以发现,直接从request的扩展属性中提取相应信息即可;

三、http plugin修改

修改com.alibaba.jvm.sandbox.repater.plugin.http.wrapper.WrapperTransModel,新增如下方法

java 复制代码
public String getMatchPattern() {
    String matchPattern = (String) request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingPattern");
    return matchPattern;
}

public Map<String, String> getUriVariables() {
    Map<String, String> res = new HashMap<>();
    if (request.getAttribute("org.springframework.web.servlet.HandlerMapping.uriTemplateVariables")!=null) {
        res.putAll((Map<String, String>)request.getAttribute("org.springframework.web.servlet.HandlerMapping.uriTemplateVariables"));
    }

    return res;
}

修改 com.alibaba.jvm.sandbox.repater.plugin.http.HttpStandaloneListener#assembleHttpAttribute, 将刚才的2个属性放进去即可

相关推荐
聚美智数6 小时前
智能结构化识别-图片结构解析-图像结构化解析-照片结构化解析
android·java·数据库
十年Java程序媛6 小时前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
我是人✓6 小时前
SpringBoot静态资源映射揭秘
java·spring boot·后端
土豆.exe7 小时前
nf_tables 的 verdict 被读了两次:一个十年未闭合的位域错配
java·数据库·网络安全·缓存
小坏讲微服务8 小时前
刚发布一个月的JDK 27,为什么我建议你立刻升级?
java·开发语言·spring boot·spring·架构·求职招聘·springboot4
kunicoding8 小时前
多线程编程核心概念详解:从线程基础到并发安全
java·jvm·安全
snow@li9 小时前
SpringBoot:核心注解全景梳理 / @xxx 叫“注解”(Annotation)
java·spring
devilnumber9 小时前
避坑_IDEA 提取方法(Extract Method)工具
java·ide·intellij-idea
鬼手点金9 小时前
Agent 的学习机制:后训练、上下文学习与外部化学习
java·人工智能·git·学习·自动化·nanogpt
小陈不好吃9 小时前
equals 与 hashCode 的契约关系:从 HashMap 到 Lombok 注解
java·hashmap·lombok