在前面我们搭建了基本的Spring Web MVC环境,并配置了一个控制器。下面我们来详细学习一下控制器。控制器的主要作用就是处理特定URL发过来的HTTP请求,然后进行业务逻辑处理,将结果返回给某个特定的视图。
处理请求
我们在前面定义了如下一个控制器。在Spring中定义控制器非常简单,新建一个类然后应用@Controller注解即可,当然一般习惯上将控制器类也命名为XXController。每个控制器可以有若干方法,分别处理不同的请求。要指定处理请求的URL,使用@RequestMapping注解。控制器方法处理之后,返回一个字符串,指定要使用的视图名称,然后该名称交给视图解析器转换成真正的视图,然后返回给客户端。@RequestMapping还可以注解到控制器类上,这样一来每个方法处理的URL就是控制器和方法上URL的组合。
@Controller
public class MainController {
@RequestMapping("/hello")
public String hello(@RequestParam(defaultValue = "苟") String name, Model model) {
model.addAttribute("name", name);
return "hello";
}
@RequestMapping("/index")
public String index() {
return "index";
}
}
默认情况下@RequestMapping会处理所有请求,如果希望只处理GET或者POST等请求,可以使用@RequestMapping的method属性。
@RequestMapping(value = "/index", method = {RequestMethod.GET})
public String index() {
return "index";
}
当然也可以直接使用Spring定义的几个Mapping注解,包括了GET、POST、DELETE、PUT等。需要注意这几个注解只能应用于方法上。
@GetMapping(value = "/index")
public String index() {
return "index";
}
路径参数
细心的同学可能会发现有些网站的URL很特别,类似http://mysite.com/list/yitian
这样的。Spring也支持这样的路径参数。这时候路径模式中相应部分需要用花括号括起来,然后在方法中使用@PathVariable注解(注解中的名称需要和花括号中的参数相同)。这样对应的路径参数就会由Spring自动赋给方法中的参数,我们直接在方法中使用即可。
@RequestMapping("/hello/{name}")
public String hey(@PathVariable("name") String username, Model model) {
model.addAttribute("name", username);
return "hello";
}
如果方法参数和路径中花括号部分相同,那么@PathVariable中的名称可以省略。
@RequestMapping("/hello/{name}")
public String hey(@PathVariable String name, Model model) {
model.addAttribute("name", name);
return "hello";
}
另外,方法中可以有多个路径参数。而且路径参数并不一定只能是字符串,也可以是int
、long
、Date
这样的简单类型,Spring会自动进行转换,如果转换失败,就会抛出TypeMismatchException
。
正则表达式匹配
有时候可能需要匹配一个比较复杂的路径,这时候可以使用正则表达式,语法是{varName:regex}
。例如为了匹配"/spring-web/spring-web-3.0.5.jar"
,我们需要这样一个方法。
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String extension) {
// ...
}
另外路径模式中还支持通配符,例如/myPath/*.do
。
最后一个问题就是这些路径优先级的问题。如果一个请求匹配了多个路径模式,那么最具体的那个会被使用。规则如下:
- 路径中路径参数和通配符越少,路径越具体。
- 路径参数和通配符个数相同的话,路径越长越具体。
- 个数和长度都相同的话,通配符个数越少路径越具体。
- 默认匹配
/**
优先级最低。 - 前缀模式例如
/public/**
比其他两个通配符的模式优先级更低。
矩阵变量Matrix Variables
RFC 3986定义了可以在路径中添加键值对,这样的键值对叫做矩阵变量。Spring默认没有启用矩阵变量。要启用它,在dispatcher-servlet.xml
中添加或修改如下一行。
<mvc:annotation-driven enable-matrix-variables="true"/>
矩阵变量可以用在路径的任何部分,需要和路径之间使用分号;
分隔开,每个矩阵变量之间也是用分号分隔。如果一个矩阵变量有多个值,使用逗号,
分隔,例如"/matrix/42;colors=red,blue,yellow;year=2012"
。
对应的控制器方法如下。
// 处理请求 /matrix/42;colors=red,blue,yellow;year=2012
@RequestMapping("/matrix/{count}")
public String matrix(@PathVariable int count, @MatrixVariable String[] colors, @MatrixVariable int year,