是否还记得SpringMVC中的@MatrixVariable注解?
创始人
2025-07-13 09:31:15
0

环境:SpringBoot3.0.5

1. 简介

RFC 3986【https://datatracker.ietf.org/doc/html/rfc3986#section-3.3】讨论了路径段中的name-value对。在Spring MVC中,我们将它们称为“矩阵变量”,但它们也可以称为URI路径参数。

矩阵变量可以出现在任何路径段中,每个变量用分号分隔,多个值用逗号分隔(例如/cars;color=red,green;year=2012)。还可以通过重复的变量名指定多个值(例如,color=red;color=green;color=blue)。

如果期望URL包含矩阵变量,则控制器方法的请求映射必须使用URI变量来屏蔽变量内容,并确保请求可以成功匹配,而不依赖于矩阵变量的顺序和存在。下面的例子使用了一个矩阵变量:

// GET /pets/42;q=11;r=22
@GetMapping("/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) {
  // petId == 42
  // q == 11
}

@MatrixVariable应用场景

  • 主要适用于需要在URI路径中传递多个与路径段相关的参数,并且希望保持URI清晰、语义化的情况下。
  • 一个资源需要通过多维度资源定位时,一个URI可能需要同时标识多个维度的信息。比如在一个图片处理服务中,可能会通过颜色模式、分辨率等参数来定位特定版本的图片资源。
/images/pic1.png;colors=rgb;resolution=high

2. 实战案例

2.1 案例1 

@GetMapping("/m1/{id}")
public Object matrix1(@PathVariable("id") Long id, @MatrixVariable Integer q, @MatrixVariable String p) {
  return String.format("input, id: %d, q: %d, p: %s", id, q, p) ;
}

请求

图片图片

2.2 案例2

多个矩阵变量,在不同的路径变量中定义

@GetMapping("/m2/{cateId}/a2/{artId}")
public Object matrix2(
    @PathVariable("cateId") Long cateId, 
    @MatrixVariable(pathVar = "cateId", name = "q") Integer q1, 
    @PathVariable("artId") Long artId, 
    @MatrixVariable(pathVar = "artId", name = "q") Integer q2) {
  return String.format("input, cateId: %d, q: %d, artId: %d, q: %s%n", 
      cateId, q1, artId, q2) ;
}

请求

图片图片

2.3 案例3

使用Map接收矩阵值

@GetMapping("/m3/{cateId}/a2/{artId}")
public Object matrix3(
    @PathVariable("cateId") Long cateId, 
    @MatrixVariable MultiValueMap cateMap, 
    @PathVariable("artId") Long artId, 
    @MatrixVariable(pathVar = "artId") MultiValueMap artMap) {
  return Map.of("cate", cateMap, "art", artMap) ;
}

请求

图片图片

注意:这里的a=1,2有多个值可以使用','分割。

2.4 案例4

当变量路径之后没有添加矩阵参数时,会报错。

图片图片

我们可以通过配置,指定非必须活着设定默认值。

@GetMapping("/m2/{cateId}/a2/{artId}")
  public Object matrix2(
      ...,
      // 设置默认值
      @MatrixVariable(pathVar = "artId", name = "q", required = false, defaultValue = "999") Integer q2) {
    return String.format("input, cateId: %d, q: %d, artId: %d, q: %s%n", 
        cateId, q1, artId, q2) ;
  }

3. 实现原理

这里以上面的 案例2 讲解。

3.1 路径匹配存储矩阵变量

public abstract class AbstractHandlerMethodMapping {
  protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
  }
  protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) {
    handleMatch(bestMatch.mapping, lookupPath, request);
  }
}

beastMatch.mapping

图片图片

lookupPath

图片图片

public abstract class RequestMappingInfoHandlerMapping {
  protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) {
    extractMatchDetails(pprc, lookupPath, request);
  }
  private void extractMatchDetails(...) {
    // 将矩阵编码存入到request对象中
    request.setAttribute(MATRIX_VARIABLES_ATTRIBUTE, result.getMatrixVariables());
  }
}

3.2 解析@MatrixVariable注解的参数

public class MatrixVariableMethodArgumentResolver {
  protected Object resolveName(...) throws Exception {
    // 从request中取出上一步存入的map集合
    Map> pathParameters = (Map>)
        request.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
    MatrixVariable ann = parameter.getParameterAnnotation(MatrixVariable.class);
    // 获取注解配置的pathVar值
    String pathVar = ann.pathVar();
    if (!pathVar.equals(ValueConstants.DEFAULT_NONE)) {
      if (pathParameters.containsKey(pathVar)) {
        // 取出值
        paramValues = pathParameters.get(pathVar).get(name);
      }
    }
    // 返回数据
    return paramValues.get(0);
  }
}

以上本篇文章的全部内容,希望对你有所帮助。

完毕!!!

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...