转载自:http://blog.csdn.net/truong/article/details/30971317
平时工作用是struts2,近来试了下springMVC,感觉很方便。
然后遇到了问题:
我有Person和Cat两个类,他们都有name这个field,如果我有一个Controller的方法接收Cat和Person两个参数,我应该如何分别他们的name?
话说在页面写person.name和cat.name是没什么意义的,于是我看了一下*。
有人推荐我写一个类,并给这个类里增加Person和Cat类型的变量,这样就可以在页面里写person.name和cat.name以作区分了。
虽然解决问题,但并不高雅。
于是我找到了另一个方法——给method参数加annotation,使用HandlerMethodArgumentResolver。
那就顺便说说HandlerMethodArgumentResolver。
springMVC有这样一个类:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
01.
/**
02.
* An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s
03.
* with the signature -- method argument and return types, defined in
04.
* {@code @RequestMapping}.
05.
*
06.
* <p>Support for custom argument and return value types can be added via
07.
* {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.
08.
* Or alternatively to re-configure all argument and return value types use
09.
* {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}.
10.
*
11.
* @author Rossen Stoyanchev
12.
* @since 3.1
13.
* @see HandlerMethodArgumentResolver
14.
* @see HandlerMethodReturnValueHandler
15.
*/
16.
public
class
RequestMappingHandlerAdapter
extends
AbstractHandlerMethodAdapter
implements
BeanFactoryAware,
17.
InitializingBean
看了说明大致明白,他可以用来定制method参数和返回值。
我这里需要修改的是参数,也就是需要用他的setCustomArgumentResolvers方法。
1.
/**
2.
* Provide resolvers for custom argument types. Custom resolvers are ordered
3.
* after built-in ones. To override the built-in support for argument
4.
* resolution use {@link #setArgumentResolvers} instead.
5.
*/
6.
public
void
setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
7.
this
.customArgumentResolvers = argumentResolvers;
8.
}
参数List类型的泛型是HandlerMethodArgumentResolver,我需要有一个类去实现他。
01.
import
java.lang.reflect.Field;
02.
import
java.util.Iterator;
03.
import
org.springframework.beans.BeanUtils;
04.
import
org.springframework.core.MethodParameter;
05.
import
org.springframework.web.bind.support.WebDataBinderFactory;
06.
import
org.springframework.web.context.request.NativeWebRequest;
07.
import
org.springframework.web.method.support.HandlerMethodArgumentResolver;
08.
import
org.springframework.web.method.support.ModelAndViewContainer;
09.
import
pac.ano.FormModel;
10.
public
class
MyMethodArgumentsResolver
implements
HandlerMethodArgumentResolver {
11.
12.
public
boolean
supportsParameter(MethodParameter parameter) {
13.
return
parameter.hasParameterAnnotation(FormModel.
class
);
14.
}
15.
public
Object resolveArgument(MethodParameter parameter,
16.
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
17.
WebDataBinderFactory binderFactory)
throws
Exception {
18.
String objName = parameter.getParameterName() +
"."
;
19.
Object o = BeanUtils.instantiate(parameter.getParameterType());
20.
StringBuffer tmp;
21.
String[] val;
22.
Field[] frr = parameter.getParameterType().getDeclaredFields();
23.
for
(Iterator<String> itr = webRequest.getParameterNames(); itr
24.
.hasNext();) {
25.
tmp =
new
StringBuffer(itr.next());
26.
if
(tmp.indexOf(objName) <
0
)
continue
;
27.
for
(
int
i =
0
; i < frr.length; i++) {
28.
frr[i].setAccessible(
true
);
29.
if
(tmp.toString().equals(objName + frr[i].getName())) {
30.
val = webRequest.getParameterValues(tmp.toString());
31.
frr[i].set(o, val[
0
]);
32.
}
33.
}
34.
}
35.
return
o;
36.
}
37.
}
这是一个不完整的版本,但是用来做例子是足够了。
我可以在supportsParameter里判断参数是否满足我的Resolver。
而在resolveArgument里我们可以处理这些参数。
另外,FormModel就是我创建的annotation。
01.
import
java.lang.annotation.Documented;
02.
import
java.lang.annotation.ElementType;
03.
import
java.lang.annotation.Retention;
04.
import
java.lang.annotation.RetentionPolicy;
05.
import
java.lang.annotation.Target;
06.
@Target
({ ElementType.PARAMETER })
07.
@Retention
(RetentionPolicy.RUNTIME)
08.
@Documented
09.
public
@interface
FormModel {
10.
String value();
11.
}
另外,我需要将他配置到spring context中。
1.
<
bean
class
=
"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
>
2.
<
property
name
=
"synchronizeOnSession"
value
=
"true"
/>
3.
<
property
name
=
"customArgumentResolvers"
>
4.
<
list
>
5.
<
bean
class
=
"pac.ano.interpreter.MyMethodArgumentsResolver"
/>
6.
</
list
>
7.
</
property
>
8.
</
bean
>
剩下的就是去使用他,controller中:
1.
@RequestMapping
(value=
"/index"
)
2.
public
ModelAndView index(
@FormModel
(
"p"
)Person p){
3.
ModelAndView tmpMAV =
new
ModelAndView(
"index"
);
4.
System.out.println(p);
5.
tmpMAV.addObject(
"p.name"
,p.getName());
6.
return
tmpMAV;
7.
}
页面中:
1.
<
form
action
=
"index"
method
=
"post"
>
2.
<
input
type
=
"text"
name
=
"p.name"
/>
3.
<
input
type
=
"text"
name
=
"name"
/>
4.
<
input
type
=
"text"
name
=
"p.age"
/>
5.
<
input
type
=
"text"
name
=
"weight"
/>
6.
<
input
type
=
"text"
name
=
"p.height"
/>
7.
<
input
type
=
"submit"
value
=
"提交"
/>
8.
</
form
>
使用起来很简单,但是要把我需要的功能完全时间就需要多做写工作了。