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

相关推荐
工业3D_大熊2 分钟前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
szc17676 分钟前
docker 相关命令
java·docker·jenkins
程序媛-徐师姐15 分钟前
Java 基于SpringBoot+vue框架的老年医疗保健网站
java·vue.js·spring boot·老年医疗保健·老年 医疗保健
yngsqq16 分钟前
c#使用高版本8.0步骤
java·前端·c#
尘浮生26 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
小白不太白95030 分钟前
设计模式之 模板方法模式
java·设计模式·模板方法模式
Tech Synapse32 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
xoxo-Rachel39 分钟前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天24940 分钟前
JDBC编程---Java
java·开发语言·sql