Spring(三)

9.请求映射
假设浏览器发送了一个请求如下:
-------------------------------
POST /login HTTP1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,en;q=0.8,zh;q=0.5,en-US;q=0.3
Connection: keep-alive
Cookie: JSESSIONID=DBC6367DEB1C024A836F3EA35FCFD5A2
Host: 127.0.0.1:8989
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0

username=tom&password=123
--------------------------------


http协议的请求格式如下:
---------------------------------
请求方法 URL 协议版本号
请求头信息
请求头信息
请求头信息
..
回车换行
请求正文
---------------------------------


从格式中我们可以看到【请求方法、URL、请求头信息、请求正文】这四部分一般是可变的,因此我们可以把请求中的这些信息在处理器的【功能处理方法】中进行的映射,因此请求的映射分为如下几种:
	URL路径映射
		使用URL映射到处理器的功能处理方法;
	请求方法映射限定
		例如限定功能处理方法只处理GET请求;
	请求参数映射限定
		例如限定只处理包含username参数的请求;
	请求头映射限定
		例如限定只处理"Accept=application/json"的请求。

10.URL路径映射
1)普通URL路径映射
@RequestMapping(value="/test")
@RequestMapping("/hello")
注解中只出现一个参数且参数名为value的话,可以将参数名去掉
@RequestMapping(value={"/test", “/user/hello”})
多个URL路径可以映射到同一个处理器的功能处理方法。

2)URI模板模式映射
@RequestMapping(value="/users/{userId}")
{XXX}占位符,得写, 请求的URL可以是"/users/123456"或"/users/abcd",之后可以通过@PathVariable可以提取URI模板模式中的{XXX}中的值
@RequestMapping(value="/users/{userId}/create")
这样也是可以的,请求的URL可以是"/users/123/create"
@RequestMapping(value="/users/{userId}/topics/{topicId}")
这样也是可以的,请求的URL可以是"/users/123/topics/123"

3)Ant风格的URL路径映射
@RequestMapping(value="/users/")
可以匹配"/users/abc/abc",但"/users/123"将会被【URI模板模式映射中的"/users/{userId}“模式优先映射到】
@RequestMapping(value=”/product/?")
可匹配"/product/1"或"/product/a",但不匹配"/product"或"/product/aa";
?代表有且只有一个字符
@RequestMapping(value="/product*")
可匹配"/productabc"或"/product",但不匹配"/productabc/abc";
代表0~n个字符
@RequestMapping(value="/product/
")
可匹配"/product/abc",但不匹配"/productabc";
@RequestMapping(value="/products/
/{productId}")
可匹配"/products/abc/abc/123"或"/products/123",也就是Ant风格和URI模板变量风格可混用;
**代表所有的子路径

4)正则表达式风格的URL路径映射
从Spring3.0 开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式},之后通过@PathVariable可以提取{XXX:正则表达式匹配的值}中的XXX这个变量的值。

	@RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}")
		可以匹配"/products/123-1",但不能匹配"/products/abc-1",这样可以设计更加严格的规则。
	@RequestMapping(value="/user/{userId:^\\d{4}-[a-z]{2}$}")
		可以匹配"/user/1234-ab"

	注意:\d表示数字,但是\在java的字符串中是特殊字符,所以需要再加一个\进行转义即可
	(参照之前js的学习文档,和java的正则几乎一致,js正则中的一个/变为java中的俩个/即可)
		括号:
			[abc] 	查找方括号之间的任何字符。
			[^abc] 	查找任何不在方括号之间的字符。
			[0-9] 	查找任何从 0 至 9 的数字。
			[a-z] 	查找任何从小写 a 到小写 z 的字符。
			[A-Z] 	查找任何从大写 A 到大写 Z 的字符。
			[A-z] 	查找任何从大写 A 到小写 z 的字符。
			(red|blue|green) 	查找任何指定的选项。

		元字符:
			. 	查找单个任意字符,除了换行和行结束符.如果要表示.这个字符,需要转义
			\w 	查找单词字符。     字母 数字 _
			\W 	查找非单词字符。非 字母 数字 _
			\d 	查找数字。
			\D 	查找非数字字符。
			\s 	查找空白字符。
			\S 	查找非空白字符。
			\b 	匹配单词边界。
			\B 	匹配非单词边界。
			\0 	查找 NUL 字符。
			\n 	查找换行符。
			\f 	查找换页符。
			\r 	查找回车符。
			\t 	查找制表符。
			\v 	查找垂直制表符。

		量词:
			n+ 		匹配任何包含至少一个 n 的字符串。
			n* 		匹配任何包含零个或多个 n 的字符串。
			n? 		匹配任何包含零个或一个 n 的字符串。
			n{X} 	匹配包含 X 个 n 的序列的字符串。
			n{X,Y} 	匹配包含 X 到 Y 个 n 的序列的字符串。
			n{X,} 	匹配包含至少 X 个 n 的序列的字符串。
			n$ 		匹配任何结尾为 n 的字符串。
			^n 		匹配任何开头为 n 的字符串。
			?=n 	匹配任何其后紧接指定字符串 n 的字符串。
			?!n 	匹配任何其后没有紧接指定字符串 n 的字符串。


	正则表达式风格的URL路径映射是一种特殊的URI模板模式映射
	URI模板模式映射不能指定模板变量的数据类型,如是数字还是字符串;
	正则表达式风格的URL路径映射,可以指定模板变量的数据类型,可以将规则写的相当复杂。

