A Quick Guide to Spring MVC Matrix Variables – Spring MVC矩阵变量的快速指南

最后修改: 2016年 6月 15日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

The URI specification RFC 3986 defined URI path parameters as name-value pairs. Matrix variables is a Spring coined term and an alternative implementation for passing and parsing URI path parameters.

URI规范RFC 3986将URI路径参数定义为名-值对。矩阵变量是Spring创造的一个术语,是传递和解析URI路径参数的另一种实现方式。

Matrix variables support became available in Spring MVC 3.2 and is meant to simplify requests with a large number of parameters.

矩阵变量支持在Spring MVC 3.2中可用,目的是为了简化有大量参数的请求

In this article, we will show how we can simplify complex GET requests that use either variable or optional path parameters inside the different path segments of a URI.

在这篇文章中,我们将展示如何简化复杂的GET请求,这些请求在URI的不同路径段中使用可变或可选的路径参数。

2. Configuration

2.配置

To enable Spring MVC Matrix Variables, let’s start with the configuration:

要启用Spring MVC矩阵变量,让我们从配置开始。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

Otherwise, they’re disabled by default.

否则,它们将被默认禁用。

3. How to Use Matrix Variables

3.如何使用矩阵变量

These variables can appear in any part of the path, and the character equals (“=”) is used for giving values and the semicolon(‘;’) for delimiting each matrix variable. On the same path, we can also repeat the same variable name or separate different values using the character comma(‘,’).

这些变量可以出现在路径的任何部分,用字符equals(“=”)来给出数值,用分号(‘;’)来限定每个矩阵变量。在同一路径上,我们还可以重复相同的变量名称,或者用字符逗号(‘,’)分隔不同的值。

Our example has a controller that provides information about the employees. Each employee has a working area, and we can search by that attribute. The following request could be used for searching:

我们的例子有一个控制器,提供关于雇员的信息。每个员工都有一个工作区域,我们可以通过该属性进行搜索。以下请求可用于搜索。

http://localhost:8080/spring-mvc-java-2/employeeArea/workingArea=rh,informatics,admin

or like this:

或像这样。

http://localhost:8080/spring-mvc-java-2
  /employeeArea/workingArea=rh;workingArea=informatics;workingArea=admin

When we want to refer to these variables in Spring MVC, we should use the annotation @MatrixVariable.

当我们想在Spring MVC中引用这些变量时,我们应该使用注解@MatrixVariable

In our examples, we will use the Employee class:

在我们的例子中,我们将使用Employee类。

public class Employee {

    private long id;
    private String name;
    private String contactNumber;

    // standard setters and getters 
}

And also the Company class:

还有Company类。

public class Company {

    private long id;
    private String name;

    // standard setters and getters
}

These two classes will bind the request parameters.

这两个类将绑定请求参数。

4. Defining Matrix Variable Properties

4.定义矩阵变量属性

We can specify required or default properties for the variable. In the following example, the contactNumber is required, so it must be included in our path, something like this:

我们可以为变量指定必要或默认的属性。在下面的例子中,contactNumber是必需的,所以它必须包含在我们的路径中,像这样。

http://localhost:8080/spring-mvc-java-2/employeesContacts/contactNumber=223334411

The request will be handled by the following method:

该请求将由以下方法处理。

