天天看點

微服務[v1.0.0][Spring MVC常用注解之@RequestMapping]

@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")

      @RequestMapping("/davieyang")

      ,但如果有超過一個屬性,就必須寫上value屬性名稱
    • value屬性的值也可以是一個空字元串,此時該方法被映射到如下請求URL:

      http://localhost:8080/context

  • 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");

繼續閱讀