天天看点

微服务[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");

继续阅读