第二部分 注解
1.@Controller:
@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。
但是单单使用@Controller 标记在一个类上还不能真正意义上的说它就SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。
这个时候有两种方式可以把MyController 交给Spring 管理,好让它能够识别我们标记的@Controller 。
第一种方式是在SpringMVC 的配置文件中定义MyController 的bean 对象。
<bean class="com.host.app.web.controller.MyController"/>
第二种方式是在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。
< context:component-scan base-package = "com.host.app.web.controller" >
< context:exclude-filter type = "annotation" expression = "org.springframework.stereotype.Service" />
</ context:component-scan >
2.@RequestMapping
- SpringMVC使用@RequestMapping注解为控制器指定可以处理哪些URL请求
在控制器的类定义与方法定义处都可标注 - @RequestMapping
-类定义处:提供初步的请求映射信息。相对于WEB应用根目录
-方法处:提供进一步的细分映射信息。相对于类定义的URL。若类定义处未标注@RequestMapping,则方法处标记的URL相对于WEB根目录 - DispatherServlet截获请求后,就通过控制器上@RequestMapping提供的映射信息确定请求所对应的处理方法
映射请求参数、请求方法或请求头
映射请求参数、请求方法或请求头.png- method 可以用来定义请求的方式
- params 和 headers 可以用来发送更加精确的映射请求。params 和 headers 支持简单的表达式
@RequestMapping(value="/testMethod",method = RequestMethod.POST)
public String testMethod() {
System.out.println("testMethod");
return SUCCESS;
}
/*
* 了解:可以使用 params 和 headers 来更加精确的映射请求。params 和 headers 支持简单的表达式
* */
@RequestMapping(value="/testParamsAndHeader",params = {"username","age!=10"},headers = {})
public String testParamsAndHeader() {
System.out.println("testParamsAndHeader");
return SUCCESS;
}
@RequestMapping还支持Ant格式通配符
Ant格式通配符.png3.PathVariable
映射URL绑定的占位符
映射URL绑定的占位符.png
@PathVariable 用例:
/*
* @PathVariable 可以来映射URL中的占位符到目标方法的参数中
* @param id
* */
@RequestMapping("/testPathVariable")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("testPathVariable: " + id);
return SUCCESS;
}
4.@RequestParam
使用@RequestParam绑定请求参数。
- 在处理方法入参处使用@RequestParam可以把请求参数传递给请求方法
-value:参数名
-required:是否必须。默认为true,表示请求参数中必须包含对应的参数,若不存在,将抛出异常
测试用例:
SpringMVCTest.java中添加。
/*
* @RequestParam
* -value:参值即请求参数的数名
* -required:是否必须。默认为true,表示请求参数中必须包含对应的参数,若不存在,将抛出异常
* -defaultValue:请求参数的默认值
* */
@RequestMapping(value = "/testRequestParam")
public String testRequestParam(@RequestParam(value = "username") String username,
// 此处 age 如果是 int 型变量,就必须设置 defaultValue="0"
@RequestParam(value = "age",required = false) Integer age) {
System.out.println("testRequestParam,uaername: " + username + " age:" + age);
return SUCCESS;
}
-----------------------------------------------------------------
index.jsp:
<a href="springmvc/testRequestParam?username=myName&age=19">Test Rest GET</a><br>
5.@RequestHeader
绑定请求头的属性值
- 请求头包含了若干个属性,服务器可根据此获知客户端的信息,通过@RequestHeader即可将请求头中的属性值绑定到处理方法的入参中
用例:
/*
* 映射请求头信息
* 用法同@RequestParam
* */
@RequestMapping(value = "/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "User-Agent") String ua) {
System.out.println("testRequestHeader,User-Agent: " + ua);
return SUCCESS;
}
------------------------------------------------------------------
index.jsp:
<a href="springmvc/testRequestHeader">testRequestHeader</a><br>
6.@SessionAttributes
HttpSession.png如果希望在多个请求之间共享某个模型属性数据(学习笔记3中会讲到),则可以在控制类上标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂存到HttpSession中
示例:
SpringMVCTest.java 添加:
注意(***): 在 SpringMVCTest 类的上面添加:
@SessionAttributes(value = {"user"},types = {String.class})
/*
* @SessionAttributes除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
* 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
* 注意:该注解只能使用在类的上面,为不能修饰方法
* */
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Map<String,Object> map) {
User user = new User("Tom","123456","tom@qq.com",15);
map.put("user",user);
map.put("school","xztywss");
return SUCCESS;
}
index.jsp添加:
<a href="springmvc/testSessionAttributes">Test SessionAttributes</a><br>
success.jsp添加:
request user: ${requestScope.user } <br><br>
session user: ${sessionScope.user } <br><br>
request school: ${requestScope.school } <br><br>
session school: ${sessionScope.school } <br><br>
7.ModelAttribute
- 先上示例:
User.java添加属性(getter、setter、toString相应的改变(此处改变后不包括Address属性)):
private Integer id;
注意:请添加一个不包含Address但是包含id的构造方法,同时应该有一个空的构造方法,不然有可能会出错。
SpringMVCTest.java添加:
/*
* 有 @ModelAttribute 标记的方法会在每个目标方法被调用之前被 SpringMVC 调用!
* */
@ModelAttribute
public void getUser(@RequestParam(value = "id",required = false) Integer id,
Map<String,Object> map) {
if(id != null) {
//模拟从数据库中获取对象
User user = new User(1,"Tom","123456","tom@qq.com",12);
System.out.println("从数据库中获取一个对象: " + user);
map.put("user",user);
}
}
@RequestMapping(value = "/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("修改: " + user);
return SUCCESS;
}
index.jsp 添加:
<!--
模拟修改操作
1.原始数据:1,Tome,123456,tom@qq.com,12
2.密码不能被修改
3.表单回显,模拟操作直接在表单填写对应的属性值
-->
<form action="springmvc/testModelAttribute" method="post">
<input type="hidden" name="id" value="1">
username: <input type="text" name="username" value="Tom"/>
<br>
email: <input type="text" name="email" value="tom@qq.com"/>
<br>
age: <input type="text" name="age" value="12"/>
<br>
<input type="submit" value="Submit">
</form>
- 输出:
不包含@ModelAttribute注解的getUser()方法时的运行结果:
修改: User{id=1, username='Tom', password='null', email='tom@qq.com', age=123}
包含@ModelAttribute注解的getUser()方法时的运行结果:
从数据库中获取一个对象: User{id=1, username='Tom', password='123456', email='tom@qq.com', age=12}
修改: User{id=1, username='Tom', password='123456', email='tom@qq.com', age=13}
注:主要区别在于password回显上的区别
- 分析
/*
* 运行流程:
* 1.执行 @ModelAttribute 注释修饰的方法:从数据库中取出对象,把对象放入 Map 中。键为:user
* 2.SpringMVC 从 Map 中取出 User 对象,并把表单的请求参数赋给 User 对象的对应属性。
* 3.SpringMVC 把上述对象传入目标方法的参数
*
* 注意:在 @ModelAttribute 修饰的方法中,放入到 Map 时的键需要和目标方法入参类型的第一个字母小写的字符串一致
* */
SpringMVC 确定目标方法 POJO 对象类型入参的过程
1.确定一个 key:
1).若目标方法的 POJO 类型的参数没有使用@ModelAttribute 作为修饰,则 key 为 POJO 类名的第一个字母小写
2).若使用了 @ModelAttribute 注解,则 key 为 @ModelAttribute 注解的 value 值
2.在 implicitModel 中查找 key 对应的对象,若存在,则作为入参传入
1).若在 @ModelAttribute 标记的方法中在 Map 中保存过,且 key 和 1 确定的 key 一致,则会获取到
3.若 implicitModel 中不存在 key 对应的对象,则检查当前 Handler 是否使用 @SessionAttributes 注解修饰,
若使用了该注解,且 @SessionAttributes 注解的 value 属性值中包含了 key,则会从 HttpSession中获取 key 所
对应的 value值,若存在则直接传入到目标方法的入参中。若不存在则抛出异常。
4.若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key ,则会
通过反射来创建 POJO 类型的参数,传入为目标方法的参数
5.SpringMVC 会把 key 和 POJO类型的对象保存到 implicitModel 中,进而会保存到 request 中。
网友评论