一. RequestMapping修饰类
SpringMVC使用@RequestMapping注解为请求处理器指定映射的URL,我们的HelloWorld程序中,@RequestMapping注解是修饰在目标方法上,实际上此注解也可以修饰在类上。
@Controller //表示是一个控制器
@RequestMapping("/hello")
public class HelloWorld {
/**
* sayHello 我们称之为请求处理器的 目标方法,每一个带有@RequestMapping注解的方法都叫做目标方法,能够处理一个URL请求
* @RequestMapping用来映射目标方法请求URL
* @return
*/
@RequestMapping("/helloworld")
public String sayHello() {
System.out.println("Hello SpringMVC");
return "success";
}
}
上面的程序中,在类上使用@RequestMapping(“/hello”),而在目标方法上使用@RequestMapping(“/helloworld”),那么这个目标方法真实的映射的地址是:/hello/helloworld,所以我们得出结论:
- @RequestMapping在类定义处:提供了初步的映射请求URL,表示此请求处理器中所有的目标方法都在此URL下访问
- @RequestMapping在方法处:为方法提供了进一步的映射请求URL。
那么我们的目标方法真实的映射URL信息 = 类定义处映射的URL+方法定义出映射的URL。而且不管是类定义出映射的URL还是方法定义出映射的URL都可以省略第一个/。
二. RequestMapping请求方式
@RequestMapping可以使用method属性指定请求方式,那么指定了请求方式的目标方法表示只能处理指定的请求方式。
/**
* method=RequestMethod.POST : 表示此处理方法只能够处理POST请求
* method=RequestMethod.GET : 表示此处理方法只能够处理GET请求
* method=RequestMethod.DELETE : 表示此处理方法只能够处理DELETE请求
* method=RequestMethod.PUT : 表示此处理方法只能够处理PUT请求
* @return
*/
@RequestMapping(value="testMethod",method=RequestMethod.POST)
public String testMethod() {
System.out.println("testMethod...");
return SUCCESS;
}
三. RequestMapping指定参数和请求头
RequetMapping注解可以使用value映射请求地址,使用method映射请求方法,我们也可以使用params映射请求参数,使用headers映射请求头,如果请求的地址不是value指定的映射地址,那么肯定不会执行相应的请求处理器的目标方法,如果请求方式不是method指定的请求方式,那么也不会执行相应的请求处理器的目标方法,同理,如果没有满足params和headers指定的请求参数和请求头,也不会执行响应的请求处理器的目标方法。
示例一:指定请求参数
/**
* 使用params指定请求参数,因为参数可能有多个,所以使用一个数组来表示
* params= {"name","age"} : 表示请求参数必须包含name 和 age,否则出现404错误
* params= {"name=xxx","age"}:表示请求参数必须包含name 和 age,而且name的参数值必须为xxx,否则出现404
* params= {"name!=xxx","age"}:表示请求参数必须包含name 和 age,而且name的参数值必须不能为为xxx,否则出现404
* params= {"name=xxx","!age"}:表示请求参数必须包含name,但是不能存在age参数,而且name的参数值必须为xxx,否则出现404
* @return
*/
@RequestMapping(value="testParams",params= {"name","!age"})
public String testParams() {
System.out.println("testParams...");
return SUCCESS;
}
示例二:指定请求头,请求头和请求参数是同样的道理
/**
* 使用headers指定请求头,因为请求头可能有多个,所以使用一个数组来表示
* headers= {"Connection=keep-alive"}:表示必须包含Connection请求头,而且只必须是keep-alive
* @return
*/
@RequestMapping(value="testHeaders",headers= {"Connection=keep-alive"})
public String testHeaders() {
System.out.println("testParams...");
return SUCCESS;
}
四. Ant风格路径
Ant风格的通配符支持3中匹配方式:
- ? 表示匹配一个字符
- * 表示匹配任意个字符
- ** 表示匹配多次路径的任意个字符
RequestMapping注解是支持Ant风格的通配符的,而且是唯一支持的一种。表示RequestMapping支持通配符,但只支持Ant风格一种。
示例:
/**
*
* @return
*/
// /testAnt/*/wanbangee 表示请求地址/testAnt/任意字符/wanbangee 比如/testAnt/abc/wanbangee,/testAnt/123/wanbangee,/testAnt/haha/wanbangee 都能够映射成功
// /testAnt/**/wanbangee 表示请求地址/testAnt/任意字符任意路径/wanbangee 比如/testAnt/a/b/c/wanbangee,/testAnt/1/wanbangee,/testAnt/abc/wanbangee
@RequestMapping("/testAnt/**/wanbangee")
public String testAnt() {
System.out.println("testAnt...");
return SUCCESS; //SUCCESS是常量被定义好的字符串
}
五. PathVariable注解
@PathVariable注解时用来映射URL绑定的占位符,是Spring3.0中新增的功能,这个功能在SpringMVC向Rest目挺近的过程中具有里程碑式的意义,通过@PathVariable注解可以将URL中占位符参数绑定要请求处理器的目标方法入参中,URL中{XXX}占位符通过@PathVariable(“XXX”)注解绑定要目标方法的入参中。
/**
* /testPathVariable/{name}/{age} : 表示会通过url占位符的形式传递两个参数过来,一个是name,另外一个是age
* 处理器的目标方法中使用@PathVariable("name") String name 获取URL占位符中的name参数,并且赋值给目标方法的入参name
* 处理器的目标方法中使用@PathVariable("age")Integer age 获取URL占位符中的age参数,并且赋值给目标方法的入参age
*
* 请求地址:hello/testPathVariable/jjm/32 会匹配到 /testPathVariable/{name}/{age} ,而且通过URL占位符携带的参数为jjm 和 32
*
*
* @param name
* @param age
* @return
*/
@RequestMapping("/testPathVariable/{name}/{age}")
public String testPathVariable(@PathVariable("name")String name,@PathVariable("age")Integer age) {
System.out.println("name:" + name + ",age:" + age);
System.out.println("testPathVariable....");
return SUCCESS;
}
六. HiddenHttpMethodFilter过滤(REST风格URL)
REST:Representational state transfer 叫做资源表现层状态转化,是目前最流行的一种互联网软件架构,Rest结构清晰,符合标准,易于理解,便于扩展,所以目前得到了越多越多的网站使用。转台转化:每次发送一个请求,表示客户端和服务端的一次交互过程,Http协议是一个无状态的协议,即所有的状态都保存在服务器端,因此如果客户想要操作服务器,必须通过某种手段,让服务器端发生状态转化,而这种转化是建立在表现层的,所以就叫做资源表现出状态转化,具体的说,就是在Http协议中,使用get请求来获取资源,使用post请求来新建资源,使用put请求来更新资源,使用delete请求来删除资源 ,http协议中存在get请求和post请求,如果发送put和delete请求呢,SpringMVC可以将post请求转换成put或者delete请求,这就是SpringMVC提供的资源表现层状态转化。所以在我们后续的开发中,不仅仅只有post和get请求了,还存在delete和put请求。
实例:
- get请求查询数据:/user/1 表示查询ID为1的资源
- Post请求新增数据:/user表示新增资源
- Delete请求删除资源:/user/1 表示删除ID为1的资源
- Put 请求修改资源 :/user/1 表示修改ID为1的资源
现在关键在于如何将post请求转换成delete和put请求呢?SpringMVC提供了响应的解决方案:
- 配置过滤器 HiddenHttpMethodFilter
- 发送post请求,携带_method = put 或者_method=delete 表示将post请求转换成put或者delete 请求。
- 在web.xml中配置过滤器
<!-- 配置HiddenHttpMethodFilter -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2. 编写请求处理器
/**
* 删除
* @param id
* @return
*/
@RequestMapping(value="/user/{id}",method=RequestMethod.DELETE)
public String deleteById(@PathVariable("id") Integer id) {
System.out.println("delete...." + id);
return SUCCESS;
}
/**
* 修改
* @param id
* @return
*/
@RequestMapping(value="/user/{id}",method=RequestMethod.PUT)
public String updateById(@PathVariable("id") Integer id) {
System.out.println("put...." + id);
return SUCCESS;
}
/**
* 新增
* @return
*/
@RequestMapping(value="/user",method=RequestMethod.POST)
public String insert() {
System.out.println("post....");
return SUCCESS;
}
/**
* 查询
* @param id
* @return
*/
@RequestMapping(value="/user/{id}",method=RequestMethod.GET)
public String selectById(@PathVariable("id") Integer id) {
System.out.println("get...." + id);
return SUCCESS;
}
- 编写请求页面
<form action="${pageContext.request.contextPath}/hello/user/1" method="post">
<input type="hidden" name="_method" value="delete">
<button>test RestFul Delete</button>
</form>
<br>
<form action="${pageContext.request.contextPath}/hello/user/1" method="post">
<input type="hidden" name="_method" value="put">
<button>test RestFul Put</button>
</form>
<br>
<form action="${pageContext.request.contextPath}/hello/user" method="post">
<button>test RestFul Post</button>
</form>
<br>
<a href="${pageContext.request.contextPath}/hello/user/1">test RestFul Get</a>
现在大家会问到三个问题:
- 参数名一定要_method 吗? 一定
- 参数值delete或者put有没有大小写的限制? 没有
- 可以不使用隐藏域传递_mthod吗? 可以,但是存在问题,使用text显示的话可能会被用户修改,所以建议使用hidden隐藏域
小结
在SpringMVC中有很多对注解的操作,大家要理解注解的用途以及注解属性的作用。