spring|从@PathVariable中学习获取path variable方法

背景 为使用spring aop解耦一个web请求中的通用逻辑,需要用到请求的uri中的参数。在web请求的controller中可以使用@PathVariable来获取对应参数,如何手动从HttpServletRequest中获取就是要研究的问题。
分析

  • 库版本
    • spring-webmvc 5.2.1.RELEASE
    • spring-web 5.2.1.RELEASE
    • tomcat-embed-core 9.0.27
  • 涉及类与接口
    • org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver
    • org.springframework.web.context.request.NativeWebRequest
    • org.springframework.web.context.request.WebRequest
    • org.springframework.web.context.request.RequestAttributes
    • org.springframework.web.context.request.RequestContextHolder
    • org.springframework.web.context.request.ServletWebRequest
    • org.springframework.web.context.request.ServletRequestAttributes
    • javax.servlet.http.HttpServletRequest
解析处理@PathVariable注解的代码
@Override @SuppressWarnings("unchecked") @Nullable protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { Map, String> uriTemplateVars = (Map, String>) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); return (uriTemplateVars != null ? uriTemplateVars.get(name) : null); }

【spring|从@PathVariable中学习获取path variable方法】上述代码中的接口NativeWebRequest继承了接口WebRequestWebRequest继承了接口RequestAttributes。通过打断点,确认了这里的request对象是ServletWebRequest对象,这个类继承自ServletRequestAttributes这里的运行逻辑可以继续深入探究)。
RequestContextHolder提供了static方法currentRequestAttributes()可以获取当前线程的RequestAttributes对象(可转换成ServletRequestAttributes对象),ServletRequestAttributes对象中封装了HttpServletRequest,而HttpServletRequest提供了类似ServletWebRequestgetAttribute()方法可以获取path variables。
这就意味着可以通过如下代码获得的path variablesmap,通过这个map可获得对应变量值。
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest(); Map, String> pathVariables = (Map, String>) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);

编码方案
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest(); Map, String> pathVariables = (Map, String>) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); String pathVariable = (pathVariables != null ? pathVariables.get("pathVariable") : null);

    推荐阅读