控制器方法可以有任意数量的不同类型大的参数。Spring 中参数的数目和类型都非常灵活。最简单的方法可以不含参数,而复杂的方法可以有几十个参数甚至更多。Spring可以理解这些参数的目的,并在调用这些参数时提供正确的值。另外,可以通过一些配置扩展Spring理解的参数类型。
1、标准Servlet类型
在需要的时候,Spring可以为方法提供Servlet API相关的众多参数类型作为参数。传入到这些参数的值永远不会是null,Spring将保证这一点。方法中可以指定一个、任意数目或者所有下面这些参数类型:
HttpServletRequest 用于操作请求属性
HttpServletResponse 用于操作响应
HttpSession 用于操作HTTP会话对象
InputStream 或者Reader 用于读取请求正文,但不能同时使用两者。在完成对它的处理后部应该关闭该对象
OutputStream 或者Writer 用于编写响应正文,但不能同时使用两者。在完成对它的处理后部应该关闭该对象
2、注解请求属性
可以使用几个参数注解表示方法参数的值应该从请求的某些属性中获取。在大多数情况下,标志这些注解之一的参数可以是任意的原始类型或者原始封装类型。
@RequestParam注解表示被注解的方法参数应该派生自命名参数。默认情况下,该注解表示请求参数是必需的,如果没有它,请求映射就无法完成。可以将required特性设置为false,禁止该行为(使请求参数变为可选的),此时如果请求中未包含请求参数,那么方法参数值将为null
例如:
@RequestMapping("user")
public String user(@RequestParam("id") long userId,
@RequestParam(value="name",required=false) String name,
@RequestParam(value="key",defaultValue="") String key)
{... }
该方法将接受一个必须的id请求参数、一个可选的name请求参数(默认为null)和一个可选的key请求参数(默认为空白),请求参数名称严格区分大小写!
如果希望请求参数有多个指,那么可以将响应方法的参数修改为正确类型的数组或集合。
@RequestHeader的工作方式与@RequestParam相同,它提供了对请求头的值的访问,与@RequestParam不同的是,头名称不区分大小写。使用方法与@RequestParam类似,不做过多阐述。
@PathVariable需配合URL模板使用,能够将URL模板中的变量用作方法参数的值
需要说明的是,Spring中URL映射不必是静态的,可以包含一个模板,表示URL的某部分是可变的,它的值将在运行时决定
例如
@RequestMapping(value = "user/edit/{userId}", method = RequestMethod.GET)
public String editUser( @PathVariable("userId") long userId)
{... }
3、输入绑定表单对象(最常用的东西)
尽管@RequestParam是一个有价值的工具,但是当方法中使用数十个参数是非常繁杂的。Spring允许指定一个表单对象作为控制器方法参数。表单对象是含有设置和读取方法的简单POJO。
例如:
public class UserForm
{
private String username;
private String name;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
@RequestMapping(value = "user/add", method = RequestMethod.POST)
public View createUser(UserForm form)
{
User user = new User();
user.setUserId(this.getNextUserId());
user.setUsername(form.getUsername());
user.setName(form.getName());
this.userDatabase.put(user.getUserId(), user);
return new RedirectView("/user/list", true, false);
}
运行原理:spring将在UserForm类中寻找方法名以set开头的方法,然后它将使用参数名称把请求参数映射到表单属性。如果请求参数不匹配表单对象的任意一个属性,它将被忽略。同样的,如果表单对象的属性不满足请求参数,它们也将被忽略。已注册的PropertyEditor和Converter将把基于字符串的请求参数值转换为它们的目标属性类型。
4、请求正文转换和实体
在POST和PUT请求可能包含了一个JSON或XML格式的请求正文,用于代表比x-www-from-urlencoded更复杂的输几局。请求正文也可以包括二进制、base64编码数据或者几乎所有客户端和服务器都可以理解的格式。当该数据代表某种对象时,它通常被引用为请求实体或者HTTP实体。通过使用@RequestBody注解,Spring将自动把一个请求实体转换为控制器方法参数。
例如:
public class UserForm
{
private String username;
private String name;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
@RequestMapping("userForm")
public class UserFormController{
@RequestMapping("update")
public String update(@RequestBody UserForm userForm){...}
}
默认情况下,@RequestBody参数是必需的,但我们可以设置required特性使它们变成可选的。Spirng 的HTTP消息转换器将自动对请求实体进行转换。请求实体必须使用特殊的消息转换器,该转换器必须可以理解源格式(JSON\XML\二进制等)和目标格式(POJO或者其他复杂对象)
5、文件上传
在浏览器环境中,几乎总是使用一个multipart请求用于上传文件,并结合使用一个正常的表单数据。在这种情况下,请求的Content-Type为multipart/form-data,并且包含了被提交的每个表单字段的一部分。如果表单字段是一个用于处理单个文件的文件类型字段,那么它的每个部分都有一个匹配文件MIME类型的Content-Type和文件内容(如果需要的话可以使用二进制编码),如果表单字段是一个用于多文件的文件类型字段,那么它的每个部分都有一个值为multipart/mixed的Content-Type,并且包含了它自己的那一部分内容,它们各存储了一个文件
使用@RequestPart注解可以标注在任意的控制器方法参数上,该参数应该来自一个multiparty请求的一部分,并且应该被HTTP消息转换器转换。它也有一个required特性
例如:
@RequestMapping("form/upload")
public String upload(@RequestParam("username") String username
@RequestPart("upload") Part upload){...}
如果是多文件上传,那么简单地使用Part或MultipartFile的数组或集合即可
@RequestMapping("form/upload")
public String upload(@RequestParam("username") String username
@RequestPart("uploads") List<MultipartFile> uploads){...}
实现文件上传不一定要使用multipart文件上传作为控制器方法参数,也可以使用表单对象包含Part或MultipartFile字段。Spring将自动自动它必须从文件部分中获值,再对数据进行正确的转换。
例如:
public class Form
{
private String subject;
private String body;
private List<MultipartFile> attachments;
public String getSubject()
{
return subject;
}
public void setSubject(String subject)
{
this.subject = subject;
}
public String getBody()
{
return body;
}
public void setBody(String body)
{
this.body = body;
}
public List<MultipartFile> getAttachments()
{
return attachments;
}
public void setAttachments(List<MultipartFile> attachments)
{
this.attachments = attachments;
}
}
@RequestMapping("form/upload")
public String update(Form form){...}
}