您的位置:首页 > 编程语言 > Java开发

扩展SpringMVC以支持更精准的数据绑定1

2014-04-04 15:15 483 查看

扩展SpringMVC以支持更精准的数据绑定1

博客分类:
springmvc杂谈
跟开涛学SpringMVC
java开发常见问题分析

最新版请点击查看FormModelMethodArgumentResolver.java

问题描述:


springMVC 数据绑定 多个对象 如何准确绑定?

Java代码







<form> <input name="student.name" value="Kate" /> <input name="student.type" value="自费" /> <input name="teacher.name" value="Gavin" /> <input name="teacher.level" value="2" /> </form>

<form>

<input name="student.name" value="Kate" />

<input name="student.type" value="自费" />

<input name="teacher.name" value="Gavin" />

<input name="teacher.level" value="2" />

</form>


Java代码







@RequestMapping("/school.do") public String school(Student student, Teacher teacher) { return "school"; }

@RequestMapping("/school.do")

public String school(Student student, Teacher teacher) {

return "school";

}

如果还是想刚才的jsp那些写表单,是不能封装参数的,必须把“student.”和“teacher.”去掉,但是这样封装就不能准确封装了。

这个问题最近老是有人问,所以写一个扩展很容易解决这个问题,springmvc和spring一样,预留的扩展点足够多。

我们都知道struts2默认就是这种方案,这是因为struts2采用了OGNL,并通过栈(根对象)进行操作的,而且栈中默认有action实例,所以很自然的没有这种问题。

springmvc不同,没有根对象的概念,而且本身很难来解决这个问题,因此大家在使用时最好避免这种方式或者使用类似于struts1的FormBean组合对象来解决。

解决方案:

扩展spring的HandlerMethodArgumentResolver以支持自定义的数据绑定方式。

1、请下载附件的代码,放到工程中;

2、在RequestMappingHandlerAdapter添加自定义HandlerMethodArgumentResolver Bean;

Java代码







<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<!--线程安全的访问session-->
<property name="synchronizeOnSession" value="true"/>
<property name="customArgumentResolvers">
<list>
<bean class="cn.javass.spring.mvc.method.annotation.RequestJsonParamMethodArgumentResolver"/>
<bean class="cn.javass.spring.mvc.method.annotation.FormModelMethodArgumentResolver"/>
</list>
</property>
</bean>

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<!--线程安全的访问session-->
<property name="synchronizeOnSession" value="true"/>
<property name="customArgumentResolvers">
<list>
<bean class="cn.javass.spring.mvc.method.annotation.RequestJsonParamMethodArgumentResolver"/>
<bean class="cn.javass.spring.mvc.method.annotation.FormModelMethodArgumentResolver"/>
</list>
</property>
</bean>

//customArgumentResolvers用于注入自定义的参数解析器,此处我们注了FormModelMethodArgumentResolver;FormModelMethodArgumentResolver我直接修改的org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;

3、使用方式

Java代码







public String user(@FormModel("student") Student student, @FormModel("teacher") Teacher teacher)

public String user(@FormModel("student") Student student, @FormModel("teacher") Teacher teacher)


4、测试控制器

Java代码







package cn.javass.chapter6.web.controller.formmodel;

import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.javass.chapter6.model.UserModel;
import cn.javass.spring.mvc.bind.annotation.FormModel;
import cn.javass.spring.mvc.util.MapWapper;

@Controller
@RequestMapping("/formmodel")
public class FormModelController {

//ok http://localhost:9080/springmvc-chapter6/formmodel/user?user.username=zhang&user.password=123
@RequestMapping("/user/{user.realname}")
public String user(@FormModel("user") UserModel user) {
System.out.println(user);
return "redirect:/success";
}

//ok http://localhost:9080/springmvc-chapter6/formmodel/array1?array[0]=zhang&array[1]=li
@RequestMapping("/array1")
public String array1(@FormModel("array") String[] array) {
System.out.println(Arrays.toString(array));
return "redirect:/success";
}

//ok http://localhost:9080/springmvc-chapter6/formmodel/array2?array[0].username=zhang&array[0].password=123&array[1].username=li
@RequestMapping("/array2")
public String array2(@FormModel("array") UserModel[] array) {
System.out.println(Arrays.toString(array));
return "redirect:/success";
}

//ok http://localhost:9080/springmvc-chapter6/formmodel/list1?list[0]=123&list[1]=234
@RequestMapping("/list1")
public String list1(@FormModel("list") List<Integer> list) {
System.out.println(list);
return "redirect:/success";
}

//ok http://localhost:9080/springmvc-chapter6/formmodel/list2?list[0].username=zhang&list[1].username=li
@RequestMapping("/list2")
public String list2(@FormModel("list") List<UserModel> list) {
System.out.println(list);
return "redirect:/success";
}

//ok http://localhost:9080/springmvc-chapter6/formmodel/map1?map['0']=123&map["1"]=234
@RequestMapping("/map1")
public String map1(@FormModel("map") MapWapper<String, Integer> map) {
System.out.println(map);
return "redirect:/success";
}
//ok http://localhost:9080/springmvc-chapter6/formmodel/map2?map['0'].password=123&map['0'].username=123&map["1"].username=234
@RequestMapping("/map2")
public String map2(@FormModel("map") MapWapper<Integer, UserModel> map) {
System.out.println(map);
return "redirect:/success";
}
}

