问题场景
原始路径模板:/users/{id}
实际获取路径:/users/40000478
在监控和统计场景中,带具体参数值的路径会导致:
- 相同的接口被统计为多个不同的路径
- 难以进行有效的聚合分析
- 通知信息不够清晰直观
解决方案:Spring MVC路径模板获取
Spring MVC在处理请求时,会在请求属性中存储丰富的映射信息。通过以下方式可以获取原始路径模板:
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
public class MonitoringUtils {
public static String getOriginalPathPattern(HttpServletRequest request) {
// 获取最佳匹配的路径模式,如 /ad/launch/task/sendConfirmEmail/{id}
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
// 如果获取不到路径模式,则回退到原始URI
return pattern != null ? pattern : request.getRequestURI();
}
}
关键请求属性详解
Spring MVC在HandlerMapping类中定义了多个有用的常量,可以从HttpServletRequest中获取:
BEST_MATCHING_PATTERN_ATTRIBUTE
- 用途:存储与请求最佳匹配的路径模式
- 场景:API监控统计的理想选择
- 示例值:
/users/{id}
URI_TEMPLATE_VARIABLES_ATTRIBUTE
- 用途:存储从URL中提取的路径变量映射
- 场景:需要同时获取路径参数名和值时使用
- 示例值:
{id: "40000478"}
@SuppressWarnings("unchecked")
Map<String, String> uriVariables = (Map<String, String>) request
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
String id = uriVariables.get("id"); // 返回 "40000478"
PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
- 用途:存储处理器映射内的实际路径
- 场景:获取去除上下文路径后的实际请求路径
- 示例值:
/users/40000478
BEST_MATCHING_HANDLER_ATTRIBUTE
- 用途:存储与请求最佳匹配的处理器对象
- 场景:需要获取具体Controller方法信息时使用
PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
- 用途:存储处理器能够产生的媒体类型列表,用于内容协商
- 内容协商过程:检查请求的
Accept头,查看控制器方法声明的produces类型,将匹配的可用媒体类型存储在PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE中,选择最合适的媒体类型生成响应 - 场景:自定义内容协商
MATRIX_VARIABLES_ATTRIBUTE
- 用途:存储矩阵变量(Matrix Variables)信息,用于处理特殊的URL参数格式
- 场景:矩阵变量(Matrix Variables)是URL中一种特殊的参数传递方式,使用分号(;)分隔而不是传统的问号。默认情况下,Spring MVC并不启用矩阵变量支持,因为矩阵变量在RFC中定义但较少使用
传统查询参数:/cars?color=red&make=ford
矩阵变量: /cars;color=red;make=ford
INTROSPECT_TYPE_LEVEL_MAPPING
- 作用:Spring MVC中一个相对底层的请求属性,它控制着Spring MVC在映射请求时是否进行类型级别的映射信息内省
- 场景:需要动态控制映射行为的应用程序,多版本API的复杂映射需求,性能敏感场景下的映射优化, 自定义URL映射策略的实现
总结
通过利用Spring MVC的HandlerMapping请求属性,我们可以优雅地获取原始路径模板,有效解决监控统计中的路径聚合问题。这种方法不仅使监控数据更加清晰,还提高了系统的可维护性和可观测性。