简介:
handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)
A、处理requet uri 部分(这里指uri template中variable,不含queryString 部分)的注解:@PathVariable;
B、处理request header部分的注解:@RequestHeader, @CookieValue;
C、处理request body部分的注解:@RequestParam, @RequestBody;
D、处理attribute类型是注解:@SessionAttributes, @ModelAttribute;
1、@PathVariable
当使用@RequestMapping URI template 样式映射时,即
someUrl/{paramId}, 这时的paramId可通过@Pathvariable注解绑定它传过来的值到方法的参数上。
示例代码:
[java]view plain copy
1.@Controller
2.@RequestMapping("/owners/{ownerId}")
3.public class RelativePathUriTemplateController {
4.
5.@RequestMapping("/pets/{petId}")
6.public void findPet(@PathVariable String ownerId, @PathVariable String petId,
Model model) {
7.// implementation omitted
8. }
9.}
上面代码把URI template 中变量ownerId的值和petId的值,绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable("name")指定uri template中的名称。
2、@RequestHeader、@CookieValue
@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。
示例代码:
这是一个Request 的header部分:
[plain]view plain copy
1.Host localhost:8080
2.Accept text/html,application/xhtml+xml,application/xml;q=0.9
3.Accept-Language fr,en-gb;q=0.7,en;q=0.3
4.Accept-Encoding gzip,deflate
5.Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
6.Keep-Alive 300
[java]view plain copy
1.@RequestMapping("/displayHeaderInfo.do")
2.public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String enc
oding,
3.@RequestHeader("Keep-Alive") long keepAlive) {
4.
5.//...
6.
7.}
上面的代码,把request header部分的Accept-Encoding的值,绑定到参数encoding上了,Keep-Alive header的值绑定到参数keepAlive上。
@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。
例如有如下Cookie值:
[java]view plain copy
1.JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
参数绑定的代码:
[java]view plain copy
1.@RequestMapping("/displayHeaderInfo.do")
2.public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
3.
4.//...
5.
6.}
即把JSESSIONID的值绑定到参数cookie上。
3、@RequestParam, @RequestBody
@RequestParam
A)常用来处理简单类型的绑定,通过Request.getParameter() 获取的String 可直接转换为简单类型的情况(String--> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post 方式中body data的值;
B)用来处理Content-Type: 为application/x-www-form-urlencoded编码的内容,提交方式GET、POST;
C) 该注解有两个属性:value、required;value用来指定要传入值的id名称,required用来指示参数是否必须绑定;
示例代码:
[java]view plain copy
1.@Controller
2.@RequestMapping("/pets")
3.@SessionAttributes("pet")
4.public class EditPetForm {
5.
6.// ...
7.
8.@RequestMapping(method = RequestMethod.GET)
9.public String setupForm(@RequestParam("petId") int petId, ModelMap mod
el) {
10. Pet pet = this.clinic.loadPet(petId);
11. model.addAttribute("pet", pet);
12.return"petForm";
13. }
14.
15.// ...
@RequestBody
该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;
它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。
因为配置有FormHttpMessageConverter,所以也可以用来处
理application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap
示例代码:
[java]view plain copy
1.@RequestMapping(value = "/something", method = RequestMethod.PUT)
2.public void handle(@RequestBody String body, Writer writer) throws IOExcep
tion {
3. writer.write(body);
4.}
4、@SessionAttributes, @ModelAttribute
@SessionAttributes:
该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。
该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象;
示例代码:
[java]view plain copy
1.@Controller
2.@RequestMapping("/editPet.do")
3.@SessionAttributes("pet")
4.public class EditPetForm {
5.// ...
6.}
@ModelAttribute
该注解有两个用法,一个是用于方法上,一个是用于参数上;
用于方法上时:通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;
用于参数上时:用来通过名称对应,把相应名称的值绑定到注解的参数bean 上;要绑定的值来源于:
A)@SessionAttributes 启用的attribute 对象上;
B)@ModelAttribute 用于方法上时指定的model对象;
C)上述两种情况都没有时,new一个需要绑定的bean对象,然后把request 中按名称对应的方式把值绑定到bean中。
用到方法上@ModelAttribute的示例代码:
[java]view plain copy
1.// Add one attribute
2.// The return value of the method is added to the model under the name "accoun
t"
3.// You can customize the name via @ModelAttribute("myAccount")
4.
5.@ModelAttribute
6.public Account addAccount(@RequestParam String number) {
7.return accountManager.findAccount(number);
8.}
这种方式实际的效果就是在调用@RequestMapping的方法之前,为request 对象的model里put(“account”,Account);
用在参数上的@ModelAttribute示例代码:
[java]view plain copy
1.@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = Requ
estMethod.POST)
2.public String processSubmit(@ModelAttribute Pet pet) {
3.
4.}
首先查询@SessionAttributes有无绑定的Pet对象,若没有则查询
@ModelAttribute方法层面上是否绑定了Pet对象,若没有则将URI template 中的值按对应的名称绑定到Pet对象的各属性上。
补充讲解:
问题:在不给定注解的情况下,参数是怎样绑定的?通过分析AnnotationMethodHandlerAdapter和RequestMappingHandlerAdapter的源代码发现,方法的参数在不给定参数的情况下:
若要绑定的对象时简单类型:调用@RequestParam来处理的。
若要绑定的对象时复杂类型:调用@ModelAttribute来处理的。
这里的简单类型指java的原始类型(boolean, int 等)、原始类型对象(Boolean, Int等)、String、Date等ConversionService里可以直接String转换成目标对象的类型;
下面贴出AnnotationMethodHandlerAdapter中绑定参数的部分源代码:[java]view plain copy
1.private Object[] resolveHandlerArguments(Method handlerMethod, Object han
dler,
2. NativeWebRequest webRequest, ExtendedModelMap implicitModel) thro
ws Exception {
3.
4. Class[] paramTypes = handlerMethod.getParameterTypes();
5. Object[] args = new Object[paramTypes.length];
6.
7.for (int i = 0; i < args.length; i++) {
8. MethodParameter methodParam = new MethodParameter(handlerMeth
od, i);
9. methodParam.initParameterNameDiscovery(this.parameterNameDiscover
er);
10. GenericTypeResolver.resolveParameterType(methodParam, handler.getClas
s());
11. String paramName = null;
12. String headerName = null;
13.boolean requestBodyFound = false;
14. String cookieName = null;
15. String pathVarName = null;
16. String attrName = null;
17.boolean required = false;
18. String defaultValue = null;
19.boolean validate = false;
20. Object[] validationHints = null;
21.int annotationsFound = 0;
22. Annotation[] paramAnns = methodParam.getParameterAnnotations();
23.
24.for (Annotation paramAnn : paramAnns) {
25.if (RequestParam.class.isInstance(paramAnn)) {
26. RequestParam requestParam = (RequestParam) paramAnn;
27. paramName = requestParam.value();
28. required = requestParam.required();
29. defaultValue = parseDefaultValueAttribute(requestParam.defaultValu
e());
30. annotationsFound++;
31. }
32.else if (RequestHeader.class.isInstance(paramAnn)) {
33. RequestHeader requestHeader = (RequestHeader) paramAnn;
34. headerName = requestHeader.value();
35. required = requestHeader.required();
36. defaultValue = parseDefaultValueAttribute(requestHeader.defaultValu
e());
37. annotationsFound++;
38. }
39.else if (RequestBody.class.isInstance(paramAnn)) {
40. requestBodyFound = true;
41. annotationsFound++;
42. }
43.else if (CookieValue.class.isInstance(paramAnn)) {
44. CookieValue cookieValue = (CookieValue) paramAnn;
45. cookieName = cookieValue.value();
46. required = cookieValue.required();
47. defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue()
);
48. annotationsFound++;
49. }
50.else if (PathVariable.class.isInstance(paramAnn)) {
51. PathVariable pathVar = (PathVariable) paramAnn;
52. pathVarName = pathVar.value();
53. annotationsFound++;
54. }
55.else if (ModelAttribute.class.isInstance(paramAnn)) {
56. ModelAttribute attr = (ModelAttribute) paramAnn;
57. attrName = attr.value();
58. annotationsFound++;
59. }
60.else if (Value.class.isInstance(paramAnn)) {
61. defaultValue = ((Value) paramAnn).value();
62. }
63.else if (paramAnn.annotationType().getSimpleName().startsWith("Valid
")) {
64. validate = true;
65. Object value = AnnotationUtils.getValue(paramAnn);
66. validationHints = (value instanceof Object[] ? (Object[]) value : ne
w Object[] {value});
67. }
68. }
69.
70.if (annotationsFound > 1) {
71.throw new IllegalStateException("Handler parameter annotations are
exclusive choices - " +
72."do not specify more than one such annotation on the same para
meter: " + handlerMethod);
73. }
74.
75.if (annotationsFound == 0) {// 若没有发现注解
76. Object argValue = resolveCommonArgument(methodParam, webReque
st); //判断WebRquest是否可赋值给参数
77.if (argValue != WebArgumentResolver.UNRESOLVED) {
78. args[i] = argValue;
79. }
80.else if (defaultValue != null) {
81. args[i] = resolveDefaultValue(defaultValue);
82. }
83.else {
84. Class> paramType = methodParam.getParameterType();
85.if (Model.class.isAssignableFrom(paramType) || Map.class.isAssigna
bleFrom(paramType)) {
86.if (!paramType.isAssignableFrom(implicitModel.getClass())) {
87.throw new IllegalStateException("Argument [" + paramType.g
etSimpleName() + "] is of type " +
88."Model or Map but is not assignable from the actual model
. You may need to switch " +
89."newer MVC infrastructure classes to use this argument.");
90. }
91. args[i] = implicitModel;
92. }
93.else if (SessionStatus.class.isAssignableFrom(paramType)) {
94. args[i] = this.sessionStatus;
95. }
96.else if (HttpEntity.class.isAssignableFrom(paramType)) {
97. args[i] = resolveHttpEntityRequest(methodParam, webRequest);
98. }
99.else if (Errors.class.isAssignableFrom(paramType)) {
100.throw new IllegalStateException("Errors/BindingResult argu ment declared " +
101."without preceding model attribute. Check your handler
method signature!");
102. }
103.else if (BeanUtils.isSimpleProperty(paramType)) {// 判断是否参
数类型是否是简单类型,若是在使用@RequestParam方式来处理,否则使用
@ModelAttribute方式处理
104. paramName = "";
105. }
106.else {
107. attrName = "";
108. }
109. }
110. }
111.
112.if (paramName != null) {
113. args[i] = resolveRequestParam(paramName, required, defaultValue , methodParam, webRequest, handler);
114. }
115.else if (headerName != null) {
116. args[i] = resolveRequestHeader(headerName, required, defaultValu e, methodParam, webRequest, handler);
117. }
118.else if (requestBodyFound) {
119. args[i] = resolveRequestBody(methodParam, webRequest, handler) ;
120. }
121.else if (cookieName != null) {
122. args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
123. }
124.else if (pathVarName != null) {
125. args[i] = resolvePathVariable(pathVarName, methodParam, webRe quest, handler);
126. }
127.else if (attrName != null) {
128. WebDataBinder binder =
129. resolveModelAttribute(attrName, methodParam, implicitMod el, webRequest, handler);
130.boolean assignBindingResult = (args.length > i + 1 && Errors.cl ass.isAssignableFrom(paramTypes[i + 1]));
131.if (binder.getTarget() != null) {
132. doBind(binder, webRequest, validate, validationHints, !assignBin dingResult);
133. }
134. args[i] = binder.getTarget();
135.if (assignBindingResult) {
136. args[i + 1] = binder.getBindingResult();
137. i++;
138. }
139. implicitModel.putAll(binder.getBindingResult().getModel());
140. }
141. }
142.
143.return args;
144. }
RequestMappingHandlerAdapter中使用的参数绑定,代码稍微有些不同,有兴趣的同仁可以分析下,最后处理的结果都是一样的。
示例:
[java]view plain copy
1.@RequestMapping ({"/", "/home"})
2.public String showHomePage(String key){
3.
4. logger.debug("key="+key);
5.
6.return"home";
7. }
这种情况下,就调用默认的@RequestParam来处理。
[java]view plain copy
1.@RequestMapping (method = RequestMethod.POST)
2.public String doRegister(User user){
3.if(logger.isDebugEnabled()){
4. logger.debug("process url[/user], method[post] in "+getClass());
5. logger.debug(user);
6. }
7.
8.return"user";
9.}
这种情况下,就调用@ModelAttribute来处理。
Springmvc框架配置步骤 小弟是个新手,有不对的地方请tell me,一起研究探讨。谢谢。 1062140832@https://www.wendangku.net/doc/6d413528.html, 配置springmvc框架其实不是很难,要现有一个总体的认识,确定要分几步,每一步主要是干什么,不要太盲目。 以为web.xml是项目的入口,所以所有的配置文件,都必须引入到wem.xml中,不然,配置了等于没用。所以,要先从入口入手。 配置web.xml 1、首先引入springmvc-servlet.xml文件
一、前言: 大家好,Spring3 MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了。Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也很优秀。 官方的下载网址是:https://www.wendangku.net/doc/6d413528.html,/download(本文使用是的Spring 3.0.5版本) Struts2也是比较优秀的MVC构架,优点非常多比如良好的结构。但这里想说的是缺点,Struts2由于采用了值栈、OGNL表达式、struts2标签库等,会导致应用的性能下降。Struts2的多层拦截器、多实例action性能都很好。可以参考我写的一篇关于Spring MVC与Struts2与Servlet比较的文章https://www.wendangku.net/doc/6d413528.html,/admin/blogs/698217 Spring3 MVC的优点: 1、Spring3 MVC的学习难度小于Struts2,Struts2用不上的多余功能太多。呵呵,当然这不是决定因素。 2、Spring3 MVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分) 3、Spring3 MVC的灵活是你无法想像的,Spring的扩展性有口皆碑,Spring3 MVC当然也不会落后,不会因使用了MVC框架而感到有任何的限制。 Struts2的众多优点:略... (呵呵,是不是不公平?) 众多文章开篇时总要吹些牛,吸引一下读者的眼球,把读者的胃口调起来,这样大家才有兴趣接着往后看。本文也没能例外。不过保证你看了之后不会后悔定有收获。
Spring mvc架构及执行流程一、请求处理流程图 二、执行流程说明 三、组件说明
说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc 的三大组件。 需要用户编写的组件有handler、view 四、Spring MVC配置 1、组件扫描器:使用组件扫描器省去在spring容器配置每个controller类,使用
2、RequestMappingHandlerMapping:注解处理器映射器,对类中标记@RequestMapping 的方法进行映射,根据RequestMapping定义的url匹配RequestMapping标记的方 法,匹配成功返回HandlerMethod对象给前端控制器,HandlerMethod对象中封装 注解描述: @RequestMapping:定义请求url到处理器功能方法的映射 3、RequestMappingHandlerAdapter:注解式处理器适配器,对标记@RequestMapping 的方法进行适配。 从spring3.1版本开始,废除了AnnotationMethodHandlerAdapter的使用,推荐使用 4、
牧涛 --<-<-<@态度决定一切→_→。。。 ?博客园 ?首页 ?新闻 ?新随笔 ?联系 ?管理 ?订阅 随笔- 171 文章- 3 评论- 79 spring MVC配置详解 现在主流的Web MVC框架除了Struts这个主力外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了。不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。 一、Spring MVC环境搭建:(Spring 2.5.6 + Hibernate 3.2.0) 1. jar包引入 Spring 2.5.6:spring.jar、spring-webmvc.jar、commons-logging.jar、cglib -nodep-2.1_3.jar Hibernate 3.6.8:hibernate3.jar、hibernate-jpa-2.0-api-1.0.1.Final.jar、a ntlr-2.7.6.jar、commons-collections-3.1、dom4j-1.6.1.jar、javassist-3.12.0.G A.jar、jta-1.1.jar、slf4j-api-1.6.1.jar、slf4j-nop-1.6.4.jar、相应数据库的驱动jar 包 SpringMVC是一个基于DispatcherServlet(分发器)的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回。 DispatcherServlet是继承自HttpServlet的,既然SpringMVC是基于DispatcherSe rvlet的,那么我们先来配置一下DispatcherServlet,好让它能够管理我们希望它管理的内容。HttpServlet是在web.xml文件中声明的。