个人建议重新练习一遍搭建的过程,如果感觉麻烦你可以直接复制上一个工程,但是需要修改pom.xml中的一点信息
<groupId>com.hanpang.springmvc</groupId> <artifactId>springmvc-demo02</artifactId> <version>0.0.1-SNAPSHOT</version>
我们可以使用@RequestMapping标注来将请求URL(类似于@WebServlet),如/hanpang等,映射到 整个类上 或 某个特定的处理器方法 上。
一般来说,类级别的标注负责将一个 特定 (或符合某种模式)的请求路径映射到一个控制器上,同时通过方法级别的标注来 细化 映射,即根据特定的HTTP请求方法(“GET”和“POST”方法等)、HTTP请求中是否携带特定参数等条件,将请求映射到匹配的方法上。
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/sys") public class Demo01Controller { //映射默认的路径 public ModelAndView test01() { System.out.println("该方法是访问sys执行"); return null; } //----------------细化--------------------// //映射一个路径 @RequestMapping(value="/user01") public ModelAndView test02() { System.out.println("/user01 path和value属性一样"); return null; } //映射一个路径 @RequestMapping(path="/user02") public ModelAndView test03() { System.out.println("/user02 path和value属性一样"); return null; } //简写方式 @RequestMapping("/user03") public ModelAndView test04() { System.out.println("/user03 当只有path或者value属性的时候,可以使用简写方式"); return null; } //多个映射路径执行一个方法 @RequestMapping(value= {"/user04","/user05"}) public ModelAndView test05() { System.out.println("设置多个映射路径"); return null; } //简写方式 @RequestMapping({"/user06","/user07"}) public ModelAndView test06() { System.out.println("设置多个映射路径"); return null; } }
阅读一下,我们简单了解一下规则就行,主要介绍一下通配符"*"的演示,实际开发中个人基本上没有使用过.
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/web") public class Demo02Controller { @RequestMapping("/*") public ModelAndView test01() { System.out.println("* 代表一层"); return null; } @RequestMapping("/**") public ModelAndView test02() { System.out.println("** 代表任意层次"); return null; } }
NOTE:谁描述的更加准确,就执行谁
测试路径如下:
http://127.0.0.1:8001/mvc/web/user01 执行tes01方法 http://127.0.0.1:8001/mvc/web/user02 执行tes01方法 http://127.0.0.1:8001/mvc/web/user01/user02 执行tes02方法 http://127.0.0.1:8001/mvc/web/a/b/c/d 执行tes02方法
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/web") public class Demo02Controller { @RequestMapping("/*") public ModelAndView test01() { System.out.println("* 代表一层"); return null; } @RequestMapping("/role*") public ModelAndView test02() { System.out.println("role* 的描述更准确"); return null; } @RequestMapping("/role") public ModelAndView test03() { System.out.println("role 我更准确"); return null; } }
修改之前上面的代码,我们继续测试路径
http://127.0.0.1:8001/mvc/web/user01 执行test01方法 http://127.0.0.1:8001/mvc/web/roleuser01 执行test02方法 http://127.0.0.1:8001/mvc/web/role 执行test03方法
使用通配符的方式真的很少,但是实际开发中我们经常使用URI模式,路径传递数据的方式(占位符),我们再次修改原来代码
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/web") public class Demo02Controller { @RequestMapping("/*") public ModelAndView test01() { System.out.println("* 代表一层"); return null; } @RequestMapping("/**") public ModelAndView test02() { System.out.println("** 代表一层"); return null; } @RequestMapping("/{a}") public ModelAndView test03() { System.out.println("{a} 一个占位符"); return null; } @RequestMapping("/{a}/{b}") public ModelAndView test04() { System.out.println("/{a}/{b} 多个占位符"); return null; } }
测试路径:
http://127.0.0.1:8001/mvc/web/user01 执行test03方法 http://127.0.0.1:8001/mvc/web/user01/user02 执行test04方法 http://127.0.0.1:8001/mvc/web/user01/user02//user03 执行test02方法
NOTE:发现占位符的描述性比通配符的描述更加准确
当一个URL同时匹配多个模式时,只会选择最匹配的一个:
/hotels/{hotel}/*
这个路径拥有一个URI变量和一个通配符,而 /hotels/{hotel}/**
这个路径则拥有一个URI变量和两个通配符,因此前者是更准确的路径模式。 /foo/bar*
就被认为比 /foo/*
更准确,因为前者的路径更长。 /hotels/{hotel}
就比 /hotels/*
更精确。 /**
比其他所有的模式都更" 不准确
"。比方说, /api/{a}/{b}/{c}
就比默认的通配模式 /**
要更准确 /public/**
)被认为比其他任何不包括双通配符的模式更不准确。例如, /public/path3/{a}/{b}/{c}
就比 /public/**
更准确 请重视这种模式,URI模式为获取**@RequestMapping**中指定的URL的眸一个特定部分提供很大的方便。
URI模式是一个类似于URI的字符串,只不过其中包含了 一个或多个的变量名
。当使用实际的值去填充这些变量名的时候,模式就成为一个URI。比如说,一个这个URI模式 http://127.0.0.1/mvc/shxt/{userId}
就包含了一个变量名userId。将值1001赋给这个变量名后,它就变成了一个URI: http://127.0.0.1/mvc/shxt/1001
。
在Spring MVC中可以在 方法参数
上使用 @PathVariable
标注,将其与URI模式中的参数绑定起来:
浏览器访问路径如下: http://127.0.0.1:8001/mvc/shxt/1001
package com.hanpang.web; @Controller//告知其是一个控制器 @RequestMapping("/shxt") public class Demo03Controller { @RequestMapping("/{userId}") public ModelAndView test01(@PathVariable String userId) { System.out.println("获取占位符的值:"+userId); return null; } }
会在控制台输出: 获取占位符的值:1001
URI模式" /shxt/{userId}
"定义了一个变量,名为 userId
。当控制器处理这个请求的时候, userId
的值就会被URI模式中对应部分的值所填充。比如说,如果请求的URI是 /userId/1001
,此时变量 userId
的值就是 1001
。
为了处理 @PathVariables
标注,Spring MVC必须通过变量名来找到URI模式中相对应的变量。可以在标注中直接声明:
package com.hanpang.web; @Controller//告知其是一个控制器 @RequestMapping("/shxt") public class Demo03Controller { @RequestMapping("/{userId}") public ModelAndView test01(@PathVariable(name="userId") String id) { System.out.println("获取占位符的值:"+id); return null; } }
package com.hanpang.web; @Controller//告知其是一个控制器 @RequestMapping("/shxt") public class Demo03Controller { @RequestMapping("/{userId}/role/{roleKey}") public ModelAndView test01(@PathVariable(name="userId") String id,@PathVariable String roleKey) { System.out.println("userId:"+id); System.out.println("roleKey:"+roleKey); return null; } }
当 @PathVariable
标注被应用于 Map<String, String>
类型的参数上时,框架会使用所有URI模式变量来填充map。
package com.hanpang.web; @Controller//告知其是一个控制器 @RequestMapping("/shxt") public class Demo03Controller { @RequestMapping("/{userId}/role/{roleKey}") public ModelAndView test01(@PathVariable Map<String,String> map) { System.out.println(map); return null; } }
@PathVariable
可以被应用于所有简单类型的参数上,比如int、long、Date等类型。Spring会自动地帮你把参数转化成合适的类型,如果转换失败,就抛出一个 TypeMismatchException
。如果需要处理其他数据类型的转换,也可以注册自定义的类。
有时候可能需要更准确地描述一个URI模式的变量,比如: /spring-web/spring-web-3.0.5.jar
。要怎么把它分解成几个有意义的部分呢?
@RequestMapping
标注支持在URI模式变量中使用正则表达式。语法是 {varName:regex}
,其中第一部分定义了变量名,第二部分就是所要应用的正则表达式。比如下面的代码样例:
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version://d//.//d//.//d}{extension://.[a-z]+}") public void handle(@PathVariable String version, @PathVariable String extension) { // ...... } }
除了URI模式外,@RequestMapping标注还支持Ant风格的路径模式(如 /myPath/*.do
等)。不仅如此,还可以把URI模式变量和Ant风格的glob组合起来使用(比如 /owners/*/pets/{petId}
这样的用法等)。