Spring MVC 映射请求

作者:範宗雲 来源:原创 发布时间:2015-03-21 归档:springmvc

开发环境 : JDK 7 Maven 3 Tomcat 7 Spring 4.1.5 Eclipse Luna
@RequestMapping
@RequestMapping 注解用于将请求映射到控制器的某个具体的处理方法上。它可以标注在方法级别上, 也可以标注在类级别上, 标注在类级别上不是必须的。
示例代码片段 1
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(method = GET)
				public String list() {
					return "class-level-mapping/list";
				}
				
				@RequestMapping(value = "/pathname", method = GET)
				public String mappedByPathname(Model model) {
					model.addAttribute("message", "mapped by /pathname");
					return "class-level-mapping/result";
				}
				
			}
			
@RequestMapping.value
value 用于映射请求的 url 表达式, 以缩小映射的范围。
参数类型 String[], 如 value = "/pathname", value = {"/", "/pathname"} ( 多个值时, 访问任意一个都是等效, 如 / 和 /pathname )
当注解只有一个参数 value 时, value 可以省略。
@RequestMapping("/class-level-mapping") 完整的写法是 @RequestMapping(value = "/class-level-mapping")。
@RequestMapping.method
method 用于映射请求的 HTTP Request Method 类型, 以缩小映射的范围。
参数类型 RequestMethod[], 如 method = GET, method = {GET, POST}
若缺省, 默认是映射所有的 HTTP Request Methods 类型 ( GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE )。
@RequestMapping 注解标注在类级别上, 表明当前控制器的处理方法映射的路径均相对于 /class-level-mapping。
GET /class-level-mapping --> list
GET /class-level-mapping/pathname --> mappedByPathname
示例代码片段 2
		    @Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
				
				@RequestMapping(value = "/parameter", method = GET, params = "param")
				public String mappedByParameter(Model model, String param) {
					model.addAttribute("message", "the param is " + param);
					return "class-level-mapping/result";
				}
				
				@RequestMapping(value = "/parameter", method = GET, params = "!param")
				public String mappedByParameterNegation(Model model) {
					model.addAttribute("message", "mapped by /parameter, not supposed param");
					return "class-level-mapping/result";
				}
				
				@RequestMapping(value = "/argument", method = GET, params = "param=1")
				public String mappedByParameterEquals(Model model) {
					model.addAttribute("message", "mapped by /argument, only param = 1");
					return "class-level-mapping/result";
				}
				
				@RequestMapping(value = "/argument", method = GET, params = "param!=1")
				public String mappedByParameterNotEquals(Model model) {
					model.addAttribute("message", "mapped by /argument, only param != 1");
					return "class-level-mapping/result";
				}
				
			}
		    
@RequestMapping.params
params 用于映射请求的参数, 以缩小映射的范围。
参数类型 String[], 如 params = "param", params = "!param", params = "param=1", params = "param!=1", params = {"p1", "p2"}
params = "param", 表明处理方法只处理 url 中含 param 参数的请求。
params = "!param", 表明处理方法只处理 url 中不含 param 参数的请求。
params = "param=1", 表明处理方法只处理 url 中含 param=1 参数的请求。
params = "param!=1", 表明处理方法只处理 url 中不含 param=1 参数的请求。
GET /class-level-mapping/parameter --> mappedByParameterNegation
GET /class-level-mapping/parameter?p=s --> mappedByParameterNegation
GET /class-level-mapping/parameter?param --> mappedByParameter
GET /class-level-mapping/parameter?param=s --> mappedByParameter
GET /class-level-mapping/argument --> mappedByParameterNotEquals
GET /class-level-mapping/argument?param=1 --> mappedByParameterEquals
GET /class-level-mapping/argument?param=2 --> mappedByParameterNotEquals
示例代码片段 3
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(value = "/header", method = POST, headers = "content-type=application/*")
				public String mappedByHeader(Model model) {
					model.addAttribute("message", "mapped by /header + presence of header");
					return "class-level-mapping/result";
				}
				
				@RequestMapping(value = "/header", headers = "!content-type")
				public String mappedByHeaderNegation(Model model) {
					model.addAttribute("message", "mapped by /header + absence of header");
					return "class-level-mapping/result";
				}
				
			}
			
@RequestMapping.headers
headers 用于映射请求的 Request Headers 内容, 以缩小映射的范围。
参数类型 String[], 如 headers = "content-type=text/html", headers = "!content-type", headers = "content-type!=text/*"
GET  /class-level-mapping/header --> mappedByHeaderNegation
POST /class-level-mapping/header --> mappedByHeader
示例代码片段 4
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(value = "/produce", method = GET, produces = "application/json")
				public @ResponseBody Person mappedByProduce() {
					return new Person(1001, "Lychie Fan");
				}
				
				public static class Person {
		
					private int id;
					private String name;
					
					public Person() {
						
					}
					
					public Person(int id, String name) {
						this.id = id;
						this.name = name;
					}
			
					// ignore getters and setters
			
					@Override
					public String toString() {
						return "[ id : " + id + ", name : " + name + " ]";
					}
					
				}
				
			}
			
