springMVC使用HandlerMethodArgumentResolver 自定义解析器实现请求参数绑定方法参数

来源:互联网 发布:centos安装nodejs 编辑:程序博客网 时间:2024/05/21 18:45

平时工作用是struts2,近来试了下springMVC,感觉很方便。
然后遇到了问题:
我有Person和Cat两个类,他们都有name这个field,如果我有一个Controller的方法接收Cat和Person两个参数,我应该如何分别他们的name?
话说在页面写person.name和cat.name是没什么意义的,于是我看了一下stackOverFlow。
有人推荐我写一个类,并给这个类里增加Person和Cat类型的变量,这样就可以在页面里写person.name和cat.name以作区分了。
虽然解决问题,但并不高雅。
于是我找到了另一个方法——给method参数加annotation,使用HandlerMethodArgumentResolver。
那就顺便说说HandlerMethodArgumentResolver。

 

springMVC有这样一个类:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter


view sourceprint?
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方法。


 

view sourceprint?
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,我需要有一个类去实现他。

 

view sourceprint?
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。


 

view sourceprint?
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中。

 

view sourceprint?
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中:

 

view sourceprint?
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.}

页面中:

 

view sourceprint?
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>

使用起来很简单,但是要把我需要的功能完全时间就需要多做写工作了。

0 0
原创粉丝点击