SpringMvc之@RequestParam详解
@RequestParam是传递参数的.
@RequestParam⽤于将请求参数区数据映射到功能处理⽅法的参数上。
public String queryUserName(@RequestParam String userName)
在url中输⼊:localhost:8080/**/?userName=zhangsan
请求中包含username参数(如/requestparam1?userName=zhang),则⾃动传⼊。
接下来我们看⼀下@RequestParam注解主要有哪些参数:
value:参数名字,即⼊参的请求参数名字,如username表⽰请求的参数区中的名字为username的参数的值将传⼊;
required:是否必须,默认是true,表⽰请求中⼀定要有相应的参数,否则将报404错误码;
defaultValue:默认值,表⽰如果请求中没有同名参数时的默认值,默认值可以是SpEL表达式,如“#{systemProperties['java.vm.version']}”。
表⽰请求中可以没有名字为username的参数,如果没有默认为null,此处需要注意如下⼏点:
public String queryUserName(@RequestParam(value="userName" ,required =false ) String userName)
原⼦类型:必须有值,否则抛出异常,如果允许空值请使⽤包装类代替。
Boolean包装类型类型:默认Boolean.FALSE,其他引⽤类型默认为null。
public String requestparam5(
@RequestParam(value="username", required=true, defaultValue="zhang") String username)
如果没有传⼊参数,则默认是"zhangsan".
但是在传递参数的时候如果是url?userName=zhangsan&userName=wangwu时怎么办呢?
其实在实际roleList参数⼊参的数据为“zhangsan,wangwu”,即多个数据之间使⽤“,”分割;我们应该使⽤如下⽅式来接收多个请求参数:
public String requestparam8(@RequestParam(value="userName") String [] userNames)
或者是:
public String requestparam8(@RequestParam(value="list") List<String> list)
@PathVariable绑定URI模板变量值
@RequestMapping(value="/users/{userId}/topics/{topicId}")
public String test( @PathVariable(value="userId") int userId, @PathVariable(value="topicId") int topicId)
如请求的URL为“控制器URL/users/123/topics/456”,则⾃动将URL中模板变量{userId}和{topicId}绑定到通过@PathVariable注解的同名参数上,即⼊参后userId=123、topicId=456。代码在PathVariableTypeController中
6.6.4、@CookieValue绑定Cookie数据值
@CookieValue⽤于将请求的Cookie数据映射到功能处理⽅法的参数上。
public String test(@CookieValue(value="JSESSIONID", defaultValue="") String sessionId)
如上配置将⾃动将JSESSIONID值⼊参到sessionId参数上,defaultValue表⽰Cookie中没有JSESSIONID时默认为空。
public String test2(@CookieValue(value="JSESSIONID", defaultValue="") Cookie sessionId)
传⼊参数类型也可以是javax.servlet.http.Cookie类型
测试代码在CookieValueTypeController中。@CookieValue也拥有和@RequestParam相同的三个参数,含义⼀样。
6.6.5、@RequestHeader绑定请求头数据
@RequestHeader⽤于将请求的头信息区数据映射到功能处理⽅法的参数上。
@RequestMapping(value="/header")
public String test(
@RequestHeader("User-Agent") String userAgent,
@RequestHeader(value="Accept") String[] accepts)
如上配置将⾃动将请求头“User-Agent”值⼊参到userAgent参数上,并将“Accept”请求头值⼊参到accepts参数上。测试代码在HeaderValueTypeController中。
@RequestHeader也拥有和@RequestParam相同的三个参数,含义⼀样。
6.6.6、@ModelAttribute绑定请求参数到命令对象
@ModelAttribute⼀个具有如下三个作⽤:
①绑定请求参数到命令对象:放在功能处理⽅法的⼊参上时,⽤于将多个请求参数绑定到⼀个命令对象,从⽽简化绑定流程,⽽且⾃动暴露为模型数据⽤于视图页⾯展⽰时使⽤;
②暴露表单引⽤对象为模型数据:放在处理器的⼀般⽅法(⾮功能处理⽅法)上时,是为表单准备要展⽰的表单引⽤对象,如注册时需要选择的所在城市等,⽽且在执⾏功能处理⽅法(@RequestMapping注解的⽅法)之前,⾃动添加到模型对象中,⽤于视图页⾯展⽰时使⽤;
③暴露@RequestMapping⽅法返回值为模型数据:放在功能处理⽅法的返回值上时,是暴露功能处理⽅法的返回值为模型数据,⽤于视图页⾯展⽰时使⽤。
⼀、绑定请求参数到命令对象
如⽤户登录,我们需要捕获⽤户登录的请求参数(⽤户名、密码)并封装为⽤户对象,此时我们可以使⽤@ModelAttribute绑定多个请求参数到我们的命令对象。
1. public String test1(@ModelAttribute("user") UserModel user)
和6.6.1⼀节中的五、命令/表单对象功能⼀样。只是此处多了⼀个注解@ModelAttribute("user"),它的作⽤是将该绑定的命令对象以“user”为名称添加到模型对象中供视图页⾯展⽰使⽤。我们此时可以在视图页⾯使⽤${user.username}来获取绑定的命令对象的属性。
绑定请求参数到命令对象⽀持对象图导航式的绑定,如请求参数包含“?username=zhang&password=123&workInfo.city=bj”⾃动绑定到user中的workInfo属性的city属性中。
Java代码
1. @RequestMapping(value="/model2/{username}")
public String test2(@ModelAttribute("model") DataBinderTestModel model) {
DataBinderTestModel相关模型请从第三章拷贝过来,请求参数到命令对象的绑定规则详见【4.16.1、数据绑定】⼀节,URI模板变量也能⾃动绑定到命令对象中,当你请求的URL中包
含“bool=yes&schooInfo.specialty=computer&hobbyList[0]=program&hobbyList[1]=music&map[key1]=value1&map[key2]=value2&state=blocked”会⾃动绑定到命令对象上。
当URI模板变量和请求参数同名时,URI模板变量具有⾼优先权。
⼆、暴露表单引⽤对象为模型数据
Java代码
1. @ModelAttribute("cityList")
public List<String> cityList() {
return Arrays.asList("北京", "⼭东");
}
如上代码会在执⾏功能处理⽅法之前执⾏,并将其⾃动添加到模型对象中,在功能处理⽅法中调⽤Model ⼊参的containsAttribute("cityList")将会返回true。
Java代码
1. @ModelAttribute("user") //①
public UserModel getUser(@RequestParam(value="username", defaultValue="") String username) {
//TODO 去数据库根据⽤户名查⽤户对象
UserModel user = new UserModel();
user.setRealname("zhang");
return user;
}
如你要修改⽤户资料时⼀般需要根据⽤户的编号/⽤户名查⽤户来进⾏编辑,此时可以通过如上代码查要编辑的⽤户。
也可以进⾏⼀些默认值的处理。
Java代码
1. @RequestMapping(value="/model1") //②
public String test1(@ModelAttribute("user") UserModel user, Model model)
此处我们看到①和②有同名的命令对象,那Spring Web MVC内部如何处理的呢:
(1、⾸先执⾏@ModelAttribute注解的⽅法,准备视图展⽰时所需要的模型数据;@ModelAttribute注解⽅法形式参数规则和@RequestMapping规则⼀样,如可以有@RequestParam等;
(2、执⾏@RequestMapping注解⽅法,进⾏模型绑定时⾸先查模型数据中是否含有同名对象,如果有直接使⽤,如果没有通过反射创建⼀个,因此②处的user将使⽤①处返回的命令对象。即②处的user等于①处的user。
三、暴露@RequestMapping⽅法返回值为模型数据
Java代码
1. public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user)
⼤家可以看到返回值类型是命令对象类型,⽽且通过@ModelAttribute("user2")注解,此时会暴露返回值到模型数据(名字为user2)中供视图展⽰使⽤。那哪个视图应该展⽰呢?此时Spring Web MVC会根据RequestToViewNameTranslator进⾏逻辑视图名的翻译,详见【4.15.5、RequestToViewNameTranslator】⼀节。
此时⼜有问题了,@RequestMapping注解⽅法的⼊参user暴露到模型数据中的名字也是user2,其实我们能猜到:
(3、@ModelAttribute注解的返回值会覆盖@RequestMapping注解⽅法中的@ModelAttribute注解的同名命令对象。
四、匿名绑定命令参数
Java代码
1. public String test4(@ModelAttribute UserModel user, Model model)
或
public String test5(UserModel user, Model model)
此时我们没有为命令对象提供暴露到模型数据中的名字,此时的名字是什么呢?Spring Web MVC⾃动将简单类名(⾸字母⼩写)作为名字暴露,如“cn.del.UserModel”暴露的名字为“userModel”。
Java代码
1. public @ModelAttribute List<String> test6()
或
public @ModelAttribute List<UserModel> test7()
对于集合类型(Collection接⼝的实现者们,包括数组),⽣成的模型对象属性名为“简单类名(⾸字母⼩写)”+“List”,如List<String>⽣成的模型对象属性名为“stringList”,List<UserModel>⽣成的模型对象属性名为“userModelList”。
其他情况⼀律都是使⽤简单类名(⾸字母⼩写)作为模型对象属性名,如Map<String, UserModel>类型的模型对象属性名为“map”。
6.6.7、@SessionAttributes绑定命令对象到session
有时候我们需要在多次请求之间保持数据,⼀般情况需要我们明确的调⽤HttpSession的API来存取会话数据,如多步骤提交的表单。Spring Web MVC提供了@SessionAttributes进⾏请求间透明的存取会话数据。
Java代码
1. //1、在控制器类头上添加@SessionAttributes注解
@SessionAttributes(value = {"user"}) //①
public class SessionAttributeController
//2、@ModelAttribute注解的⽅法进⾏表单引⽤对象的创建
@ModelAttribute("user") //②
public UserModel initUser()
//3、@RequestMapping注解⽅法的@ModelAttribute注解的参数进⾏命令对象的绑定
@RequestMapping("/session1") //③
public String session1(@ModelAttribute("user") UserModel user)
//4、通过SessionStatus的setComplete()⽅法清除@SessionAttributes指定的会话数据
@RequestMapping("/session2") //③
public String session(@ModelAttribute("user") UserModel user, SessionStatus status) {
if(true) { //④
status.setComplete();
}
return "success";
}
@SessionAttributes(value = {"user"})含义:
@SessionAttributes(value = {"user"}) 标识将模型数据中的名字为“user” 的对象存储到会话中(默认HttpSession),此处value指定将模型数据中的哪些数据(名字进⾏匹配)存储到会话中,此外还有⼀个types属性表⽰模型数据中的哪些类型的对象存储到会话范围内,如果同时指定value和types属性则那些名字和类型都匹配的对象才能存储到会话范围内。
包含@SessionAttributes的执⾏流程如下所⽰:
①⾸先根据@SessionAttributes注解信息查会话内的对象放⼊到模型数据中;
②执⾏@ModelAttribute注解的⽅法:如果模型数据中包含同名的数据,则不执⾏@ModelAttribute注解⽅法进⾏准备表单引⽤数据,⽽是使⽤①步骤中的会话数据;如果模型数据中不包含同名的数据,执⾏@ModelAttribute注解的⽅法并将返回值添加到模型数据中;
③执⾏@RequestMapping⽅法,绑定@ModelAttribute注解的参数:查模型数据中是否有@ModelAttribute注解的同名对象,如果有直接使⽤,否则通过反射创建⼀个;并将请求参数绑定到该命令对象;
此处需要注意:如果使⽤@SessionAttributes注解控制器类之后,③步骤⼀定是从模型对象中取得同名的命令对象,如果模型数据中不存在将抛出HttpSessionRequiredException Expected session attribute ‘user’(Spring3.1)
或HttpSessionRequiredException Session attribute ‘user’ required - not found in session(Spring3.0)异常。
④如果会话可以销毁了,如多步骤提交表单的最后⼀步,此时可以调⽤SessionStatus对象的setComplete()标识当前会话的@SessionAttributes指定的数据可以清理了,此时当@RequestMapping功能处理⽅法执⾏完毕会进⾏清理会话数据。
我们通过Spring Web MVC的源代码验证⼀下吧,此处我们分析的是Spring3.1的RequestMappingHandlerAdapter,读者可以⾃⾏验证Spring3.0的AnnotationMethodHandlerAdapter,流程⼀样:
(1、RequestMappingHandlerAdapter.invokeHandlerMethod
Java代码
1. //1、RequestMappingHandlerAdapter⾸先调⽤ModelFactory的initModel⽅法准备模型数据:
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
//2、调⽤@RequestMapping注解的功能处理⽅法
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
//3、更新/合并模型数据
modelFactory.updateModel(webRequest, mavContainer);
(2、ModelFactory.initModel
Java代码
1. Map<String, ?> attributesInSession = ieveAttributes(request);
//1.1、将与@SessionAttributes注解相关的会话对象放⼊模型数据中
//1.2、调⽤@ModelAttribute⽅法添加表单引⽤对象
invokeModelAttributeMethods(request, mavContainer);
//1.3、验证模型数据中是否包含@SessionAttributes注解相关的会话对象,不包含抛出异常
for (String name : findSessionAttributeArguments(handlerMethod)) {
if (!ainsAttribute(name)) {
//1.4、此处防⽌在@ModelAttribute注解⽅法⼜添加了会话对象
//如在@ModelAttribute注解⽅法调⽤session.setAttribute("user", new UserModel());
Object value = ieveAttribute(request, name);
if (value == null) {
throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
}
mavContainer.addAttribute(name, value);
}
(3、ModelFactory.invokeModelAttributeMethods
Java代码
1. for (InvocableHandlerMethod attrMethod : this.attributeMethods) {
String modelName = MethodAnnotation(ModelAttribute.class).value();
//1.2.1、如果模型数据中包含同名数据则不再添加
if (ainsAttribute(modelName)) {
continue;
}
//1.2.2、调⽤@ModelAttribute注解⽅法并将返回值添加到模型数据中,此处省略实现代码
}
(4、requestMappingMethod.invokeAndHandle 调⽤功能处理⽅法,此处省略
(5、ModelFactory.updateMode 更新模型数据
Java代码
1. //3.1、如果会话被标识为完成,此时从会话中清除@SessionAttributes注解相关的会话对象
if (SessionStatus().isComplete()){
this.sessionAttributesHandler.cleanupAttributes(request);
}
//3.2、如果会话没有完成,将模型数据中的@SessionAttributes注解相关的对象添加到会话中
else {
this.sessionAttributesHandler.storeAttributes(request, Model());
}
/
/省略部分代码
到此@SessionAtrribute介绍完毕,测试代码在cn.javass.ller.paramtype.SessionAttributeController中。
另外cn.javass.ller.paramtype.WizardFormController是⼀个类似于【4.11、AbstractWizardFormController】中介绍的多步骤表单实现,此处不再贴代码,多步骤提交表单需要考虑会话超时问题,这种⽅式可能对⽤户不太友好,我们可以采取隐藏表单(即当前步骤将其他步骤的表单隐藏)或表单数据存数据库(每步骤更新下数据库数据)等⽅案解决。
6.6.8、@Value绑定SpEL表⽰式
@Value⽤于将⼀个SpEL表达式结果映射到到功能处理⽅法的参数上。
Java代码
1. public String test(@Value("#{systemProperties['java.vm.version']}") String jvmVersion)
springmvc的注解有哪些到此数据绑定我们就介绍完了,对于没有介绍的⽅法参数和注解(包括⾃定义注解)在后续章节进⾏介绍。接下来我们学习下数据类型转换吧。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论