@RequestMapping.produces ( 生产者 )
produces 表明处理方法产生的媒体类型, 再由请求的 Request Headers 中的 Accept 来进行匹配, 以缩小映射的范围。
参数类型 String[], 如 produces = MediaType.APPLICATION_JSON_VALUE, produces = {"text/plain", "application/*"}
produces = "application/*", 若 Request Headers 中的 Accept 含 application/xml, application/json 等都可匹配。
@ResponseBody
表明处理方法的返回值绑定到 Response Body。使用时将跳过视图解析部分, 返回如 json, xml 等格式的数据。
引入依赖
		    <dependency>
		      <groupId>com.fasterxml.jackson.core</groupId>
		      <artifactId>jackson-databind</artifactId>
		      <version>2.4.1</version>
		    </dependency>
		    
GET /class-level-mapping/produce --> mappedByProduce --> {"id":1001,"name":"Lychie Fan"}
示例代码片段 5
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(value = "/consume", method = POST, consumes = "application/json")
				public String mappedByConsume(@RequestBody Person person) {
					System.out.println("person = " + person);
					return "class-level-mapping/result";
				}
				
			}
			
@RequestMapping.consumes ( 消费者 )
consumes 表明处理方法消费的媒体类型, 由请求的 Request Headers 中的 Content-Type 来进行匹配类型, 以缩小映射的范围。
参数类型 String[], 如 consumes = "application/*", consumes = {"text/plain", "application/*"}
@RequestBody
表明处理方法的参数是绑定到 Request Body。使用时从 Request Body 中读取绑定的数据。
		    <body>
			  <h3>
			    <p><a href="javascript:;" class="consume">class-level-mapping/consume</a></p>
			  </h3>
			  <textarea style="display:none">{"id":1001,"name":"Lychie Fan"}</textarea>
			  <script type="text/javascript">
			    $(function(){
			  	  $(".consume").click(function(){
			  		  $.ajax({
			  			  type : "post",
			  			  url : "class-level-mapping/consume",
			  			  data : $("textarea").val(),
			  			  contentType : "application/json",
			  			  success : function(){
			  				  alert("well, now you can see the execution result on the console");
			  			  }
			  		  });
			  	  });
			    });
			  </script>
			</body>
		    
POST /class-level-mapping/consume --> mappedByConsume --> person = [ id : 1001, name : Lychie Fan ]
示例代码片段 6
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(value = "/foo/{bar}", method = GET)
				public String mappedByUriTemplate(Model model, @PathVariable String bar){
					model.addAttribute("message", bar);
					return "class-level-mapping/result";
				}
				
				@RequestMapping(value = "/food/{name}/{kind}", method = GET)
				public String mappedByUriTemplate(Model model, @PathVariable("name") String foodName, @PathVariable String kind) {
					model.addAttribute("message", foodName + ", " + kind);
					return "class-level-mapping/result";
				}
				
			}
			
@PathVariable
{bar} 是变量的写法, /foo/{bar} 是一个 URI 模板, bar 部分是可变的, @PathVariable 注解用于将处理方法的参数绑定到这个 URI 模板中。
如请求 /foo/foobar, 处理方法 mappedByUriTemplate 执行时, foobar 将作为处理方法参数 bar 的值被设置进去。
若处理方法的参数绑定的变量与模板中的变量名不一致, 则需要在处理方法中显式的指明参数绑定的是模板中的哪个变量, 如上述代码所示。
GET /class-level-mapping/foo/foobar --> mappedByUriTemplate(Model, String) --> foobar
GET /class-level-mapping/food/fruit/banana --> mappedByUriTemplate(Model, String, String) --> fruit, banana
示例代码片段 7
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(value = "/{filename:[a-z-_]+}{extension:\\.[a-z]+}", method = GET)
				public String mappedByRegular(Model model, @PathVariable String filename, @PathVariable String extension) {
					model.addAttribute("message", filename + extension);
					return "class-level-mapping/result";
				}
				
			}
			
正则表达式的运用
{filename:[a-z-_]+} 其中, filename 是变量名, [a-z-_]+ 是正则表达式的值。
GET /class-level-mapping/spring-mvc-mapping.zip --> mappedByRegular --> spring-mvc-mapping.zip
示例代码片段 8
			@Controller
			@RequestMapping("/class-level-mapping")
			public class ClassLevelMappingController {
			
				@RequestMapping(value = "/pathname", method = GET)
				public String mappedByPathname(Model model) {
					model.addAttribute("message", "mapped by /pathname");
					return "class-level-mapping/result";
				}
			
				@RequestMapping(value = "/pathname/*", method = GET)
				public String mappedByPathnamePattern(Model model) {
					model.addAttribute("message", "mapped by /pathname/*");
					return "class-level-mapping/result";
				}
			
				@RequestMapping(value = "/pathname/*.html", method = GET)
				public String mappedByPathnameExtension(Model model) {
					model.addAttribute("message", "mapped by /pathname/*.html");
					return "class-level-mapping/result";
				}
				
			}
			
/pathname/* 模式, * 匹配 0 个至多个字符, 不含路径符。
GET /class-level-mapping/pathname --> mappedByPathname
GET /class-level-mapping/pathname/public --> mappedByPathnamePattern
GET /class-level-mapping/pathname/sample.html --> mappedByPathnameExtension

示例代码下载
spring-mvc-mapping.zip