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个属性放进去即可

相关推荐
tryxr2 分钟前
JVM 垃圾回收机制
java·jvm·gc·垃圾回收
揣一尾游鱼yu1 小时前
Spring上(IOC)笔记
java·笔记·spring·ioc
荣码1 小时前
长上下文与大文档处理:200页PDF怎么喂给AI,我踩了4个坑
java·python
极限挑战哥2 小时前
共享电单车联营平台分账架构实践:二清合规与自动分账零人工方案
java·大数据·人工智能·微信小程序·架构·微信公众平台
皮皮林5512 小时前
比 VMware 更快,更轻的虚拟机,横空出世!
java
Thomas.Sir2 小时前
第13课:MyBatis-Plus整合SpringBoot4.x,分页、条件查询、逻辑删除实战
java·spring boot
meiying88383 小时前
多快递公司快递单号批量查询接口怎么对接?Python 聚合查询实现
java·大数据·python
古法安卓3 小时前
Android-GPU压测工具
android·java·android studio
SL_staff3 小时前
10人团队如何用轻量私有化文档平台实现知识复用提效?技术视角拆解B/S架构下的协作闭环
java·开源·全栈
释厄6234 小时前
同性线套娃律——圆面积必然=1+2+...+n 的求和·圆心不与 π 相关
java·人工智能·算法·1024程序员节