@RequestMapping
開發者需要在控制器内部為每一個請求動作開發相應的處理方法
org.springframework.web.bind.annotation.RequestMapping
注解訓示Spring用哪一個類或方法來處理請求動作,該注解可用于類或方法
- @RequestMapping 注解雖然也包含在 org.springframework.web.bind.annotation裡面,但是嚴格來說,它并不屬于參數綁定注解
- @RequestMapping注解可以用來注釋一個控制器類,在這種情況下,所有方法都将映射為相對于類級别的請求,表示該控制器處理的所有請求都被映射到value屬性所訓示的路徑下
代碼示例
@Controller
@RequestMapping(value="/user")
public class UserController{
@RequestMapping(value="/register")
public String register(){
return "register";
}
@RequestMapping(value="/login")
public String login(){
return "login";
}
}
由于UserController類中添加了value="/user"的@RequestMapping 注解,是以所有相關路徑都要加上"/user",此時方法被映射到如下請求URL:和
http://localhost:8080/user/register
http://localhost:8080/user/login
@RequestMapping注解指定屬性
使用@RequestMapping注解可指定如下表内的屬性
屬性 | 類型 | 是否必要 | 說明 |
---|---|---|---|
value | String[] | 否 | 用于将指定請求的世紀位址映射到方法上 |
name | String | 給映射位址指定一個别名 | |
method | RequestMethod[] | 映射指定請求的方法類型,包括GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE | |
consumes | 指定處理請求的送出内容類型(Content-Type),例如application/json、text/html等 | ||
produces | 指定傳回的内容類型,傳回的内容類型必須是request請求頭(Accept)中所包含的類型 | ||
params | 指定request中必須包含某些參數值時,才讓該方法處理 | ||
headers | 指定request中必須包含某些指定的header值時,才能讓該方法處理請求 | ||
Path | 在Servlet環境中隻有:uri路徑映射(例如“/myPath.do”),也支援如ant的基于路徑模式(例如“/myPath/*,”),在方法層面上隻支援相對路徑(例如“edit.do”) |
- value屬性:@RequestMapping 是一個用來處理請求位址映射的注解,可以使用@RequestMapping 注釋一個方法或類,一個采用@RequestMapping注釋的方法将成為一個請求處理方法
@RequestMapping(value="/davieyang") public ModelAndView davieyang(){ return ...; }
- 該示例使用@RequestMapping注釋的value屬性将URL映射到方法上,在這個例子中,将davieyang映射到davieyang方法上,使用如下URL通路應用時将由davieyang方法進行處理
http://localhost:8080/context/hello
- 由于value屬性是@RequestMapping注釋的預設屬性,是以,如果隻有唯一的屬性,則可以省略屬性名,即如下兩個注解含義相同
@RequestMapping(value="/davieyang")
,但如果有超過一個屬性,就必須寫上value屬性名稱@RequestMapping("/davieyang")
- value屬性的值也可以是一個空字元串,此時該方法被映射到如下請求URL:
http://localhost:8080/context
- 該示例使用@RequestMapping注釋的value屬性将URL映射到方法上,在這個例子中,将davieyang映射到davieyang方法上,使用如下URL通路應用時将由davieyang方法進行處理
- method屬性
該屬性用來訓示該方法僅處理哪些HTTP請求方式
@RequestMapping(value="/davieyang", method=RequestMethod.POST)
代碼method=RequestMethod.POST表示該方法隻支援POST請 求。也可以同時支援多個HTTP請求方式
@RequestMapping(value="/davieyang', method={RequestMethod.POST, RequestMethod.GET})
如果沒有指定method屬性值,則請求處理方法可以處理任意的 HTTP請求方式
Spring4.3之後,新增了@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping 注解,這幾個注解可 以指定的屬性和@RequestMapping注解類似,差別在于@GetMapping注 解隻支援GET方式的請求;@PostMapping注解隻支援POST方式的請 求;@PutMapping、@DeleteMapping、@PatchMapping分别對應PUT請 求、DELETE請求和PATCH請求,使用比較少
- consumes屬性
該屬性指定處理請求的送出内容類型(Content-Type)
@RequestMapping(value="/davieyang", method=RequestMethod.POST, consumes="application/json")
表示方法僅處理request Content-Type為“application/json”類型的請求
- produces屬性
該屬性指定傳回的内容類型,傳回的内容類型必須是 request 請求頭(Accept)中所包含的類型
@RequestMapping(value="/davieyang", method=RequestMethod.POST, produces="application/json")
方法僅處理request請求中Accept頭中包含了"application/json"的請求,同時指明了傳回的内容類型為application/json
- params屬性
該屬性指定request中必須包含某些參數值時,才讓該方法處理
@RequestMapping(value="/davieyang", method=RequestMethod.POST, params="myParam=myValue")
方法僅處理其中名為“myParam、值為“myValue”的請求
- headers屬性
該屬性指定request中必須包含某些指定的header值時,才能讓該方法處理請求
@RequestMapping(value="/davieyang", method=RequestMethod.POST, headers="Referer=http://editor.csdn.net/")
方法僅處理 header 中包含了指定“Referer”請求頭和對應值為“http://editor.csdn.net/”的請求
請求處理方法中可出現的參數類型
每個請求處理方法可以有多個不同類型的參數
- 如果需要通路HttpServletRequest對象,則可以添加HttpServletRequest作為參數,Spring會将對象正确地傳遞給方法
@RequestMapping(value="/davieyang") public String login(HttpServletRequest request){ return "login"; }
- 如果需要通路HttpSession對象,則可以添加HttpSession作為參數, Spring會将對象正确地傳遞給方法
@RequestMapping(value="/login") public String login(HttpSession session){ return "login"; }
下面是可以在請求處理方法中出現的參數類型:
- javax.servlet.ServletRequest或javax.servlet.http.HttpServletRequest
- javax.servlet.ServletResponse或javax.servlet.http.HttpServletResponse
- javax.servlet.http.HttpSession
- org.springframework.web.context.request.WebRequest或org.springframework.web.context.request.NativeWebRequest
- java.util.Locale
- java.io.InputStream或java.io.Reader
- java.io.OutputStream或java.io.Writer
- java.security.Principal
- HttpEntity<?>
- java.util.Map
- org.springframework.ui.Model
- org.springframework.ui.ModelMap
- org.springframework.web.servlet.mvc.support.RedirectAttributes
- org.springframework.validation.Errors
- org.springframework.validation.BindingResult
- org.springframework.web.bind.support.SessionStatus
- org.springframework.web.util.UriComponentsBuilder
- @PathVariable、@MatrixVariable @RequestParam、@RequestHeader、@RequestBody、@RequestPart
其中最重要的是
org.springframework.ui.Model
類型。這不是一個Servlet API類型,而是一個Spring MVC類型,其中包含了Map對象用來存儲資料。如果方法中添加了Model參數,則每次調用請求處理方法時,Spring MVC都會建立Model對象,并将其作為參數傳遞給方法,還要重點說明的一個對象是
org.springframework.web.context.request.WebRequest
,WebRequest是Spring MVC提供的統一請求通路接口,其不僅可以通路請求相關資料,如參數資料、請求頭資料,但通路不到Cookie區資料,而且還可以通路請求作用域和會話作用域中的資料,NativeWebRequest繼承了 WebRequest,并提供通路本地Servlet API的方法
WebRequest中有如下這些重點方法:
- getParameter(String name):根據請求參數名擷取請求參數值,等同于 Servlet API 的request.getParameter(String name)
- getHeader(String name):根據請求頭參數名擷取請求頭參數值,等同于Servlet API的request.getHeader(String name)
- setAttribute(String name,Object value,int scope):儲存資料到指定的作用域,等同于Servlet API的scope(request, session).setAttribute(String name,Object value)方法。參數中的int scope是WebRequest對象中定義的兩個常量SCOPE_REQUEST(請求作用域)、SCOPE_SESSION(會話作用域)
//儲存名稱為username的值到request作用域 webRequest.setAttribute("username", "davieyang", WebRequest.SCOPE_REQUEST); //儲存名稱為bookname的值到request作用域 webRequest.setAttribute("bookname", "基于Python的Selenium自動化測試", WebRequest.SCOPE_SESSION);
- getAttribute(String name,int scope)從指定的作用域中提取資料,等同于Servlet API的scope(request,session).getAttribute(String name)方法
//從request作用域中取出名稱為username的值 webRequest.getAttribute("username", WebRequest.SCOPE_REQUEST); //從session作用域取出名稱為bookname的值 webRequest.getAttribute("bookname", WebRequest.SCOPE_SESSION);
從架構的無侵入性而言,建議使用 WebRequest 對象替代 Servlet API 的HttpServletRequest對象和HttpSession對象
請求處理方法可傳回的類型
每個請求處理方法可以傳回以下類型的傳回結果:
- org.springframework.web.portlet.ModelAndView
- java.util.Map<k,v>
- org.springframework.web.servlet.View
- java.lang.String
- HttpEntity或ResponseEntity
- java.util.concurrent.Callable
- org.springframework.web.context.request.async.DeferredResult
- void
Model和ModelMap
在請求處理方法中可出現和傳回的參數類型中,最重要的就是Model 和 ModelAndView了,對于MVC架構,控制器(Controller)執行業務邏輯,用于産生模型資料(Model),而視圖(View)則用于渲染模型資料
如何将模型資料傳遞給視圖是Spring MVC架構的一項重要工作,Spring MVC提供了多種途徑輸出模型資料,如Model、ModelMap、ModelAndView、@ModelAttribute、@SessionAttributes
Spring MVC在内部使用了一個
org.springframework.ui.Model
接口存儲模型資料,它的功能類似
java.util.Map
接口,但是比Map易于使用
org.springframework.ui.ModelMap
接口實作了Map接口
Spring MVC在調用處理方法之前會建立一個隐含的模型對象,作為模型資料的存儲容器。如果處理方法的參數為Model或ModelMap類型,則Spring MVC會将隐含模型的引用傳遞給這些參數。在處理方法内部, 開發者可以通過這個參數對象通路模型中的所有資料,也可以向模型中 添加新的屬性資料
在處理方法中,Model和ModelMap對象都可以使用
addAttribute (String attributeName,Object attributeValue)
方法添加模型資料
package org.davieyang.domain;
import java.io.Serializable;
// 域對象,實作序列化接口
public class User implements Serializable{
private static final long serialVersionUID = 1L;
// 私有字段
private String loginname;
private String password;
private String username;
// 公共構造器
public User() {
super();
}
public User(String loginname, String password, String username) {
super();
this.loginname = loginname;
this.password = password;
this.username = username;
}
// set/get方法
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [loginname=" + loginname + ", password=" + password
+ ", username=" + username + "]";
}
}
import org.davieyang.domain.User;
import org.springframewwork.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ModelController{
@Requestmapping(value="/modelTest")
public String modelTest(Model model){
System.out.println("modelTest");
User user=new User();
//設定user對象的username屬性
user.setUsername("基于Python的Selenium自動化測試")
//将User對象添加到Model當中
model.addAttribute("user", user);
return "ressult modelTest";
}
@RequestMapping(value="/ModelMapTest")
public String ModelMapTest(ModelMap modelMap){
System.out.println("ModelMapTest");
User user = new User();
user.setUsername("基于Python的Selenium自動化測試");
//将User對象添加到ModelMap中
modelMap.addAttribute("user", user);
return "result ModelMapTest"
}
}
- 在modelTest方法中建立了一個自定義的User對象,并且給username屬性指派,使用Model對象的addAttribute(“user”, user)方法将User對象添加到Model當中,即JSP的requestScope當中
- ModelMapTest方法的代碼功能與此類似,隻是存儲對象由Model改成了ModelMap
ModelAndView
控制器處理方法的傳回值如果是ModelAndView,則其既包含模型 資料資訊,也包含視圖資訊,這樣Spring MVC将使用包含的視圖對模型資料進行渲染。可以簡單地将模型資料看成一個Map<String, Object> 對象
在處理方法中可以使用ModelAndView對象的
addObject(String attributeName, Object attributeValue);
方法添加模型資料:通過
setViewName(String viewName)
方法設定視圖
package org.davieyang.domain;
import java.io.Serializable;
// 域對象,實作序列化接口
public class User implements Serializable{
private static final long serialVersionUID = 1L;
// 私有字段
private String loginname;
private String password;
private String username;
// 公共構造器
public User() {
super();
}
public User(String loginname, String password, String username) {
super();
this.loginname = loginname;
this.password = password;
this.username = username;
}
// set/get方法
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [loginname=" + loginname + ", password=" + password
+ ", username=" + username + "]";
}
}
package org.davieyang.controller;
import org.davieyang.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
// Controller注解用于訓示該類是一個控制器,可以同時處理多個請求動作
@Controller
public class ModelAndViewController{
@RequestMapping(value="/ModelAndViewTest")
public ModelAndView ModelAndViewTest(ModelAndView mv){
System.out.println("ModelAndViewTest");
User user = new User();
// 設定user對象的username屬性
user.setUsername("基于Python的selenium自動化測試");
// 将User對象添加到ModelAndView當中
mv.addObject("user", user);
// 設定要轉發的頁面
mv.setViewName("result");
return mv;
}
}
頁面轉發
轉發到JSP頁面
- 若請求處理方法傳回字元串,預設使用伺服器内部跳轉(forward),示例代碼:
return "main";
- 如果希望用戶端重定向(redirect),在傳回的字元串前面加上"redirect:/",示例代碼:
return "redirect:/main.jsp";
- 若請求處理方法傳回ModelAndView,使用setViewName方法設定轉發的頁面,預設使用伺服器内部跳轉(forward),示例代碼:
mv.setViewName("main");
- 若請求處理方法傳回 ModelAndView,使用 setViewName方法設定轉發的頁面,例如"mv.setViewName(“redirect:/main.jsp”);", 則用戶端重定向到名為main.jsp的頁面,示例代碼
"mv.setViewName("redirect:/main.jsp");
轉發到控制器的請求處理方法
- 若請求處理方法傳回字元串,在傳回的字元串前面加上" forward:/",例如"forward:/main",則伺服器内部跳轉到名為main的請求處理方法,示例代碼:
return "forward:/main";
- 若請求處理方法傳回字元串,在傳回的字元串前面加上" redirect:/",例如"redirect:/main",則用戶端重定向到名為main的請求處理方法,示例代碼:
return "redirect:/main";
- 若請求處理方法傳回ModelAndView,調用setViewName方法設定需要轉發的控制器,例如"mv.setViewName(“forward:/main”);",則伺服器内部跳轉到名為main的請求處理方法,示例代碼:
mv.setViewName("forward:/main");
- 若請求處理方法傳回ModelAndView,調用setViewName方法設定需 要轉發的控制器,例如"mv.setViewName(“redirect:/main”);",則用戶端重定向到名為main的請求處理方法,示例代碼:
mv.setVeiwName("redirect:/main");