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

相关推荐
white-persist35 分钟前
汇编代码详细解释:汇编语言如何转化为对应的C语言,怎么转化为对应的C代码?
java·c语言·前端·网络·汇编·安全·网络安全
程序员阿达1 小时前
开题报告之基于SpringBoot框架的图书借阅系统的设计与实现
java·spring boot·后端
Eoch771 小时前
吃透 Java 核心技术:JVM 调优、并发安全、微服务开发,解决 90% 企业级场景问题
java·后端
yaoxin5211231 小时前
229. Java 集合 - 操作集合中的多个元素(批量操作)
java·开发语言·python
C++chaofan1 小时前
MyBatis - Plus学习笔记
java·spring boot·笔记·后端·mysql·架构·mybatis
HSJ01701 小时前
Aviator中使用BigDecimal进行高精度计算
java·开发语言·bigdecimal·aviator
weixin_307779131 小时前
利用 AWS Lambda 与 EventBridge 优化低频 Java 作业的云计算成本
java·开发语言·云原生·云计算·aws
一缕南风2 小时前
Spring Boot 响应拦截器(Jackson)实现时间戳自动添加
java·spring boot·后端·拦截器
期待のcode2 小时前
Docker容器
java·docker·容器
Homeey2 小时前
深入理解 synchronized:从硬件原子性到并发架构设计
java·后端