SpringMVC核心——映射问题
一、SpringMVC 使用 RequestMapping 来解决映射问题。
二、在学习 RequestMapping 之前,首先来看一张图。
这张图表示的是发送一次 http 请求时,所包含的请求 URL,请求 Method,以及请求头和请求体。图中已经标记的很明白了。
三、RequestMapping
1.翻译过来是请求映射,在我看来,映射的是 http 请求和处理请求的 handler 方法。
2.@RequestMapping 可以标注于处理请求的 Handler 类定义处,也可以标注于 handler 方法定义处。
(1)标注于 Handler 类定义处:提供基础的请求映射信息,相对于 web 应用的根目录。在真实项目中,相当于 namespace 的作用,一般用来划分模块。如:
请求 URL:http://localhost:8080/springmvc/test/method
目标Handler:
/**
* @author solverpeng
* @create 2016-08-03-11:06
*/
@Controller
@RequestMapping("/test")
public class RequestMappingTest2 {
@RequestMapping("/method")
public String testRequestMapping() {
System.out.println("test requestMapping..");
return "success";
}
}
需要注意的是:此时 handler 方法处的 @RequestMapping value 属性相对的是类定义处的路径。
(2)标注于 handler 方法定义处:提供请求的映射信息,相对于 web 应用的根目录。如:
请求URL:http://localhost:8080/springmvc/hello
目标 Handler:
@RequestMapping("/hello")
public String hello() {
System.out.println("hello springmvc!!!");
return "success";
}
3.@RequestMapping 属性详解。
在对各个属性进行解释说明之前,先来看看 @ReqeustMapping 这个注解类
从中可以看出,SpringMVC 在 Servlet 环境下,可以对 http 请求的所有信息进行映射,并且通过数组的方式,同个规则下,可以映射多个。
(1)value 属性
官方文档是这样解释的:
The primary mapping expressed by this annotation.
<p>In a Servlet environment: the path mapping URIs (e.g. "/myPath.do").
Ant-style path patterns are also supported (e.g. "/myPath/*.do").
At the method level, relative paths (e.g. "edit.do") are supported
within the primary mapping expressed at the type level.
Path mapping URIs may contain placeholders (e.g. "/${connect}")
解释的已经很明白了,在Servlet环境下,映射 URI,支持 Ant 风格的映射,在方法级别也支持相对路径的映射。映射信息甚至可以从外部文件中获取。
这里对 Ant 风格进行说明:
Ant 风格资源地址支持 3 中匹配:
?:匹配一个字符
*:匹配任意个字符
**:匹配多层路径
使用在 @RequestMapping 的 value 属性中:
/test/*/add:匹配 /test/test01/add、/test/test02/add 等URL
/test/**/add:匹配 /test/springmvc/test01/add、/test/springmvc/test02/add 等 URL
/test/springmvc/add??:匹配 /test/springmvc/addaa、/test/springmvc/addbb 等 URL
具体使用:可以映射单个 uri ,也可以映射多个 uri。
@RequestMapping("/hello")
public String hello() {
System.out.println("hello springmvc!!!");
return "success";
}
@RequestMapping(value = {"/testUrl01", "/testUrl02"})
public String testRequestMappingUrl() {
System.out.println("test multi url...");
return "success";
}
(2)method 属性
官方文档是这样解释的:
The HTTP request methods to map to, narrowing the primary mapping:
GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
<p><b>Supported at the type level as well as at the method level!</b>
When used at the type level, all method-level mappings inherit
this HTTP method restriction (i.e. the type-level restriction
gets checked before the handler method is even resolved).
<p>Supported for Servlet environments as well as Portlet 2.0 environments.
简单来说,method 属性是对 http 请求方式的一种映射,主要映射 GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE 这几种方式。
这几种方式以枚举的方式存放在:RequestMethod 枚举类中:
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
支持使用在类级别,也支持使用在方法级别,使用在类级别的时候,所有方法级别的映射都要继承它。
具体使用:可以映射一个 method,也可以映射多个 method。
@RequestMapping(value = "/testMultiMethod", method = {RequestMethod.GET, RequestMethod.POST})
public String testRequestMappingMultiMethod() {
System.out.println("test multi method...");
return "success";
} @RequestMapping(value = "/testUrl", method = RequestMethod.POST)
public String testRequestMappingUrlAndMethod(){
System.out.println("test url and method...");
return "success";
}
(3)params 属性
官方文档解释内容过多,这里只做说明:
params 属性映射的是请求参数,看下面几种映射:
"myParam=myValue" style expressions:请求参数中必须包含 myParam 且值必须为 myValue。
"myParam!=myValue" style expressions:请求参数中必须包含 myParam 且值必须不为 myValue。
"!myParam" style expressions:请求参数中必须不能包含 myParam。
可以使用在类级别,也可以使用在方法级别。使用在方法级别,需要继承自类级别。
看下面例子:
@RequestMapping(value = "/testMultiParam", params = {"userName", "age!=23"})
public String testRequestMappingParam5() {
System.out.println("test multi params ...");
return "success";
} /**
* 请求参数中必须包含 userName 但是不能等于jack。
*/
@RequestMapping(value = "/testParam4", params = "userName!=jack")
public String testRequestMappingParam4() {
System.out.println("test param4 ...");
return "success";
} /**
* 请求参数中不能包含 userName。
*/
@RequestMapping(value = "/testParam3", params = "!userName")
public String testRequestMappingParam3() {
System.out.println("test param3 ...");
return "success";
} /**
* 请求参数必须为 userName,且值为 jack。否则会返回404错误
*/
@RequestMapping(value = "/testParam2", params = "userName=jack")
public String testRequstMappingParam2() {
System.out.println("test param2 ...");
return "success";
} /**
* 如果请求参数中没有 userName 则会返回404错误
*/
@RequestMapping(value = "/testParam", params = "userName")
public String testRequestMappingParam() {
System.out.println("test param...");
return "success";
}
(4)header 属性
header 属性用来映射 http 请求头,主要分为下面几种映射:
"My-Header=myValue":映射的请求头属性 My-Header 属性值必须为 myValue,否则返回404。
"My-Header!=myValue":映射的请求头属性 My-Header 属性值必须不为 myValue,否则返回404。
"!My-Header":映射的请求必须不能存在 My-Header 属性,否则返回404。
如:
@RequestMapping(value = "/testHeader", headers = "Accept-Language=zh,zh-CN;q=0.8")
public String testRequestMappingHeader() {
System.out.println("test header ...");
return "success";
}
@RequestMapping(value = "/testHeader", headers = "Accept-Language!=zh,zh-CN;q=0.8")
public String testRequestMappingHeader() {
System.out.println("test header ...");
return "success";
}
@RequestMapping(value = "/testHeader", headers = "!Accept-Language")
public String testRequestMappingHeader() {
System.out.println("test header ...");
return "success";
}
同时支持媒体类型的通配,如:
RequestMapping(value = "/something", headers = "content-type=text/*")
将会匹配:"text/html", "text/plain" 等等。
(5)consumes 属性
consumes 属性用来映射消费者媒体类型,指的是请求,如:
consumes = "text/plain"
consumes = {"text/plain", "application/*"}
也可以使用 "!" 操作符,如在 "!text/plain" 中,用来过滤 Content-Type 除 "text/plain" 之外的类型。
Content-Type:请求头的内容类型,表示发送到服务器的内容数据的媒体类型,在服务器端可以通过 request.getContentType() 的方式读取。
使用 consumes = "text/plain" 表示只对 Content-Type 为 text/plain 的数据进行处理。即(消费请求内容数据)
(6)produces 属性
produces 属性用来映射生产者媒体类型,指的是响应,如:
produces = "text/plain"
produces = {"text/plain", "application/*"}
也可以使用 "!" 操作符,如在 "!text/plain" 中,用来过滤 Accept 除 "text/plain" 之外的类型。
在服务器端生产响应头 Content-Type 并指定返回的数据(服务器端是生产者),客户端是消费者。
总的来说:
①客户端—发送请求—服务器:客户端通过请求头Content-Type指定内容体的媒体类型(即客户端此时是生产者),服务器根据Content-Type消费内容体数据(即服务器此时是消费者)。
②服务器—发送请求—客户端:服务器生产响应头Content-Type指定的响应体数据(即服务器此时是生产者),客户端根据Content-Type消费内容体数据(即客户端此时是消费者)。
问题:
①服务器端可以通过指定【headers = "Content-Type=application/json"】来声明可处理(可消费)的媒体类型,即只消费Content-Type指定的请求内容体数据。
②客户端如何告诉服务器端它只消费什么媒体类型的数据呢?即客户端接受(需要)什么类型的数据呢?服务器应该生产什么类型的数据?此时我们可以请求的Accept请求头来实现这个功能。
关于这两个属性,具体内容可以参考:
http://jinnianshilongnian.iteye.com/blog/1695047
四、总结:
本节没有解释 springmvc config文件和 web.xml 的配置,就以前一篇文章作为基础。
SpringMVC 通过 RequestMapping 解决了 http 请求到目标处理方法的映射问题,通过 @RequestMapping 的各个属性,包含了所有请求内容,甚至对特定的类型还分配了独立的属性,如映射消费者、生产者媒体类型。
在使用的过程中,这种写法非常优雅、灵活。每一个属性都是 String[] 形式,支持同时匹配多个值,属于“或”的关系;且不同属性之间同时存在的话,属于“且”的关系。在学习该节之前,建议先对 http 请求有完整的理解。
已经在文章首页对一个 http 请求通过一张图的方式进行了说明。
还有一些基础内容,可以参看:
http://www.cnblogs.com/solverpeng/p/5613568.html
还有关于 url-pattern 的问题,可以参看:
http://www.cnblogs.com/solverpeng/p/5729763.html
SpringMVC核心——映射问题的更多相关文章
- SpringMVC深度探险(四) —— SpringMVC核心配置文件详解
在上一篇文章中,我们从DispatcherServlet谈起,最终为读者详细分析了SpringMVC的初始化主线的全部过程.整个初始化主线的研究,其实始终围绕着DispatcherServlet.We ...
- SpringMVC中映射路径的用法之请求限制、命名空间
SpringMVC中映射路径的请求限制 什么是SpringMVC请求限制? 在SpringMVC中,支持对请求的设置.如果不满足限制条件的话,就不让请求访问执行方法,这样可以大大提高执行方法 的安全性 ...
- 【spring源码学习】springMVC之映射,拦截器解析,请求数据注入解析,DispatcherServlet执行过程
[一]springMVC之url和bean映射原理和源码解析 映射基本过程 (1)springMVC配置映射,需要在xml配置文件中配置<mvc:annotation-driven > ...
- SpringMvc核心流程以及入门案例的搭建
1.什么是SpringMvc Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 M ...
- SpringMVC核心分发器DispatcherServlet分析[附带源码分析]
目录 前言 DispatcherServlet初始化过程 DispatcherServlet处理请求过程 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不 ...
- SpringMVC核心——视图渲染(包含视图解析)问题
一.本来想说的是返回值处理问题,但在 SpringMVC 中,返回值处理问题的核心就是视图渲染.所以这里标题叫视图渲染问题. 本来想在上一篇文章中对视图解析进行说明的,但是通过源码发现,它应该算到视图 ...
- SpringMVC核心类DispatcherServlet
配置DispatcherServlet 要使用SpringMVC,必须在web.xml中配置好这个DispatcherServlet类 <!-- spring框架必须定义ContextLoade ...
- SpringMVC的映射器、适配器、解析器
1.处理器和适配器 1.1springmvc的映射器 根据客户端请求的url,找到处理本次请求的handler(处理器),将url和controller关联起来 1.2springmvc的适配器 对映 ...
- SpringMVC核心类和注解
springMVC最重要的就是前端控制器DispatchServlet了.他是整个springMVC应用的核心. 需要将它配置在web.xml中. 1.DispatchServlet的配置 <! ...
随机推荐
- 学习rabbitmq
http://www.cnblogs.com/dubing/p/4017613.html elk+redis 搭建nginx日志分析平台 http://www.cnblogs.com/yjf512/p ...
- SK-Learn使用NMF(非负矩阵分解)和LDA(隐含狄利克雷分布)进行话题抽取
英文链接:http://scikit-learn.org/stable/auto_examples/applications/topics_extraction_with_nmf_lda.html 这 ...
- Logdump使用指引
Logdump使用指引 Logdump使用指引在GGSCI中使用如下命令查看当前处理的队列文件和RBA号,例如:GGSCI (br-jl-accs-db1) 3> info REPYXAREPL ...
- H5页面设计器,仿有赞商城页面在线设计器,比富文本框更友好的内容编辑器
基本上每个web应用,都会牵扯到内容编辑,尤其是移动的web应用,微信开发之类的.页面内容自定义是最常用的功能了,之前大部分解决方案都是采用富文本框编辑器kindeditor,ueditor,cked ...
- MySQL数据库从GBK转换到UTF-8最简单解决方案(也适用于其它编码转换)
1.使用mysqldump导出表结构,如: mysqldump -d -u root -p 数据库名 >/root/struct.sql 2.使用mysqldump以特定编码导出数据(其中utf ...
- 配置ST3在浏览器中打开
打开Preferences - 「Key Bindings - User」,添加此行: {"keys": ["f1"],"command": ...
- data-role参数表:
data-role参数表: page 页面容器,其内部的mobile元素将会继承这个容器上所设置的属性 header 页面标题容器,这个容器内部可以包含文字.返回按钮.功能按钮等 ...
- hadoop的dfs工具类一个【原创】
开始没搞定插件问题,就弄了个dsf操作类,后面搞定了插件问题,这玩意也就聊胜于无了,还是丢这里算了. 首先是一个配置,ztool.hadoop.properties hadoop.home.dir=G ...
- 聊聊并发(七)——Java中的阻塞队列
3. 阻塞队列的实现原理 聊聊并发(七)--Java中的阻塞队列 作者 方腾飞 发布于 2013年12月18日 | ArchSummit全球架构师峰会(北京站)2016年12月02-03日举办,了解更 ...
- 用Wireshark简单分析HTTP通信
我们都学过TCP,HTTP的相关概念,本文借助协议分析工具Wireshark,让大家对一些概念眼见为实,权当温故而知新. 场景: 在Client(10.239.196.211)上通过web brows ...