目录
一、常用注解
RequestMapping
SpringMVC使用@RequestMapping注解为控制器指定可以处理哪些URL请求,可以标注在类上和方法上,表示多级路径请求,标注在类上可以为当前类所有方法的请求地址指定一个基准路径
1.RequestMapping的属性
- value:url路径
- method:限定请求方式,常用GET、POST,默认为HTTP协议中的所有请求方式
- params:规定请求参数
- headers:规定请求头(浏览器)
- consumes:规定请求头中的Content-Type
- produces:给响应头中加上Content-Type
2.url中的通配符
- ?:代表一个字符
- *:代表任意多个字符和一层路径
- **:代表多层路径
RequestParam
获取请求参数,默认必须带参数
注意@RequestParam与@PathVariable有区别,其中一个是获取路径传的参数,一个是获取路径中占位符的值
- value:指定要获取的参数的key
- required:这个参数是否是必须的
- defaultValue:默认值,默认是null
RequestHeader
获取请求头中某个key的值,如果请求头中没有这个值会报错
- value:指定要获取的参数的key
- required:这个参数是否是必须的
- defaultValue:默认值,默认是null
CookieValue
获取请求头中cookie的值
- value:指定要获取的参数的key
- required:这个参数是否是必须的
- defaultValue:默认值,默认是null
二、POJO
如果我们的请求参数是一个POJO对象,Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值,支持级联属性,请求参数名和对象属性名需要一一对应。
例如:在jsp的表单中发起请求
<form action="/hi/book" method="post">
书名<input type="text" name="bookName"><br>
作者<input type="text" name="author"><br>
价格<input type="text" name="price"><br>
库存<input type="text" name="stock"><br>
街道<input type="text" name="address.street"><br>
市<input type="text" name="address.city"><br>
<input type="submit">
</form>
定义实体类,表单数据封装的对象
class Book {
private String bookName;
private String author;
private Double price;
private Integer stock;
private Address address;
}
class Address {
private String street;
private String city;
}
在方法中可以自动封装到类中
@RequestMapping("/book")
public String addBook(Book book){
System.out.println("我要保存的图书"+book);
return "say";
}
三、提交数据乱码问题
- GET请求:在server.xml的8080端口处加上URIEncoding=“UTF-8”
- POST请求、响应乱码:
SpringMVC提供了字符编码filter,在web.xml里的其他filter之前加上以下代码,可以解决POST请求和响应乱码
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四、数据传给页面
- 可以在方法处传入Model、Map、ModelMap参数中,给这些参数里保存的数据都会放在请求域中,可以在页面获取。例如:
@RequestMapping(value = "/model")
public String handleModel(Model model){
model.addAttribute("msg","你好坏");
System.out.println(model.getClass());
return "say";
}
@RequestMapping(value = "/map")
public String handleMap(Map<String,Object> map){
map.put("msg","你好");
System.out.println(map.getClass());
return "say";
}
@RequestMapping(value = "/modelmap")
public String handleModelMap(ModelMap modelMap){
modelMap.addAttribute("msg","你好棒");
System.out.println(modelMap.getClass());
return "say";
}
在跳转的页面中可以通过requestScope获取
request:${requestScope.msg}
以上三种类型最终都转换为BindingAwareModelMap实现
- 方法返回值使用ModelAndView类型,既包含视图信息(页面地址),也包含模型数据(给页面携带的数据),数据放在请求域requestScope中,例如:
@RequestMapping(value = "/view")
public ModelAndView handleModelMap(){
ModelAndView mv = new ModelAndView("say");
mv.addObject("msg","你好哈哈哈");
return mv;
}
五、源码分析
- 1.DispatcherServer收到所有请求
- 2.调用doDispatch()方法进行处理
- getHandler():根据当前请求在HandlerMapping中找到能处理这个请求的目标处理器类
- 细节:HandlerMapping保存了每一个处理器能处理哪些请求的映射信息,IOC容器创建Controller对象的时候扫描每个处理器都能处理的请求,保存在HandlerMapping的HandlerMap属性中,下一次请求过来,就看哪个HandlerMapping中有这个请求映射
- getHandlerAdapter():根据当前处理器类获取能执行这个处理器方法的适配器
- 使用获得的适配器执行目标方法
- 目标方法执行后会返回一个ModelAndView对象
- 根据ModelAndView的信息转发到具体的页面,并可以在请求域中取出ModelAndView中的模型数据
- getHandler():根据当前请求在HandlerMapping中找到能处理这个请求的目标处理器类
- 3.调用doDispatch()方法进行处理