- 浏览: 1638487 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (405)
- C/C++ (16)
- Linux (60)
- Algorithm (41)
- ACM (8)
- Ruby (39)
- Ruby on Rails (6)
- FP (2)
- Java SE (39)
- Java EE (6)
- Spring (11)
- Hibernate (1)
- Struts (1)
- Ajax (5)
- php (2)
- Data/Web Mining (20)
- Search Engine (19)
- NLP (2)
- Machine Learning (23)
- R (0)
- Database (10)
- Data Structure (6)
- Design Pattern (16)
- Hadoop (2)
- Browser (0)
- Firefox plugin/XPCOM (8)
- Eclise development (5)
- Architecture (1)
- Server (1)
- Cache (6)
- Code Generation (3)
- Open Source Tool (5)
- Develope Tools (5)
- 读书笔记 (7)
- 备忘 (4)
- 情感 (4)
- Others (20)
- python (0)
最新评论
-
532870393:
请问下,这本书是基于Hadoop1还是Hadoop2?
Hadoop in Action简单笔记(一) -
dongbiying:
不懂呀。。
十大常用数据结构 -
bing_it:
...
使用Spring MVC HandlerExceptionResolver处理异常 -
一别梦心:
按照上面的执行,文件确实是更新了,但是还是找不到kernel, ...
virtualbox 4.08安装虚机Ubuntu11.04增强功能失败解决方法 -
dsjt:
楼主spring 什么版本,我的3.1 ,xml中配置 < ...
使用Spring MVC HandlerExceptionResolver处理异常
最近遇到一个需求,使用Spring MVC 3,需要绑定动态列表成员。Google了好多文章,没有找到完美的解决方案,绑定到不成问题,主要是动态添加、删除导致绑定的列表下标,在提交之前需要进行normalize,使用js进行normalize可行,但是费劲而且如果有对表单新的修改导致已有的js出现错误,本文提供了一个简单可行的易于维护的方法:
在添加的时候,我们根据当前条目的数量,计算新添加条目的下标。
在删除的时候,使用js将删除的条目隐藏,并将删除列表的下标记录到隐藏字段中。
这样在后台,我们只需要将删除的条目,按照记录在隐藏字段的下标删除,然后再保存即可。
关于绑定动态列表,在Spring 2.5中,不能使用普通的List,必须使用AutoPopulatingList进行绑定,否则会导致OutOfBoundException,Spring 3提供了Auto Grown的功能,但还仅限于List和Array,map和set还不能Auto Grown。
下面以一个简单的订单修改的例子说明如何进行动态列表绑定:
一个订单,有很多订单条目,用户可以修改订单,动态删除或者添加订单条目。
先看看model:
订单类,一个订单有一个订单列表:
订单条目类:
我们的控制器使用@ModelAttribute注解和表单绑定:
edit_order.jsp的表单和js添加、删除:
在Serice类中我们只是简单的准备数据和打印出结果查看效果:
BTW:Java的自动拆装箱要注意,特别是List#remove有两个重载的方法,
remove(Object) remove(int),这个必须手工拆箱。
好像不可以,绑定的需要能够按照下标访问的,而Set本身不能确保有序,所以不能下标访问。最好在VO中使用List绑定,然后和PO的Set转换一下。
在添加的时候,我们根据当前条目的数量,计算新添加条目的下标。
在删除的时候,使用js将删除的条目隐藏,并将删除列表的下标记录到隐藏字段中。
这样在后台,我们只需要将删除的条目,按照记录在隐藏字段的下标删除,然后再保存即可。
关于绑定动态列表,在Spring 2.5中,不能使用普通的List,必须使用AutoPopulatingList进行绑定,否则会导致OutOfBoundException,Spring 3提供了Auto Grown的功能,但还仅限于List和Array,map和set还不能Auto Grown。
下面以一个简单的订单修改的例子说明如何进行动态列表绑定:
一个订单,有很多订单条目,用户可以修改订单,动态删除或者添加订单条目。
先看看model:
订单类,一个订单有一个订单列表:
package com.qunar.advertisement.advertiser.model; import java.util.List; /** * Author: fuliang * http://fuliang.iteye.com */ public class Order { private Long id; private String name; private List<OrderItem> orderItems; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void setOrderItems(List<OrderItem> orderItems) { this.orderItems = orderItems; } public List<OrderItem> getOrderItems() { return orderItems; } }
订单条目类:
package com.qunar.advertisement.advertiser.model; /** * Author: fuliang * http://fuliang.iteye.com */ public class OrderItem { private Long id; private String product; private Integer price; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public void setProduct(String product) { this.product = product; } public String getProduct() { return product; } }
我们的控制器使用@ModelAttribute注解和表单绑定:
package com.qunar.advertisement.advertiser.controller; import java.util.Collections; import java.util.List; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import com.qunar.advertisement.advertiser.model.Order; import com.qunar.advertisement.advertiser.service.OrderManger; /** * Author: fuliang * http://fuliang.iteye.com */ @Controller @RequestMapping("/orders") public class OrderController { private OrderManger orderManager; @Autowired public void setOrderManger(OrderManger orderManager){ this.orderManager = orderManager; } @RequestMapping("/edit/{id}") public ModelAndView edit(@PathVariable("id") Long id){ return new ModelAndView("/orders/edit_order",Collections.singletonMap("order", orderManager.getOrderById(id))); } @RequestMapping("/update") public ModelAndView update(@ModelAttribute("order") @Valid Order order,@RequestParam(value="deletedIndexes",required=false) List<Integer> deletedIndexes){ orderManager.update(order,deletedIndexes); return new ModelAndView("/orders/home"); } }
edit_order.jsp的表单和js添加、删除:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jstl/fn" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <jsp:include page="../base.jsp"></jsp:include> <head> <script src="js/jquery-1.3.1.js" type="text/javascript"></script> <title>Order Home</title> <script type="text/javascript"> function deleteItem(itemIndex){ $('#item_' + itemIndex).hide(); $('#deletedIndexes').append("<input type='hidden' name='deletedIndexes' value='" + itemIndex + "'"); } function addItem(){ var itemCnt = parseInt($('#itemCnt').val()); var newItem = '<tr id="item_' + itemCnt + '">' + '<th>订单条目' + (itemCnt + 1)+ '</th>' + '<td><input type="hidden" name="orderItems[' + itemCnt + '].id"/>' + '<input type="text" name="orderItems[' + itemCnt + '].product"/>' + '</td>' + '<td><input type="text" name="orderItems[' + itemCnt + '].price"/></td>' + '<td><a href="javascript:void(0)" onclick="deleteItem('+ itemCnt + ')">删除条目</a></td>' + '</tr>'; $('#item_' + (itemCnt-1)).after(newItem); $('#itemCnt').val(itemCnt + 1); } </script> </head> <body> <div id="form"> <form:form commandName="order" id="orderForm" action="orders/update" method="post"> <form:hidden path="id"/> <div id="deletedIndexes" style="display:none;"> </div> <input type="hidden" value="${fn:length(order.orderItems)}" id="itemCnt"/> <table> <tr> <th>订单名</th> <td colspan="3"><form:input path="name"/></td> </tr> <c:forEach varStatus="vs" items="${order.orderItems}"> <tr id="item_${vs.index}"> <th>订单条目${vs.index + 1}</th> <td><form:hidden path="orderItems[${vs.index}].id"/> <form:input path="orderItems[${vs.index}].product"/> </td> <td><form:input path="orderItems[${vs.index}].price"/></td> <td><a href="javascript:void(0)" onclick="deleteItem('${vs.index}')">删除条目</a></td> </tr> </c:forEach> <tr> <td colspan="4" style="text-align:center"> <input type="submit" value="保存"/> <input type="button" value="添加订单条目" onclick="addItem()"/> </td> </tr> </table> </form:form> </div> </body> </html>
在Serice类中我们只是简单的准备数据和打印出结果查看效果:
package com.qunar.advertisement.advertiser.service; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; import com.qunar.advertisement.advertiser.model.Order; import com.qunar.advertisement.advertiser.model.OrderItem; /** * Author: fuliang * http://fuliang.iteye.com */ @Service public class OrderManger { //Simple data for test public Order getOrderById(Long id){ Order order = new Order(); order.setId(id); order.setName("手机订单"); List<OrderItem> orderItems = new ArrayList<OrderItem>(); order.setOrderItems(orderItems); OrderItem orderItem1 = new OrderItem(); orderItem1.setId(1L); orderItem1.setProduct("iPhone 4"); orderItem1.setPrice(5000); orderItems.add(orderItem1); OrderItem orderItem2 = new OrderItem(); orderItem2.setId(2L); orderItem2.setProduct("Nokia N97"); orderItem2.setPrice(4000); orderItems.add(orderItem2); return order; } /** * * @param order should be updated * @param deletedItemIndexes orderItem indexes should be deleted * 简单的在控制台打印出结果,如果存入到数据库,可以根据orderItem id * 是否为null,进行更新或者保存。 */ public void update(Order order, List<Integer> deletedItemIndexes) { if(deletedItemIndexes != null){ for(int i = deletedItemIndexes.size() - 1; i >= 0; i--){ order.getOrderItems().remove(deletedItemIndexes.get(i).intValue()); } } StringBuilder sb = new StringBuilder(); sb.append("Order Id: ").append(order.getId()).append("\tName: ").append(order.getName()).append("\n"); List<OrderItem> items = order.getOrderItems(); for (OrderItem orderItem : items) { sb.append("Item Id: ").append(orderItem.getId()).append("\tName: ").append(orderItem.getProduct()).append("\tprice: ").append(orderItem.getPrice()).append("\n"); } System.out.println(sb.toString()); } }
BTW:Java的自动拆装箱要注意,特别是List#remove有两个重载的方法,
remove(Object) remove(int),这个必须手工拆箱。
评论
3 楼
fuliang
2011-02-27
junnyfan 写道
我想同问,如果成员属性是Set如何绑定呢?
好像不可以,绑定的需要能够按照下标访问的,而Set本身不能确保有序,所以不能下标访问。最好在VO中使用List绑定,然后和PO的Set转换一下。
2 楼
junnyfan
2011-02-27
我想同问,如果成员属性是Set如何绑定呢?
1 楼
蓝之月
2011-01-20
如果对象成员为SET,如何绑定呢?
发表评论
-
自定义Jackson Json的Serializer
2011-08-05 18:52 16103转载请标明出处: http://fuliang.iteye.c ... -
Spring MVC form data binding and ajax form
2011-04-12 23:26 7294Model和View绑定是虽然不是MVC模式的标配,但是Mod ... -
使用Spring MVC HandlerExceptionResolver处理异常
2011-03-08 23:31 72268转载请标明出处:http://fuliang.iteye.co ... -
使用HandlerInterceptor实现简单的授权
2010-11-04 19:37 24026实现拦截器接口HandlerInterceptor或者Hand ... -
BeanPropertyRowMapper
2010-10-07 22:19 8786spring 2.5+提供了BeanPropertyRowMa ... -
使用Struts2+Hibernate+Spring写了一个RSS Reader
2008-04-06 22:11 4784一个简单的RSS Reader其实很好写,或许根本不需要使用S ... -
体验一下Spring2.5 Annotation-based-configration
2008-03-17 21:22 4120Spring2.5 Annotation-based-conf ... -
Dependency injection都有人质疑??
2008-01-12 12:46 1755Proffitt认为DI流行的唯一 ... -
Open Session in View
2007-12-08 23:57 3792我们在使用Hibernate的lazy load来优化 ... -
使用Struts2+Spring+Hibernate+sitemesh做的一个在线音乐站点
2007-11-03 16:21 9884前段时间用用Struts2+Spring+Hibernate+ ...
相关推荐
4.3.5.引用其他对象或类型的成员 4.3.5.1.使用对象或类的属性值进行注入 4.3.5.2.使用字段值进行注入 4.3.5.3.使用方法的返回值进行注入 4.3.6.IFactoryObject接口的其它实现 4.3.6.1.Log4Net 4.3.7.使用depends-on ...
"weixin108校园二手交易平台的设计与实现+ssm(源码+部署说明+演示视频+源码介绍+lw).rar" 这个资源包是一个针对校园内二手物品交易的完整项目文件,它使用Spring、SpringMVC和MyBatis(简称SSM)框架搭建。...
________ 专 业 软件工程 青 岛 工 学 院 目 录 1综述 1 1.1选题依据 1 1.2技术介绍 1 1.2.1开发工具介绍 2 1.2.2系统技术介绍 2 1.3组成员分工 2 2系统需求分析 3 2.1功能需求 3 2.1.1前台页面功能 3 2.1.2后台管理...
Seshat 扩展命名和平衡服务提供了一个完全符合 COS 命名服务的扩展,允许您在... 该服务使用 Spring Security Framework 进行访问控制,并且可以配置为使用 Spring Security Framework 支持的任何身份验证授权系统。
优点: 不需要书写XML配置文件 良好的学习文档 社区成员很热心 缺点: 社区比较小 不如其他的项目活跃 ActionBean里面的URL是硬编码的 Struts 2 优点: 架构简单——易于扩展 标记库很容易利用FreeMarker或者...
控制器接受前台的值的方式 路径传值 @RequestMapping("/login/{id}")...这里定义实体类需要注意的是,对于基本数据类型的成员变量尽量声明成其对应的包装类型… public class User{ private String name; private
常用组件是一些常用的组件和可复用API的集合,它包含了公共方法、异常处理,缓存、验证、全球化\本地化、动态类生成器、Data Context工厂、日志处理、事物处理、Spring.NET整合等等 扩展模型 扩展模型可以让你在...
15、增加租户成员绑定(TenantMemberBindEvent),解绑(TenantMemberUnBindEvent)事件.可通过spring-event订阅处理此事件.(Pro) 16、优化子设备状态检查,当检查子设备状态时,将会尝试发送ChildDeviceMessage<...
它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 select select * from category c where c.pid = #{pid} CollectionUtils.isnotblank 判断集合是否为空 测试 可以利用url直接查询数据库...
C#静态成员和方法的学习小结 C#中结构与类的区别 C#中 const 和 readonly 的区别 利用自定义属性,定义枚举值的详细文本 Web标准和ASP.NET - 第一部分 XHTML介绍 在ASP.NET页面中推荐使用覆写(Override)而不是事件...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...
Spring4GWT GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java...