第三章 控制器的实现(二)

矩阵变量

URI规范RFC 3986定义了可以在路径块中使用键值对。我们把它称为“Matrix URIs”。在Spring MVC中,则称作矩阵变量。矩阵变量可以出现在任何一个路径块中,每个矩阵变量之间以分号分隔。比如,“/cars;color=red;year=2012”,变量如果有多个值的话则以逗号分隔,如“color=red,green,blue”或重复变量名-值对,如“color=red;color=green;color=blue”。

如果一个URL需要包含矩阵变量,请求映射的模式需要以URI模板的形式表示。这样是为了确保无论是否存在矩阵变量以及它们的顺序如何都可以正确地对请求进行映射。下面是一个提取矩阵变量“q”的示例:

// GET /pets/42;q=11;r=22

@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET)

public void findPet(@PathVariable String petId, @MatrixVariable int q) {

    // petId == 42

    // q == 11

}

因为有可能多个路径块都会包含矩阵变量,在某些情况下我们还需要更明确地指明该矩阵变量是附属于哪个URI模板变量上,比如下面的例子:

// GET /owners/42;q=11/pets/21;q=22

@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)

public void findPet(

        @MatrixVariable(value="q", pathVar="ownerId") int q1,

        @MatrixVariable(value="q", pathVar="petId") int q2) {

    // q1 == 11

    // q2 == 22

}

有时矩阵变量也可能是可选的,因此需要一个默认值,我们就可以像下面的例子这样:

// GET /pets/42

@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET)

public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) {

    // q == 1

}

我们也可以通过一个Map来获取到矩阵变量的值,如下面的例子所示:

// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)

public void findPet(

        @MatrixVariable Map<String, String> matrixVars,

        @MatrixVariable(pathVar="petId"") Map<String, String> petMatrixVars) {

    // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]

    // petMatrixVars: ["q" : 11, "s" : 23]

}

需要特别注意的是,如果使用矩阵变量的话,我们需要把RequestMappingHandlerMapping Bean的属性removeSemicolonContent值设置为false才行,它的默认值为true。此外,我们还可以通过在配置文件中使用“mvc”命名空间来进行设置,这是通过把<mvc:annotation-driven>元素的enable-matrix-variables属性值设置为true来实现的,默认地,它的值为false。例子如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:mvc="http://www.springframework.org/schema/mvc"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="

        http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/mvc

        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

 

    <mvc:annotation-driven enable-matrix-variables="true"/>

</beans>

 

可接收的客户端请求媒介类型

控制器处理方法对客户端请求的过滤还可以通过指定可接收的媒介类型来进行。只有请求头中的Content-Type字段匹配了指定的媒介类型,才会映射到相应的处理方法上,比如下面的例子:

@Controller

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")

public void addPet(@RequestBody Pet pet, Model model) {

    // implementation omitted

}

媒介类型的值还可以通过“!”非操作符来做取反操作,比如“!text/plain”就表示该处理器方法可接收所有Content-Type的值不为“text/plain”的请求。对媒介类型的指定在类层面和方法层面均可以使用。不同于其他条件的设定,当用在类层面上时,如果方法上也指定了则会覆盖类层面的值而不是继承下来。

 

可输出的响应媒介类型

与可接收的请求媒介类型类似,我们也可以指定可输出的响应媒介类型。这是通过匹配请求头中的Accept字段的值来实现的。而且,指定了响应媒介类型的话,框架会根据该媒介类型来生成相应的响应内容类型。比如下面的例子:

@Controller

@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")

@ResponseBody

public Pet getPet(@PathVariable String petId, Model model) {

    // implementation omitted

}

getPet方法的返回值Pet对象将会以json的形式响应给客户端。

关于“!”操作符的使用以及方法覆盖类层面指定的值与上面的相同,不再赘述。



指定请求参数和请求头

我们还可以通过指定具体的请求参数和请求头的值来过滤请求,比如"myParam""!myParam""myParam=myValue"等形式。前面两个是检测该名称的请求参数是否存在,而第3个则是检测该名称的请求参数值是否与指定的值相同。下面为一个示例:

@Controller

@RequestMapping("/owners/{ownerId}")

public class RelativePathUriTemplateController {

    @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")

    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {

        // implementation omitted

    }

}

同样地,也可以检测请求头中的某个字段是否存在以及值是否匹配,示例如下:

@Controller

@RequestMapping("/owners/{ownerId}")

public class RelativePathUriTemplateController {

    @RequestMapping(value = "/pets", method = RequestMethod.GET, headers="myHeader=myValue")

    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {

        // implementation omitted

    }

}

尽管我们可以使用模糊匹配来指定Content-TypeAccept字段的值,比如“content-type=text/*”将会匹配“text/plain”和“text/html”两种请求,但不建议这样使用。在媒介类型上,我们应该分别使用consumesproduces条件进行明确地指明。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值