package cn.javass.chapter6.web.controller.formmodel;

import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.javass.chapter6.model.UserModel;
import cn.javass.spring.mvc.bind.annotation.FormModel;
import cn.javass.spring.mvc.util.MapWapper;

@Controller
@RequestMapping("/formmodel")
public class FormModelController {

//ok   http://localhost:9080/springmvc-chapter6/formmodel/user?user.username=zhang&user.password=123 @RequestMapping("/user/{user.realname}")
public String user(@FormModel("user") UserModel user) {
System.out.println(user);
return "redirect:/success";
}

//ok   http://localhost:9080/springmvc-chapter6/formmodel/array1?array[0]=zhang&array[1]=li @RequestMapping("/array1")
public String array1(@FormModel("array") String[] array) {
System.out.println(Arrays.toString(array));
return "redirect:/success";
}

//ok   http://localhost:9080/springmvc-chapter6/formmodel/array2?array[0].username=zhang&array[0].password=123&array[1].username=li @RequestMapping("/array2")
public String array2(@FormModel("array") UserModel[] array) {
System.out.println(Arrays.toString(array));
return "redirect:/success";
}

//ok   http://localhost:9080/springmvc-chapter6/formmodel/list1?list[0]=123&list[1]=234 @RequestMapping("/list1")
public String list1(@FormModel("list") List<Integer> list) {
System.out.println(list);
return "redirect:/success";
}

//ok   http://localhost:9080/springmvc-chapter6/formmodel/list2?list[0].username=zhang&list[1].username=li @RequestMapping("/list2")
public String list2(@FormModel("list") List<UserModel> list) {
System.out.println(list);
return "redirect:/success";
}

//ok   http://localhost:9080/springmvc-chapter6/formmodel/map1?map['0']=123&map["1"]=234 @RequestMapping("/map1")
public String map1(@FormModel("map") MapWapper<String, Integer> map) {
System.out.println(map);
return "redirect:/success";
}
//ok   http://localhost:9080/springmvc-chapter6/formmodel/map2?map['0'].password=123&map['0'].username=123&map["1"].username=234 @RequestMapping("/map2")
public String map2(@FormModel("map") MapWapper<Integer, UserModel> map) {
System.out.println(map);
return "redirect:/success";
}
}


具体使用可以下载之前springmvc第六章源代码/content/2573641.html

将附件中的FormModel.rar解压放到src下进行测试。

支持的spring版本:

springmvc 3.1.x,暂不支持3.0。为什么不支持呢?springmvc 3.1 和 3.0 从架构上发生了变化,而且springmvc3.1更容易扩展。

支持绑定的数据:

模型、集合、数组、MapWapper(Map的一个包装器,通过getInnerMap获取真实Map)

缺点:

spring自定义的参数解析器会放在默认解析器之后,不能指定order,因此如果我们@FormModel("map") Map map,此map会变成Model(请参考/content/2573644.html 第六部分、Model Map ModelMap),希望未来的版本支持自定义顺序来解决这个问题;此处我们使用MapWapper解决,可以通过MapWapper.getInnerMap()拿到我们需要的Map

其他方案:

[SpringMVC]修改源码使之能够更加智能的自动装配request请求参数.(不建议修改源代码解决)

@rainsoft 也给出了类似的方案, http://www.iteye.com/topic/1124433#2357830

如果你使用的是mvc:annotation-driven,请这样配置

Java代码







<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.sishuok.es.common.web.bind.method.annotation.FormModelMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>

<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.sishuok.es.common.web.bind.method.annotation.FormModelMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: