SpringMVC(Spring4)——引數註解
1.請求處理方法簽名:
SpringMVC通過分析處理方法的簽名,將HTTP請求資訊繫結到處理方法的相應入參中。
SpringMVC對控制器處理方法簽名的限制很寬鬆。
必要時可以對方法及方法入參相應的註解(@PathVariable、@RequestParam、@RequestHeader等)SpringMVC框架會將HTTP請求的資訊繫結到相應的方法入參中,並根據方法的返回值型別做出相應的後續處理。
1.1 @RequestParam:
在處理方法入參處使用RequestParam可以把請求引數傳遞給請求方法:
value:引數名;
required:是否必須。預設為true。
@RequestMapping(value = "/testRequestParam") public String testRequestParam( @RequestParam(value = "username") String un, @RequestParam(value = "age", required = false, defaultValue = "0") int age) { System.out.println("testRequestParam, username: " + un + ", age: " + age); return SUCCESS; }
1.2 @RequestHeader:
請求頭包含了若干個屬性,伺服器可以根據此獲知客戶端的資訊。
@RequestMapping("/testRequestHeader")
public String testRequestHeader(
@RequestHeader(value = "Accept-Language") String al) {
System.out.println("testRequestHeader, Accept-Language: " + al);
return SUCCESS;
}
1.3 @CookieValue:
@CookieValue可以讓處理方法入參繫結某個Cookie值。
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("testCookieValue: sessionId: " + sessionId);
return SUCCESS;
}
1.4 POJO作為引數:
Spring MVC會按請求引數名和POJO屬性名進行自動匹配,自動為物件填充屬性值。支援級聯屬性。
package com.atguigu.springmvc.entities;
public class User {
private Integer id;
private String username;
private String password;
private String email;
private int age;
private Address address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
// @Override
// public String toString() {
// return "User [username=" + username + ", password=" + password
// + ", email=" + email + ", age=" + age + ", address=" + address
// + "]";
// }
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password="
+ password + ", email=" + email + ", age=" + age + "]";
}
public User(String username, String password, String email, int age) {
super();
this.username = username;
this.password = password;
this.email = email;
this.age = age;
}
public User(Integer id, String username, String password, String email,
int age) {
super();
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.age = age;
}
public User() {}
}
package com.atguigu.springmvc.entities;
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [province=" + province + ", city=" + city + "]";
}
}
@RequestMapping("/testPojo")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return SUCCESS;
}
1.5 Servlet API作為引數:
MVC的Handler方法可以接受的Servlet 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");
// return SUCCESS;
}
2.處理模型資料:
SpringMVC提供了以下幾種途徑輸出模型資料:
ModelAndView:處理方法返回值型別為ModelAndView時,方法體即可通過該物件新增模型資料。
Map及Model:入參為org.springframework.ui.Model、org.springframework.ui. ModelMap或java.uti.Map時,處理方法返回時,Map中的資料會自動新增到模型中。
@SessionAttributes:將模型中的某個屬性暫存到HttpSession中,已便多個請求之間可以共享這個屬性。
@ModelAttribute:方法入參標註該註解之後,入參的物件就會放到資料模型中。
2.1 ModelAndView:
控制器處理方法的返回值如果位ModelAndView,則其既包含檢視資訊又包含模型資料資訊。
新增模型資料:
– MoelAndView addObject(String attributeName, Object attributeValue)
– ModelAndView addAllObject(Map<String, ?> modelMap)
設定檢視:
– void setView(View view)
– void setViewName(String viewName)
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView(viewName);
modelAndView.addObject("time", new Date());
return modelAndView;
}
2.2 Map及Model:
Spring MVC在內部使用了一個org.springframework.ui.Model介面儲存模型資料。
具體步驟:
SpringMVC在呼叫方法之前會建立一個隱含的模型物件作為模型資料的儲存容器;
如果方法中的入參為Map或者Model型別,SpringMVC會將隱含模型的引用傳遞給這些入。
在方法體內,開發者可以通過這個入參物件訪問到模型中的所有資料,也可以向模型中新增新的屬性資料。
@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;
}
2.3 @SessionAttributes:
若希望在多個請求之間共用某個模型屬性資料,則可以在控制器上標註一個@SessionAttributes,SpringMVC將在模型中對應的屬性暫存到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})
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Map<String, Object> map){
User user = new User("Tom", "123456", "[email protected]", 15);
map.put("user", user);
map.put("school", "atguigu");
return SUCCESS;
}
}
2.4 @ModelAttribute:
在只需要修改資料庫部分欄位的原始操作:
改進後:
這就是SpringMVC的@ModelAttribute註解的作用。
在方法定義上使用@ModelAttribute註解:SpringMVC在呼叫目標處理方法前,會先逐個呼叫在方法級上標註了@ModelAttribute的方法。
在方法的入參前使用@ModelAttribute註解:
-可以從隱含物件中獲取隱含的模型資料中獲取物件,再將請求引數繫結到物件中,再傳入入參。
-將方法入參物件新增到模型中。
<!--
模擬修改操作
1. 原始資料為: 1, Tom, 123456,[email protected],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="[email protected]"/>
<br>
age: <input type="text" name="age" value="12"/>
<br>
<input type="submit" value="Submit"/>
</form>
//上面圖一的情況
//可以通過@ModelAttribute("user")獲取user也可以不使用
//若@ModelAttribute("user")不能獲取,則會從@SessionAttributes獲取
//若@SessionAttributes也沒有,則會丟擲異常,前提是有@SessionAttributes註解
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("user")User user){
System.out.println("修改: " + user);
return SUCCESS;
}
//加上下面的方法之後就是圖二的情況
//但是這個方法會在所有方法呼叫之前都呼叫一下
//在執行這個方法時,會把表單的資料賦給這個物件的對應資料
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map<String, Object> map){
System.out.println("modelAttribute method");
if(id != null){
//模擬從資料庫中獲取物件
User user = new User(1, "Tom", "123456", "[email protected]", 12);
System.out.println("從資料庫中獲取的物件: " + user);
map.put("user", user);
}
}