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