11.请求方法映射限定
一般获取数据为GET请求方法,提交表单一般为POST请求方法。但之前URL路径映射方式对任意请求方法都是接受的,因此我们需要某种方式来告诉相应的功能处理方法只处理如GET方式的请求或POST方式的请求。

@RequestMapping(value="/user/{userId:\\d+}",method=RequestMethod.GET)
	可以匹配"/user/100",并且请求方式只能是GET

@RequestMapping(value="/hello", method={RequestMethod.POST,RequestMethod.GET})
	可以匹配"/hello",并且请求方式只能是POST或者GET

@RequestMapping(value="/register",method={RequestMethod.POST})
public String doPost(String name){
	System.out.println("name = "+name);
	System.out.println("注册成功");
	return "success";
}
@RequestMapping(value="/register",method={RequestMethod.GET})
public String doGet(){
	return "register";
}

注意:
1、一般浏览器只支持GET、POST请求方法,如想浏览器支持PUT、DELETE 等请求方法只能模拟。(jquery中的ajax函数可以发送这些方式的请求)
2、除了GET、POST,还有HEAD、OPTIONS、PUT、DELETE、TRACE(观察servlet源码也可获知)
3、DispatcherServlet默认开启对GET、POST、PUT、DELETE、HEAD 的支持;
4、如果需要支持OPTIONS、TRACE,请添加DispatcherServlet 在web.xml 的初始化参数:dispatchOptionsRequest 和
dispatchTraceRequest 为true。(查看源码,在DispatcherServlet的父类中可以找到这个俩个属性)

12.请求参数映射限定
1)请求数据中有指定参数名

	@RequestMapping("/test")
   	@Controller
   	public class HomeController {
   		@RequestMapping(params="create",method=RequestMethod.GET)
   		public ModelAndView test1(){

   			return null;
   		}
   		@RequestMapping(params="create",method=RequestMethod.POST)
   		public ModelAndView test2(){

   			return null;
   		}
   	}
可以匹配的路径为:/test?create
如果是get 方式的请求则访问test1方法
如果是post方式的请求则访问test2方法

2)请求数据中没有指定参数名
@RequestMapping(params="!create", method=RequestMethod.GET)

3)请求数据中指定参数名=值
@RequestMapping(params=“username=tom”)

4)请求数据中指定参数名!=值
username参数名可以不出现,但是如果出现了,那么参数值一定不能等于tom
@RequestMapping(params=“username!=tom”)

5)组合使用是"且"的关系
@RequestMapping(params={“create”,“username=tom”})

13.请求头数据映射限定
1)请求头数据中有指定参数名
@RequestMapping(value="/header/test1", headers=“Accept”)
表示请求的URL必须为"/header/test1"且请求头中必须有Accept参数才能匹配。

@RequestMapping(value="/header/test1", headers=“my_test”)
表示请求的URL必须为"/header/test1"且请求头中必须有my_test参数才能匹配

2)请求头数据中没有指定参数名
@RequestMapping(value="/header/test2", headers="!abc")
表示请求的URL必须为"/header/test2"且请求头中必须没有abc参数才能匹配

3)请求头数据中指定参数名=值
@RequestMapping(value="/header/test3", headers=“Content-Type=application/json”)
表示请求的URL必须为"/header/test3"且请求头中必须有"Content-Type=application/json"参数即可匹配。

4)请求头数据中指定参数名!=值
@RequestMapping(value="/header/test4", headers=“Accept!=text/html”)
表示请求的URL必须为"/header/test4"且请求头中必须有Accept参数,但是值不等于text/html即可
例如:
@RequestMapping(value="/test1",headers=“Content-Type!=application/json”)
表示请求头信息中要么不出现Content-Type属性,如果出现了那么它的值一定不能等于application/json

5)组合使用是"且"的关系
@RequestMapping(value="/header/test5", headers={“Accept!=text/html”, “abc=123”}):
表示请求的URL必须为"/header/test5"且请求头中必须有"Accept"参数但值不等于"text/html"且请求中必须有参数"abc=123"即可匹配。

6)consumes属性和produces属性
consumes 指定处理请求的提交内容类型(消费)
@RequestMapping(value="/test",consumes=“application/json”)
方法仅处理请求中,Content-Type为"application/json"的情况
produces 指定返回的内容类型(生产)
@RequestMapping(value= “/test”, produces=“application/json”)
表示该功能处理方法将产生json格式的数据,此时根据请求头中的Accept进行匹配,如请求头"Accept=application/json"时即可匹配;

例如:
   	@RequestMapping(value="test6",consumes="application/json")
   	public String test6(){
   		System.out.println("test6...");
   		return "test";
   	}

   	@RequestMapping(value="test7",produces="application/json")
   	public String test7(){
   		System.out.println("test7...");
   		return "test";
   	}
测试类中的main函数代码:
此处我们使用Spring提供的Http客户端API创建了请求并设置了请求的Content-Type和编码并在响应体中写回了json数据
	public static void main(String[] args) {

   		try {
   			String url = "http://127.0.0.1:8989/XXX/XXX";
   			//创建HttpRequest
   			ClientHttpRequest request =
   			new SimpleClientHttpRequestFactory().
   			createRequest(new URI(url), HttpMethod.POST);
   			//设置请求头的内容类型头和内容编码
   			//request.getHeaders().set("Content-Type", "application/json;charset=UTF-8");
   			request.getHeaders().set("Accept", "application/json");
   			//写出请求内容体
   			String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}";
   			request.getBody().write(jsonData.getBytes("UTF-8"));
   			//发送请求并得到响应
   			ClientHttpResponse response = request.execute();
   			System.out.println(response.getStatusCode());
   			System.out.println(response.getHeaders());
   		} catch (Exception e) {
   			e.printStackTrace();
   		}
   	}

注意:在上面代码中,如果想获得响应正文中的数据,可以编写一下代码:
//得到响应体的编码方式
Charset charset = response.getHeaders().getContentType().getCharSet();
//得到响应体的内容
InputStream is = response.getBody();
byte bytes[] = new byte[(int)response.getHeaders().getContentLength()];
is.read(bytes);
String data = new String(bytes, charset);
System.out.println(“charset=”+charset);
System.out.println("data : " + data);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值