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

相关推荐
jiaguangqingpanda4 分钟前
Day36-20260204
java·开发语言
tb_first10 分钟前
万字超详细苍穹外卖学习笔记4
java·spring boot·笔记·学习·spring·mybatis
努力写代码的熊大27 分钟前
c++异常和智能指针
java·开发语言·c++
山岚的运维笔记31 分钟前
SQL Server笔记 -- 第15章:INSERT INTO
java·数据库·笔记·sql·microsoft·sqlserver
Yvonne爱编码31 分钟前
JAVA数据结构 DAY5-LinkedList
java·开发语言·python
小王不爱笑1321 小时前
LangChain4J 整合多 AI 模型核心实现步骤
java·人工智能·spring boot
西凉的悲伤1 小时前
spring-boot-starter-validation使用注解进行参数校验
java·spring boot·参数校验·validation·注解校验参数
LucDelton1 小时前
Java 读取无限量文件读取的思路
java·运维·网络
夹锌饼干1 小时前
mysql死锁排查流程--(处理mysql阻塞问题)
java·mysql
小信丶2 小时前
@EnableTransactionManagement注解介绍、应用场景和示例代码
java·spring boot·后端