源码地址
三、@RequestMapping注解 3.1)@RequestMapping注解的功能从注解名称上可以看到,@RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来建立映射关系;SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。
如上述步骤建立工程 SpringMvcDemo2,新建 TestController.java
@Controller
public class TestController {
@RequestMapping("/")
public String index() {
return "index";
}
}
新建 RequestMappingController.java
public class RequestMappingController {
@RequestMapping("/")
public String index() {
return "index";
}
}
启动工程报错:【保证在所有控制器中@RequestMapping对于的路径是唯一的,否则SpringMVC 不知道该匹配哪一个路径报错】
3.2)@RequestMapping注解的位置12:47:53.487 [http-nio-8080-exec-3] WARN org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'testController' method com.study.mvc.controller.TestController#index() to { [/]}: There is already 'requestMappingController' bean method com.study.mvc.controller.RequestMappingController#index() mapped. 12:47:53.489 [http-nio-8080-exec-3] ERROR org.springframework.web.servlet.DispatcherServlet - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'testController' method com.study.mvc.controller.TestController#index() to { [/]}: There is already 'requestMappingController' bean method com.study.mvc.controller.RequestMappingController#index() mapped.
@RequestMapping注解源码如下:
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
@org.springframework.web.bind.annotation.Mapping
public @interface RequestMapping {
...
}
以下代码说明可以@RequestMapping可以标识类和方法
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
-
@RequestMapping标识一个类:设置映射请求的请求路径的初始信息
-
@RequestMapping标识一个方法:设置映射请求请求路径的具体信息
代码示例:
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping("/testRequestMapping")
public String success(){
return "success";
}
}
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击超链接,页面跳转至http://localhost:8080/SpringMvcDemo2/hello/testRequestMapping ,页面如下:
通过在类上设置@RequestMapping,就可以在不同的控制器(模块)上使用相同的路径了
3.3)@RequestMapping注解的value属性-
@RequestMapping注解的value属性通过请求的请求地址匹配请求映射;
-
@RequestMapping注解的value属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求;
-
@RequestMapping注解的value属性必须设置,至少通过请求地址匹配请求映射
代码示例:
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping(value = {"/testRequestMapping", "/test"})
public String success(){
return "success";
}
}
index.html 如下:
Title 首页 测试RequestMapping注解的位置
测试RequestMapping注解的value属性-->/testRequestMapping
测试RequestMapping注解的value属性-->/test
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击超链接2,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/testRequestMapping ,页面如下:
点击超链接3,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/test,页面如下:
3.4)@RequestMapping注解的method属性-
@RequestMapping注解的method属性通过请求的请求方式(get或post)匹配请求映射【默认get】;
POST与GET两种请求方式的区别
1、GET请求:请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接;
POST请求:POST请求会把请求的数据放置在HTTP请求的body体中;
因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。
2、传输数据的大小
在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET请求,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制;
对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。
3、安全性
POST的安全性比GET的高,但传输速度比GET的慢,且文件上传不能使用GET,只能使用POST。
-
@RequestMapping注解的method属性是一个RequestMethod类型的数组,表示该请求映射能够匹配多种请求方式的请求;
-
若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报错405:Request method 'POST' not supported
代码示例:
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping(value = {"/testRequestMapping", "/test"},
method = {RequestMethod.GET}
)
public String success(){
return "success";
}
}
index.html 如下:
Title 首页 1)测试RequestMapping注解的位置
2)测试RequestMapping注解的value属性-->/testRequestMapping
3)测试RequestMapping注解的value属性-->/test
4)测试RequestMapping注解的method属性-->GET
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击链接4,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/test,页面如下:
点击链接5,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/test,页面如下:【代码只能匹配GET】
修改代码,添加 method属性,
@RequestMapping(value = {"/testRequestMapping", "/test"},
method = {RequestMethod.GET, RequestMethod.POST}
)
public String success(){
return "success";
}
点击链接5,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/test,页面如下:
3.4.1)派生注解
对于处理指定请求方式的控制器方法,SpringMVC中提供了@RequestMapping的派生注解,如下:
处理get请求的映射-->@GetMapping
处理post请求的映射-->@PostMapping
处理put请求的映射-->@PutMapping
处理delete请求的映射-->@DeleteMapping
以 GetMapping为例,代码如下:【即method = {RequestMethod.GET},无需再配置method 属性】
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@GetMapping("/testGetMapping")
public String testGetMapping() {
return "success";
}
}
index.html 如下:
6)测试GetMapping注解-->/testGetMapping
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击链接6,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/testGetMapping,页面如下:
3.4.2)常用的请求方式
上述的method属性对应的枚举值如下:
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
常用的请求方式有:post【增】,delete【删】,put【改】,get【查】
但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符串(put或delete),则按照默认的请求方式get处理;若要发送put和delete请求,则需要通过spring提供的过滤器HiddenHttpMethodFilte;
以 form表单为例,代码如下:【设置method为put,查看 form表单】
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping(value = "/testPut", method = RequestMethod.PUT)
public String testPut() {
return "success";
}
}
index.html 如下:
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击链接7,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/testPut?,页面如下:【不支持PUT方法,按照默认的请求方式get处理】
3.5)@RequestMapping注解的params属性(了解)
@RequestMapping注解的params属性通过请求的请求参数匹配请求映射;
@RequestMapping注解的params属性是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系:
-
"param":要求请求映射所匹配的请求必须携带param请求参数;
-
"!param":要求请求映射所匹配的请求必须不能携带param请求参数;
-
"param=value":要求请求映射所匹配的请求必须携带param请求参数且param=value;
-
"param!=value":要求请求映射所匹配的请求必须携带param请求参数但是param!=value
代码示例:
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping(value = "/testParamsAndHeaders",
params = {"username"}
)
public String testParamsAndHeaders() {
return "success";
}
}
index.html 如下:
8)测试RequestMapping注解的params属性-->/testParamsAndHeaders
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击链接8,页面跳转至 http://localhost:8080/SpringMvcDemo2/hello/testParamsAndHeaders,页面如下:【请求链接中不包含username,所以报错】
修改index.html 如下:
8)测试RequestMapping注解的params属性-->/testParamsAndHeaders
再次点击链接8,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/testParamsAndHeaders?username=admin,页面如下:
params属性是一个字符串类型的数组,支持多个参数,修改代码:
@RequestMapping(value = "/testParamsAndHeaders",
params = {"username","password!=123456"}
)
public String testParamsAndHeaders() {
return "success";
}
修改index.html 如下:
8)测试RequestMapping注解的params属性-->/testParamsAndHeaders
再次点击链接8,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/testParamsAndHeaders?username=admin&password=123,页面如下:
3.6)@RequestMapping注解的headers属性(了解)
@RequestMapping注解的headers属性通过请求的请求头信息匹配请求映射;
@RequestMapping注解的headers属性是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系
-
"header":要求请求映射所匹配的请求必须携带header请求头信息
-
"!header":要求请求映射所匹配的请求必须不能携带header请求头信息
-
"header=value":要求请求映射所匹配的请求必须携带header请求头信息且header=value
-
"header!=value":要求请求映射所匹配的请求必须携带header请求头信息且header!=value
若当前请求满足@RequestMapping注解的value和method属性,但是不满足headers属性,此时页面显示404错误,即资源未找到;
修改代码:【当前配置端口为8080】
@RequestMapping(value = "/testParamsAndHeaders",
params = {"username", "password!=123456"},
headers = {"Host=localhost:8081"}
)
public String testParamsAndHeaders() {
return "success";
}
输出:再次点击链接8,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/testParamsAndHeaders?username=admin&password=123,页面如下:【8081端口与当前配置端口8080不一致】
修改代码:【将当前端口修改为与配置端口一致的8080】
@RequestMapping(value = "/testParamsAndHeaders",
params = {"username", "password!=123456"},
headers = {"Host=localhost:8080"}
)
public String testParamsAndHeaders() {
return "success";
}
输出:再次点击链接8,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/testParamsAndHeaders?username=admin&password=123,页面如下:【与当前配置端口8080一致】
3.7)SpringMVC支持ant风格的路径
SpringMVC支持模糊匹配,如下:
-
?:表示任意的单个字符
-
*:表示任意的0个或多个字符
-
**:表示任意的一层或多层目录
注意:在使用**时,只能使用xxx的方式
代码示例:【?:表示任意的单个字符】
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping("/a?a/testAnt")
public String testAnt(){
return "success";
}
}
修改index.html 如下:
9)测试@RequestMapping可以匹配ant风格的路径-->使用?
10)测试@RequestMapping可以匹配ant风格的路径-->使用*
11)测试@RequestMapping可以匹配ant风格的路径-->使用**
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击链接9,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/a1a/testAnt,页面如下:
修改为:http://localhost:8080/SpringMvcDemo2/hello/a11a/testAn,页面如下:【因为/a?a/testAnt说明中间只能有一个字符】
修改代码示例:【*:表示任意的0个或多个字符】
@RequestMapping("/a*a/testAnt")
public String testAnt(){
return "success";
}
点击链接10,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/a11a/testAnt,页面如下:
修改代码示例:【**:表示任意的一层或多层目录】
@RequestMapping("testAnt")
public String testAnt() {
return "success";
}
点击链接11,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/a1a/a1a/testAnt,页面如下:
3.8)SpringMVC支持路径中的占位符(重点)
原始方式:/deleteUser?id=1
rest方式:/deleteUser/1
SpringMVC路径中的占位符常用于RESTful风格中,当请求路径中将某些数据通过路径的方式传输到服务器中,就可以在相应的@RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据,在通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参。
代码示例:占位符【@PathVariable注解将占位符所表示的数据赋值给控制器方法的形参】
@Controller
@RequestMapping("/hello")
public class RequestMappingController {
@RequestMapping("/testPath/{id}/{username}")
public String testPath(@PathVariable("id")Integer id, @PathVariable("username") String username){
System.out.println("id:"+id+",username:"+username);
return "success";
}
}
修改index.html 如下:
12)测试@RequestMapping支持路径中的占位符-->/testPath
输出:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo2/ 】页面如下:
点击链接12,页面跳转至:http://localhost:8080/SpringMvcDemo2/hello/testPath/1/admin,页面如下:



