HTTP请求
由于SpringMVC是通过HTTP进行访问的,需要了解一些HTTP有关的知识,简单记录一下HTTP请求。
我们知道HTTP是一种无状态的请求—响应协议,大致工作原理如下:
- 客户与服务器建立连接
- 客户向服务器提出请求
- 服务器接受请求,并根据请求返回相应的文件作为应答
- 客户与服务器关闭连接
HTTP请求其实是发送一段符合HTTP协议标准的数据,就是HTTP报文。
HTTP请求报文格式:
请求行 - 【通用信息头 - 请求头 - 实体头】(这三部分一般称为请求头或报文头) - 报文主体
请求行以方法字段开始,后面分别是 URL 字段和 HTTP 协议版本字段,并以 CRLF 结尾。SP 是分隔符。除了在最后的 CRLF 序列中 CF 和 LF 是必需的之外,其他都可以不要。
- 通用头标:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联。
- 请求头标:允许客户端传递关于自身的信息和希望的响应形式。
- 实体头标:定义被传送资源的信息。即可用于请求,也可用于响应。
**
图中的报文头部分就包括了通用信息头、请求头、实体头,还注意到报文头和报文体中间有一个空格,报文体就是我们真实要传输的数据。
HTTP响应报文格式:
响应行- 响应头- 报文主体
响应行由报文协议及版本、状态码及状态描述组成。状态码元由3位数字组成,表示请求是否被理解或被满足。下面图片中的响应头

@RequestMapping
请求映射
在总结一中的HelloWorld程序中使用了@RequestMapping注解来映射请求。

在helloworld中可以看到使用请求URL映射请求,还可以用请求方法、请求参数和请求头映射请求。
@RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条 件,他们之间是与的关系,联合使用多个条件可让请求映射 更加精确化,@RequestMapping如果不指定参数,默认就是使用value即URL映射方式。
params 和 headers支持简单的表达式:
- param1: 表示请求必须包含名为 param1 的请求参数
- !param1: 表示请求不能包含名为 param1 的请求参数
- param1 != value1: 表示请求包含名为 param1 的请求参数,但其值不能为 value1
- {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
@RequestMapping(
value = "testParamsAndHeaders",
params = { "username", "age!=10" },
headers = {"Accept-Language=zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-CN;q=0.3,en;q=0.2" })
@RequestMapping支持 Ant 风格的 URL。
Ant 风格资源地址支持 3 种匹配符:
- ?:匹配文件名中的一个字符
- *:匹配文件名中的任意个数字符
- **:匹配多层路径
/user/*/createUser: 匹配 – /user/aaa/createUser、/user/bbb/createUser 等 URL
/user/**/createUser: 匹配 – /user/createUser、/user/aaa/bbb/createUser 等 URL
/user/createUser??: 匹配 – /user/createUseraa、/user/createUserbb 等 UR、
@RequestMapping 除了修饰方法, 还可来修饰类
- 类定义处: 提供初步的请求映射信息。相对于 WEB 应用的根目录
- 方法处: 提供进一步的细分映射信息。 相对于类定义处的 URL。若类定义处未标注 @RequestMapping,则方法处标记的 URL相对于 WEB 应用的根目录
参数映射
使用 @PathVariable 、@RequestParam、@RequestHeader 等注解,Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参 中。
@PathVariable 映射 URL 绑定的占位符:
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable(“xxx”) 绑定到操作方法的入参中。
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("SpringMVCTest.testPathVariable:" + id);
return SUCCESS;
}
@RequestParam 绑定请求参数值:
该注解有三个属性:
- value:参数名
- required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
- defaultValue: 如果URL中没有该请求参数时,赋值给变量的值
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(value = "username") String un,
@RequestParam(value = "age", required = false, defaultValue = "0") int age) {
System.out.println("SpringMVCTest.testRequestParam:username=" + un + ",age=" + age);
return SUCCESS;
}
@RequestHeader 绑定请求报头的属性值:
请求头包含了若干个属性,服务器可据此获知客户端的信•息,通过 @RequestHeader 即可将请求头中的属性值绑 定到处理方法的入参中。属性同 @RequestParam。
@RequestMapping("/testRequestHeader")
private String testRequestHeader(@RequestHeader(value = "Accept-Language") String al) {
System.out.println("SpringMVCTest.testRequestHeader,Accept-Language:" + al);
return SUCCESS;
}
使用 @CookieValue 绑定请求中的 Cookie 值:
@CookieValue 可让处理方法入参绑定某个 Cookie 。属性同 @RequestParam。
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("testCookieValue: sessionId: " + sessionId);
return SUCCESS;
}
使用 POJO(Plain Ordinary Java Object,简单的Java对象,实际就是普通对象,一般指没有业务逻辑方法的对象)绑定请求参数值:
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹 配,自动为该对象填充属性值。支持级联属性。 如:dept.deptId、dept.address.tel
@RequestMapping("/testPojo")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return SUCCESS;
}
使用 Servlet API 作为入参
可以使用 Serlvet 原生的 API 作为目标方法的参数 具体支持以下类型
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Locale InputStream
- OutputStream
- Reader
- Writer
@RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request,
HttpServletResponse response, Writer out) throws IOException {
System.out.println("testServletAPI, " + request + ", " + response);
out.write("hello springmvc");
}
模型处理
所谓模型数据我理解的就是含有@RequestMapping的方法的返回值就是个模型,这个模型包含了视图信息和数据信息。在进行视图解析和渲染的时候要使用的数据就是模型数据。
Spring MVC 提供了以下几种途径输出模型数据:
- ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
- 添加模型数据
MoelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObject(Map<String, ?> modelMap)– - 设置视图:
void setView(View view)
void setViewName(String viewName)j
控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView(viewName);
//添加模型数据到 ModelAndView 中.
modelAndView.addObject("time", new Date());
return modelAndView;
}
- Map 及 Model: 入参为org.springframework.ui.Model、org.springframework.ui. ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
- Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存储模型数据
具体步骤:
Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
如果方法的入参为 Map 或 Model 类型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据.
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("Tom", "Jerry", "Mike"));
return SUCCESS;
}
- @SessionAttributes: 将模型中的某个属性暂存到 HttpSession 中,以便多个请求之间可以共享这个属性 , 注意: 该注解只能放在类的上面. 而不能修饰放方法.
- 若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。
- @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中
— @SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。
— @SessionAttributes(value={“user1”, “user2”})
— @SessionAttributes(types={User.class, Dept.class})
— @SessionAttributes(value={“user1”, “user2”}, types={Dept.class}
@SessionAttributes(value={"user"}, types={String.class})注意这个注解是加在类上的
我是为了记录所以才剪切了过来。
public String testSessionAttributes(Map<String, Object> map){
User user = new User("Tom", "123456", "tom@atguigu.com", 15);
map.put("user", user);
map.put("school", "atguigu");
return SUCCESS;
}
- @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型
这个使用方法太多,放在本文章中过于冗余,我会单独写一篇文章记录——@ModelAttritbute的用法,还有上面提到了Controller类的方法返回为String、Model、Map等类型的时候的情况,在这篇文章中我也会记录一下关于Controller类的各种返回值的不同处理方式。
最后来谈一下关于@SessionAttributes引发的异常的问题。
如果在处理类定义处标注了 @SessionAttributes(“xxx”),则会尝试从会话中获取该属性,并将其赋给该入参,然后再用请求消息填充该入参对象。如果在会话中找不到对应的属 性,则抛出 HttpSessionRequiredException 异常.
一般用@ModelAttribute注解来向隐含模型中添加一个@SessionAttribute所要获取的对象来避免此异常的发生。

5587

被折叠的 条评论
为什么被折叠?



