标签:
每个请求处理方法可以有多个不同的参数,以及一个多种类型的返回结果。
如果在请求处理方法中需要访问HttpSession对象,则可以添加HttpSession作为参数,Spring会将对象正确的传递给方法,如:publish String action(HttpSession session);若需要访问客户端语言环境和HttpServletRequest对象,则可以在方法签名上包含这样的参数,如:public String action(HttpServletRequest request,Locale locale)。可以在请求中出现的参数类型有:
org.springframework.web.context.request.WebRequest
org.springframework.web.context.request.NativeWebRequest
java.util.Locale 当前请求的语言环境
java.util.TimeZone 时区
java.io.InputStream或java.io.Reader
java.io.OutputStream或java.io.Writer
org.springframework.http.HttpMethod
java.security.Principal
HttpEntity <?>参数用于访问Servlet的HTTP请求的标题和内容
java.util.Map / org.springframework.ui.Model / org.springframework.ui.ModelMap 视图隐含模型
org.springframework.web.servlet.mvc.support.RedirectAttributes 重定向
命令或表单对象
基本数据类型,如int,String,double...
复杂数据类型,如自定义的POJO对象
HandlerAdapter
org.springframework.validation.Errors / org.springframework.validation.BindingResult 验证结果
org.springframework.web.bind.support.SessionStatus 会话状态
org.springframework.web.util.UriComponentsBuilder
@PathVariable 注解参数访问URI模板变量。
@MatrixVariable 注释参数用于访问位于URI路径段键值对对,矩阵变量。
@RequestParam 注解参数访问特定的Servlet请求参数,请求参数绑定。
@RequestHeader 注解参数访问特定的se??rvlet请求HTTP标头,映射请求头。
@RequestBody 注解参数访问HTTP请求主体,注解映射请求体
@RequestPart 注解参数访问“的multipart / form-data的”请求部分的内容。处理客户端上传文件,多部分文件上传的支持
@SessionAttribute 注解参数会话属性
@RequestAttribute 注解参数访问请求属性
方法的参数可以是任意基本数据类型,如果方法参数名与http中请求的参数名称相同时会进行自动映射,视图foo目录下的index.jsp与示例代码如下:
//自动参数映射 @RequestMapping("/action0") public String action0(Model model,int id,String name){ model.addAttribute("message", "name="+name+",id="+id); return "foo/index"; }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Foo</title> </head> <body> ${message} </body> </html>
运行结果如下:
除了基本数据类型,也可以映射复杂的数据类型,如一个自定义的POJO对象,Spring MVC会通过反射把请中的参数设置到对象中,转换类型,示例代码如下:
package com.zhangguo.springmvc03.entities;
import java.io.Serializable;
/**
* 产品
*/
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private double price;
public Product() {
}
public Product(String name, double price) {
super();
this.name = name;
this.price = price;
}
public Product(int id, String name, double price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "编号(id):"+this.getId()+",名称(name):"+this.getName()+",价格(price):"+this.getPrice();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
//自动参数映射 复杂数据类型
@RequestMapping("/action01")
public String action01(Model model,Product product){
model.addAttribute("message", product);
return "foo/index";
}
虽然自动参数映射很方便,但有些细节是不能处理的,如参数是否为必须参数,参数的默认值就没有有办法做到了。如果使用@RequestParam可以实现请求参数绑定,Spring MVC会自动查找请求中的参数转类型并将与参数进行绑定,示例代码如下:
package com.zhangguo.springmvc03.controllers; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller @RequestMapping("/foo") public class FooController { @RequestMapping("/action1") public String action1(Model model,@RequestParam(required=false,defaultValue="99") int id){ model.addAttribute("message", id); return "foo/index"; } }
@RequestParam共有4个注解属性,required属性表示是否为必须,默认值为true,如果请求中没有指定的参数会报异常;defaultValue用于设置参数的默认值,如果不指定值则使用默认值,只能是String类型的。
运行结果:
在一个请求处理方法Action中如果返回结果为“index”字符则表示转发到视图index,有时候我们需要重定向,则可以在返回的结果前加上一个前缀“redirect:”,可以重定向到一个指定的页面也可以是另一个action,示例代码如下:
//重定向 @RequestMapping("/action2") public String action2(Model model){ return "foo/index"; } @RequestMapping("/action3") public String action3(Model model){ model.addAttribute("message", "action3Message"); return "redirect:action2"; }
当请求http://localhost:8087/SpringMVC02/foo/action3时运行结果如下:
在action3中返回的结果为redirect:action2,则表示重定向到action2这个请求处理方法,所有重定向都是以当前路径为起点的,请注意路径。在action3向model中添加了名称message的数据,因为重定向到action2中会发起2次请求,为了保持action3中的数据Spring MVC自动将数据重写到了url中。为了实现重定向时传递复杂数据,可以使用Flash属性,示例代码如下:
//接收重定向参数 @RequestMapping("/action2") public String action2(Model model,Product product){ model.addAttribute("message", product); System.out.println(model.containsAttribute("product")); //true return "foo/index"; } //重定向属性 @RequestMapping("/action3") public String action3(Model model,RedirectAttributes redirectAttributes){ Product product=new Product(2, "iPhone7 Plus", 6989.5); redirectAttributes.addFlashAttribute("product", product); return "redirect:action2"; }
当访问action3时,首先创建了一个product产口对象,将该对象添加到了Flash属性中,在重定向后取出,个人猜测应该暂时将对象存入了Session中。当请求foo/action3时运行结果如下:
url地址已经发生了变化,product对象其实也已经被存入了model中,在action的视图中可以直接拿到。
@ModelAttribute可以应用在方法参数上或方法上,他的作用主要是当注解在方法中时会将注解的参数对象添加到Model中;当注解在请求处理方法Action上时会将该方法变成一个非请求处理的方法,但其它Action被调用时会首先调用该方法。
当注解在参数上时会将被注解的参数添加到Model中,并默认完成自动数据绑定,示例代码如下:
@RequestMapping("/action6") public String action6(Model model,@ModelAttribute(name="product",binding=true) Product entity){ model.addAttribute("message", model.containsAttribute("product")+"<br/>"+entity); return "foo/index"; }
运行结果:
其实不使用@ModelAttribute我也样可以完成参数与对象间的自支映射,但使用注解可以设置更多详细内容,如名称,是否绑定等。
用于标注一个非请求处理方法,通俗说就是一个非Action,普通方法。如果一个控制器类有多个请求处理方法,以及一个有@ModelAttribute注解的方法,则在调用其它Action时会先调用非请求处理的Action,示例代码如下:
@RequestMapping("/action7") public String action7(Model model){ Map<String,Object> map=model.asMap(); for (String key : map.keySet()) { System.out.println(key+":"+map.get(key)); } return "foo/index"; } @ModelAttribute public String noaction(){ System.out.println("noaction 方法被调用!"); String message="来自noaction方法的信息"; return message; }
当访问http://localhost:8087/SpringMVC03/foo/action7时,控制台显示结果如下:
非请求处理方法可以返回void,也可以返回一个任意对象,该对象会被自动添加到每一个要被访问的Action的Model中,key从示例中可以看出为类型名称。
二、Action返回值类型
ModelAndView
Model
Map 包含模型的属性
View
String 视图名称
void
HttpServletResponse
HttpEntity<?>或ResponseEntity<?>
HttpHeaders
Callable<?>
DeferredResult<?>
ListenableFuture<?>
ResponseBodyEmitter
SseEmitter
StreamingResponseBody
其它任意类型,Spring将其视作输出给View的对象模型
新增一个action5,代码如下:
@RequestMapping("/action5") public String action5(Model model){ return "foo/action5"; }
在foo目录下添加视图action5.jsp,内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>action5的视图</title> </head> <body> <img alt="风景" src="../../images/3.jpg"> </body> </html>
目标结构如下:
访问结果:
这里图片访问不到的原因是因为:action5.jsp视图此时并非以它所在的目录为实际路径,他是以当前action所在的控制器为起始目录的,当前控制器的url为:http://localhost:8087/SpringMVC02/foo/,而图片的src为:../../images/3.jpg,向上2级后变成:http://localhost:8087/images/3.jpg,但我们的项目实际路径中并没有存放3.jpg这张图片,解决的办法是在视图中使用“绝对”路径;另外一个问题是我们将静态资源存放到WEB-INF下不太合理,因为该目录禁止客户端访问,修改后的视图如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>action5的视图</title> </head> <body> <img alt="风景" src="<c:url value="/images/3.jpg"></c:url>"> </body> </html>
目录结构变化后如下所示:
运行结果:
小结:主要是借助了标签<c:url value="/images/3.jpg"></c:url>,将路径转换成“绝对路径”;建议在引用外部资源如js、css、图片信息时都使用该标签解析路径。
标签:
原文地址:http://blog.csdn.net/zhangguo5/article/details/51890361