@RequestMapping(value = "/employeesContacts/{contactNumber}", 
  method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<List<Employee>> getEmployeeByContactNumber(
  @MatrixVariable(required = true) String contactNumber) {
    List<Employee> employeesList = new ArrayList<Employee>();
    ...
    return new ResponseEntity<List<Employee>>(employeesList, HttpStatus.OK);
}

As a result, we will get all the employees who have the contact number 223334411.

因此,我们将得到所有拥有联系号码223334411的雇员。

5. Complement Parameter

5.补足参数

Matrix variables can complement path variables.

矩阵变量可以补充路径变量。

For example, we are searching an employee for his/her name, but we can also include the starting numbers of his/her contact number.

例如,我们在搜索一个雇员的名字,但我们也可以包括他/她的联系电话的起始号码。

The request for this search should be like this:

这个搜索的请求应该是这样的。

http://localhost:8080/spring-mvc-java-2/employees/John;beginContactNumber=22001

The request will be handled by the following method:

该请求将由以下方法处理。

@RequestMapping(value = "/employees/{name}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<List<Employee>> getEmployeeByNameAndBeginContactNumber(
  @PathVariable String name, @MatrixVariable String beginContactNumber) {
    List<Employee> employeesList = new ArrayList<Employee>();
    ...
    return new ResponseEntity<>(employeesList, HttpStatus.OK);
}

As a result, we will get all the employees who have the contact number 22001 or whose name is John.

结果,我们将得到所有联系号码为22001或姓名为John的雇员。

6. Binding All Matrix Variables

6.绑定所有矩阵变量

If for some reason, we want to get all the variables that are available on the path, we can bind them to a Map:

如果出于某种原因,我们想获得路径上的所有变量,我们可以将它们绑定到一个Map

http://localhost:8080/spring-mvc-java-2/employeeData/id=1;name=John;contactNumber=2200112334

This request will be handled by the following method:

这一请求将由以下方法处理。

@GetMapping("employeeData/{employee}")
@ResponseBody
public ResponseEntity<Map<String, String>> getEmployeeData(
  @MatrixVariable Map<String, String> matrixVars) {
    return new ResponseEntity<>(matrixVars, HttpStatus.OK);
}

Of course, we can restrict binding to the matrix variables of a specific part of the path. For example, if we have a request like this:

当然,我们可以限制对路径中特定部分的矩阵变量的绑定。例如,如果我们有一个这样的请求。

http://localhost:8080/spring-mvc-java-2/
  companyEmployee/id=2;name=Xpto/employeeData/id=1;name=John;
  contactNumber=2200112334

And we only want to get all the variables that belong to employeeData; then we should use as an input parameter this:

而我们只想获得属于employeeData的所有变量;那么我们应该使用这个作为输入参数。

@RequestMapping(
 value = "/companyEmployee/{company}/employeeData/{employee}",
 method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Map<String, String>> getEmployeeDataFromCompany(
  @MatrixVariable(pathVar = "employee") Map<String, String> matrixVars) {
  ...
}

7. Partial Binding

7.部分约束力

Apart from simplicity, flexibility is another gain, matrix variables can be used in a variety of different ways. For example, we can get each variable from each path segment. Consider the following request:

除了简单之外,灵活性是另一个好处,矩阵变量可以以各种不同的方式使用。例如,我们可以从每个路径段获得每个变量。考虑下面的请求。

http://localhost:8080/spring-mvc-java-2/
  companyData/id=2;name=Xpto/employeeData/id=1;name=John;
  contactNumber=2200112334

If we only want to know the matrix variable name of the companyData segment, then, we should use as an input parameter the following:

如果我们只想知道companyData段的矩阵变量name,那么,我们应该使用以下内容作为输入参数。

@MatrixVariable(value="name", pathVar="company") String name

8. Firewall Setup

8.防火墙设置

If the application uses Spring Security, then StrictHttpFirewall is used by default. This blocks requests that appear to be malicious, including Matrix Variables with semicolon separator.

如果应用程序使用Spring Security,那么StrictHttpFirewall被默认为使用。这将阻止那些看起来是恶意的请求,包括带有分号分隔符的矩阵变量。

We can customize this implementation in application configuration and allow such variables whilst rejecting other possibly malicious requests.

我们可以在应用程序配置中自定义,允许此类变量同时拒绝其他可能是恶意的请求。

However, this way, we can open the application to attacks. Therefore, we should only implement this after careful analysis of the application and security requirements.

然而,这样一来,我们可能会使应用程序受到攻击。因此,我们应该在仔细分析了应用程序和安全要求之后才实施。

9. Conclusion

9.结论

This article illustrated some of the various ways that matrix variables can be used.

这篇文章说明了矩阵变量的一些不同使用方式。

It’s essential to understand how this new tool can deal with requests that are too complex or help us add more parameters to delimit our search.

了解这个新工具如何处理过于复杂的请求,或帮助我们添加更多的参数来限定我们的搜索,这一点至关重要。

The implementation of all these examples and code snippets can be found in a GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

所有这些例子和代码片段的实现都可以在一个GitHub项目中找到–这是一个基于Maven的项目,所以应该很容易导入并按原样运行。