1.使用@RequestMapping 映射请求
1.1在类和方法上添加@RequestMapping
SpringMVC 使用@RequestMapping 为控制器指定可以处理哪些 URL 请求。可以在类上和方法上都添加@RequestMapping 注解。如在 IndexController 中添加注解:
@Controller
//加上这个注解,本类方法访问路径前都要加上/mvc
@RequestMapping("/mvc")
public class IndexController {
//RequestMapping 设置访问路径是 index.html
//因为类名上面已经加了/mvc,所以进入这个方法的 url 是/mvc/index.html
@RequestMapping("/index.html")
public String showIndex() {
//因为添加了父路径,而 index.jsp 在根路径,所以前面加/代表相对于根路径
return "/index.jsp";
}
}
IndexController 类 上 添 加 了 @RequestMapping(“/mvc”) , 相 当 于 一 个 父 路 径 , 即IndexController 类中所有@ResuestMapping 注解的方法访问路径前都要添加上这个路径。想进入 showIndex()方法,路径是/mvc/index.html。@RequestMapping(“/mvc”)相当于@RequestMapping(value=“/mvc”)DispatcherServlet 截获请求后,就通过RequestMapping 提供的信息,将请求进行分发。
应用场景示例:
DeptController 用于处理部门相关的业务。EmployeeController 用于处理员工相关的业务。部门列表叫 list.html,员工列表也叫 list.html。可以通过父路径来区分请求。不需要程序员给每个请求单独起名字,也能让项目中的 url 更规范。
1.2 通过 method 指定 POST 或 或 GET
@RequestMapping 中有一个 method 属性,用于指定当前的方法是用 POST 还是 GET 访问:
//此方法只支持 POST 访问方式
@RequestMapping(value = "/post.html", method = RequestMethod. POST )
public String showPost() {
return "/index.jsp";
}
如果在浏览器中通过 GET 访问,会出现如下错误:
1.3其他参数
其它参数需要对应到 http 请求头:
1. comsume:
@RequestMapping(value = "xx.html", consumes = "application/json")
方法仅处理 request Content-Type 为“application/json”类型的请求。
2. produces:
@RequestMapping(value = "xx.html", produces = "application/json")
方法仅处理 request 请求中 Accept 头中包含了"application/json"的请求,同时返回的内容类型为 application/json;
3. params:
@RequestMapping(value = "xx.html", params = "act=list")
只处理请求中包含 act 参数并且值为 list 的请求。
params=”param1”请求中必须包含参数名为 param1 的参数。
params=”!param1”请求中不能包含参数名为 param1 的参数。
params=”param1!=value1”请求中包含名为 param1 的参数,但参数值不能为 value1。
params={“p1=v1”,p2}请求中必须包含名称为 p1 和 p2 两个参数,且 p1 的值为 v1。
4. headers:
@RequestMapping(value = "xx.html", headers = "Referer=http://www.xx.com/")
仅处理 request 的 header 中包含了指定“Refer”请求头和对应值为“ http://www.xx.com/ ”的请求;
1.4 REST 风格 URL
如/delete/123 和/delete/456 这两个 url,其中/delete/是公用的,后面的 123 和 456 是动态的参数。使用@PathVariable 获取参数:
//url 中包含参数
@RequestMapping(value = "/rest1/{id}")
public String testRest1(@PathVariable Integer id) {
System. out .println(id);
return "/index.jsp";
}
//占位的参数和方法中参数名不同的时候
@RequestMapping(value = "/rest2/{id} ")
public String testRest2(@PathVariable("id") Integer someId) {
System. out .println(someId);
return "/index.jsp";
}
1.5 支持正则表达式
//支持正则表达式匹配
@RequestMapping("/reg/{param:[\\d]+.html")
public String testRest3(@PathVariable Integer param) {
System. out .println(param);
return "/index.jsp";
}
{参数名:正则表达式}
应用场景示例:
比如有一些静态页面展示,如果每一个页面都写一个访问的方法,会增加代码量。可以使用动态参数,在路径中提取出页面名称,合并到一个方法。(ps:在项目开发中,有时需要对权限进行限制,比如有些页面必须登录后才能访问。这时就需要限制用户不能直接通过.jsp 直接访问 jsp 页面文件,而是通过.html 经过 Spring 过滤器进行处理。)
上面的代码返回的页面路径前没有加/,所以是相对于当前访问路径的,页面需要放在webapp 的 page 文件夹下才能显示。
1.6 ANT 风格 URL
Ant 风格支持三种匹配符:
1. ?:匹配一个字符
@RequestMapping("/ant/test??.html")
可以匹配/ant/testaa.html 或/ant/testbb.html
2. *:匹配任意字符
@RequestMapping("/ant/*/test.html")
3. **:匹配多层路径
@RequestMapping("/ant/**/test.html")
可以匹配/ant/test.html 或/ant/aa/test.html 或/ant/aa/bb/test.html 等ANT 风格的 url 通常用在资源路径的加载中。
2. 参数绑定
2.1 @RequestParam
使用@RequestParam 可以实现把请求中的参数传递给被请求的方法。在这里我们新建一个 ParamController.java。
2.1.1 value
@Controller
public class ParamController {
@RequestMapping("param1.html")
public String testParam1(@RequestParam(value = "name") String name,
@RequestParam(value = "id") Integer id) {
System. out .println(name);
System. out .println(id);
return "index.jsp";
}
}
在浏览器中访问如下地址:http://localhost:8080/param1.html?name=abc&id=1
可以看到控制台上输出:
abc
1
@RequestParam(value = "name") String name
相当于 servlet 中的:
String name=request.getParameter("name");
代码:
@RequestParam(value = "id") Integer id
相当于 servlet 中的:
String idStr= request.getParameter("id");
Integer id=null;
if(idStr!=null&& idStr.trim()!=""){
id=Integer.parseInt(idStr)
}
2.1.2 required
默 认 的 使 用 @RequestParam 注 解 的 参 数 都 是 必 传 的 。 上 面 的 例 子 中 , 使 用@RequestParam 注解了 name 和 id 两个参数。如果在访问的时候少传一个参数,会出现如下异常:
如果某个参数不是必须的,可以使用 required 属性设置:
@RequestParam(value = "id",required = false) Integer id
required 默认是 true,代表参数必传;设置为 false,则代表参数可以为 null。需要注意的是如果注入的是基本类型的数据,如 int 型,参数为空就会抛出异常,因为null 不能赋值给基本数据类型,只能是对象类型。
2.1.3 defaultValue
如果没传某个参数时,想给参数一个默认值,可以使用 defaultValue 属性设置:
@RequestParam(value = "name",defaultValue = "123") String name
如果访问时没传 name 参数,将会默认给 name 赋值为 123。相当于 servlet 中的:
String name = request.getParameter("name");
if (name = null) {
name ="123";
}
2.1.4 简化写法
//当 url 中的参数名与方法接收时参数名一致,且参数都是必传的,可以省略@RequestParam
@RequestMapping("param3.html")
public String testParam3(String name, Integer id) {
System. out .println(name);
System. out .println(id);
return "index.jsp";
}
2.1.5 映射 POJO 类型参数
SpringMVC 支持 POJO 类型参数映射,即将多个参数直接封装成实体类。如我们要将参数封装到 Employee 和 Dept 对象中,先创建实体类:
public class Dept {
private Integer id;
private String name;
private List<Employee> employees;
//getter/setter 方法略
}
-------------------------------------
public class Employee {
private Integer id;
private String name;
private Float salary;
private Dept dept;
//getter/setter 方法略
}
controller 中的方法:
//映射 pojo 类
@RequestMapping("param5.html")
public String testParam5(Employee employee) {
System. out .println("员工名:" + employee.getName());
System. out .println("员工 id:" + employee.getId());
//支持级联形式的映射
System. out .println("员工部门名:" + employee.getDept().getName());
System. out .println("员工部 id:" + employee.getDept().getId());
return "index.jsp";
}
为方便测试,jsp 页面中以表单形式提交请求:
<form action="/param5.html" method="post">
员工 id:<input name="id" type="text"/><br/>
员工名:<input name="name" type="text"/><br/>
<!--级联形式的映射-->
员工部门 id:<input name="dept.id" type="text"/><br/>
员工部门名:<input name="dept.name" type="text"/><br/>
<input type="submit" value="提交"/>
</form>
运行结果:
提交后控制台输出:
2.1.6 基本类型的数组
基本数据类型的数组如 Integer[],String[]等比如批量删除数据的时候,需要传递多个数据的 id,这时用一个数组去接收:
//映射数组
@RequestMapping("param6.html")
public String testParam6(Integer[] ids) {
for (Integer id : ids) {
System. out .println(id);
}
return "index.jsp";
}
页面:
<form action="/param6.html" method="post">
<input name="ids" value="1" type="checkbox"/>1<br/>
<input name="ids" value="2" type="checkbox"/>2<br/>
<input name="ids" value="3" type="checkbox"/>3<br/>
<input name="ids" value="4" type="checkbox"/>4<br/>
<input type="submit" value="提交"/>
</form>
运行结果:控制台输出:
2.2 @RequestBody
对于复杂的数据类型,如 Dept[]、List<Integer>、List<Dept>、List<Map<String,Object>>以及 Dept 里包含 List<Employee>的映射,不能再使用简单的 form 表单提交请求了,需要使用 ajax 模拟提交 json 数据,并指定请求的 contentType 是 application/json。在 Controller 中用@RequestBody 接收参数。SpringMVC 解析 json 需要一个 json 适配器,json 转化使用的是 jackson,需要在 pom.xml中添加 jackson 的 jar 包:
<!-- Jackson Json 处理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.4</version>
</dependency>
在 springMVC-servlet.xml 中配置 json 适配器:
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
在工程中加入 jQuery 类库,如 jquery-1.10.1.min.js:
param.jsp 是我们写页面代码的文件。在页面中引入 jQuery:
<script type="text/javascript" src="jquery-1.10.1.min.js"></script>
3.2.1 List<Object> 类型的映射
List 是基本数据类型的集合,如 List<String>类型的映射:
//List 集合中包含基本数据类型
@RequestMapping("param7.html")
public String testParam7(@RequestBody List<String> names) {
for (String name : names) {
System. out .println(name);
}
return "index.jsp";
}
页面中发送请求的方法:
<input type="button" onclick=" testParam7 ()" value="测试 List<Object>"/>
<script type="text/javascript">
function testParam7 (){
var nameList = ["张三","李四 "];//String 类型的数组
$.ajax({
type: "POST",
url: "/param7.html",
data: JSON .stringify(nameList),//将对象序列化成 JSON 字符串
contentType : "application/json;charset=utf-8",
success: function(data){
alert(data);
}
});
}
</script>
3.2.2 List<POJO> 和 和 POJO[] 类型的映射
如将请求数据封装成 List<Dept>:
//List 集合中包含对象类型
@RequestMapping("param8.html")
//如果是数组,就写(@RequestBody Dept[] depts)
public String testParam8(@RequestBody List<Dept> depts) {
//public String testParam8(@RequestBody Dept[] depts) {
for (Dept dept : depts) {
System. out .println(dept.getId() + dept.getName());
}
return "index.jsp";
}
如果要封装成数组,就写页面提交请求方法
<input type="button" onclick=" testParam8 ()" value="测试 List<POJO>"/>
<script type="text/javascript">
function testParam8 (){
var deptList = new Array();//集合中存放的是实体类
deptList.push({"id":1,"name":"技术部"});
deptList.push({"id":2,"name":"测试部"});
$.ajax({
type: "POST",
url: "/param8.html",
data: JSON .stringify(deptList),//将对象序列化成 JSON 字符串
contentType : "application/json;charset=utf-8",
success: function(data){
alert(data);
}
});
}
</script>
3.2.3 POJO 中包含 List 的映射
//POJO 中包含 List。Dept 中包含 List<Employee>
@RequestMapping("param9.html")
public String testParam9(@RequestBody Dept dept) {
System. out .println(dept.getName());
for (Employee employee : dept.getEmployees()) {
System. out .println(employee.getName());
}
return "index.jsp";
}
页面提交请求的代码:
<input type="button" onclick=" testParam9 ()" value="POJO 中包含 List"/>
<script type="text/javascript">
function testParam9 (){
var empList = new Array();//集合中存放的是实体类
empList.push({"id":1,"name":"张三"});
empList.push({"id":2,"name":"李四"});
var dept={"id":1,"name":"技术部","employees":empList};
$.ajax({
type: "POST",
url: "/param9.html",
data: JSON .stringify(dept),//将对象序列化成 JSON 字符串
contentType : "application/json;charset=utf-8",
success: function(data){
alert(data);
}
});
}
</script>
3.2.4 List<Map<String,Object>> 的映射
List 中封装 Map 的操作和封装 POJO 类似:
//List<Map<String,Object>>的映射
@RequestMapping("param10.html")
public String testParam10(@RequestBody List<Map<String, Object>> map) {
for (Map<String, Object> stringObjectMap : map) {//遍历集合
for (String key : stringObjectMap.keySet()) {//遍历当前 Map 中的 key
//根据 key 拿到对应的值
System. out .println(key + "=" + stringObjectMap.get(key));
}
System. out .println("--------------------");
}
return "index.jsp";
}
页面发送请求的代码:
<input type="button" onclick=" testParam10 ()" value="测试 List<Map<String,Object>>"/>
<script type="text/javascript">
function testParam10 (){
var data = new Array();//
data.push({"id":1,"name":"技术部"});
data.push({"id":3,"addr":"三楼"});
$.ajax({
type: "POST",
url: "/param10.html",
data: JSON .stringify(data),//将对象序列化成 JSON 字符串
contentType : "application/json;charset=utf-8",
success: function(data){
alert(data);
}
});
}
</script>
3.3 使用 Servlet API
如果我们在方法中还想用 Servlet 的 request 和 response,可以在方法上添加参数:
/得到 HttpServletRequest 和 HttpServletResponse
@RequestMapping("param4.html")
public String testParam4(HttpServletRequest request, HttpServletResponse response) {
System. out .println(request.getParameter("name"));
return "index.jsp";
}
需要在 pom.xml 中添加 servlet 的 jar 包:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>