- 浏览: 139880 次
- 性别:
- 来自: 重庆
最新评论
-
老梦a:
要是保存到数据库,是怎么做呢,数据流这块,不太懂。。(*^__ ...
使用flash摄像头拍照的简单实践 -
wolf521hf:
学习 最近正在看相关的文档 标记下
Spring安全权限管理(Spring Security) -
yue_hun1025:
怎么下载不了??????
java反编译工具jad下载 -
ry.china:
你把这个放到jdk的bin目录下就可以了
java反编译工具jad下载 -
幻樱释:
不知道能不能看懂哦。
javascript高级程序设计实例代码
一,一些可改进的代码片段
据我平常观察,周围的同事还存在不少类似的代码,举两例进行说明:
这段是操作ResultSet的
- CustBean bean = new CustBean () ;
- bean . setCustId ( rs . getString ( " CUST_ID " ))
- bean . setCustName ( rs . getString ( " CUST_NAME " ))
- ....
- // more similar code
- ...
这段是Servlet或其它业务类中的
- CustBean bean = new CustBean () ;
- bean . setCustId ( request . getParameter ( " CUST_ID " ))
- bean . setCustName ( request . getParameter ( " CUST_NAME " ))
- ....
依次类推,类似的getter/setter随处可见,以至代码相当冗余,还白白耗费键盘功夫.
当然,以上的代码如果在hibernate或其它ORM框架的支撑下,是不会出现的.
所以,你如果从一开始就掉在这些框架温柔的陷井里,也许还会难以理解这种写法的存在.
拿第二段来说,如果页面传入参数的名称和Bean中的property一致的话,其实就可以用commons beanutils工具包来简化:
- BeanUtils . populate ( bean , request . getParameterMap ())
那更进一步,如果常用对象都能用值copy的方式送入到指定bean中,代码量将大大减少;
可遗憾的是,BeanUtils.populate()方法,源对象参数只能是Map类型,
况且,对于数据库表字段或者页面参数命名,有人喜欢大写加个下划线,有人喜欢小写加个下划线,而我个人则喜欢直接用Java类命名方式:首字母大写来搞定.
所以,想要进行省事的值copy运算,得对beanutils进行扩展,以适应不同的场景,必竟人的习惯是一样很可怕的东西,相当顽固,一旦养成,很难改变.
其实,在Java中从某种内部对象向bean进行的值copy场景,出现的机率是相当高的.除非你完全摒弃MVC的精神,另搞一套新鲜玩法.
还有些场景,我们得从外部XML直接装载数据到bean
,这些都算是一种值copy的应用,基本可以说无处不在!
二,回头再从beanutils说起
如果曾用过apache commons的这个工具包,都会留意到它的这两个实用功能:
此方法可以将src对象中的属性值,逐一对应地填充到做为dest参数的JavaBean中,
但有两点限制:
1,,src对象一定是Map类型;就像前面的例子中提到的一样
2,,src对象中的key值,一定是和JavaBean提供的setter方法保持统一的命名规范,因为populate的内部实现本身就是基于introspection的.
这个就更直接了.dest和src都是JavaBean,但两者所属类型可以不一样,只要property的setter能对应起来,就能够完成值copy.
在本文的工具案例中,对于copyProperties是不需要的,已经给了替代统一的实现方案.
很显然,以上两个方法都是挺实用的.在不少我们已接触的开源框架中都有用到beanutils,Struts的ActionForm值自动填充就是一例.
但在我个人实用应用中,它们都表现很大的局限性,仍然不够灵活.
最为突出的不便之处在于,beanutils对于src参数对象的要求太过于苛刻了:
1,populate的源参数对象只接收Map类型
2,key值得符合dest bean的命名规范, 才能进行值copy.
三,扩展源值对象的类型支持
在一般J2EE WEB应用开发中,可能出现值copy的地方一般会有两种:
1, 从ResultSet对象中提取数据,送入Bean
2, 从HttpServletRequest对象中提取数据,送入Bean.同前述ActionForm
情况1往往会出现在读取数据库进行业务展现时,而情况2则反之,是从获取从前台提交的数据做业务处理,然后写表.
而我个人还会碰一种情况.
在DWR做辅助开发时,如果需要向一个后台DAO对象传送多个页面参数时,我喜欢用prototype提供的一个方法:
Form.serialize( $(’someForm’) )
这个方法,可以直接将Form上所有表单元素,生成key=value的标准Http GET参数串形式,然后我会将此串直接传入DWR后台业务对象处理.
这样不但省掉了定义多个方法参数的麻烦,也便于参数个数的任意调整,应对需求变化很实用.
那对于这种 key=value的字符串参数,我需要也能直接进行值copy,绑定到bean才行.
当然,除了上面的ResultSet, HttpServletRequest, String三类,beanutils默认支持的Map,普通Bean当然也需要在考虑之中.
这一步的修改,比较简单.我们只要将这几种类型统一转成Map,再用beanutils的populate即可.
内部实现代码如下:
- public static void setValues ( Object dest , Object src ) throws Exception {
- Map propAliasMap = getPropertyAliasMap ( dest , " alias_as_key " ) ;
- if ( src instanceof HttpServletRequest ) {
- BeanUtils . populate ( dest , mapToMap ((( HttpServletRequest ) src )
- . getParameterMap () , propAliasMap )) ;
- } else if ( src instanceof ResultSet ) {
- BeanUtils . populate ( dest , resultSetToMap (( ResultSet ) src ,
- propAliasMap )) ;
- } else if ( src instanceof String ) {
- BeanUtils . populate ( dest , keyValueToMap (( String ) src , propAliasMap )) ;
- } else if ( src instanceof Map ) {
- BeanUtils . populate ( dest , mapToMap (( Map ) src , propAliasMap )) ;
- } else {
- BeanUtils . populate ( dest , beanToMap ( src , propAliasMap )) ;
- }
- }
至于将特定对象转成Map的方法,一般人都可以想当然的知道了,不必螯述.
如果使用过Spring的JdbcTemplate,它其中的queryForList(sql)默认就提供了一个RowMapper实现,每行ResultSet就会自动转成Map.
但如果需要自定义RowMapper转换特定类型的话,就正好可以搭配本文的工具包使用,直接对每行rs对象进行值copy到Bean对象.本文最后会有代码示例说明这点.
通过这样通过的处理后,我们可以用同一行代码,完成几乎常用的值copy操作,比如:
- ModelValueUtils . setValues ( Object dest , Object src ) ;
- // 这个src对象的类型,就比较灵活了
四,解决Key值对Bean的property映射
看完上面一节,你是不是已发现了一些相关的东西.
在解决了对多种源值对象类型的支持后,现在就该来解决每个人的命名习惯问题了.
如前所述.像Hibernate,或者iBatis这类ORM映射框架,它们从数据表里自动获取数据,再绑定到bean时,实际上就完成了一次值copy;
至少它的内部实现,我们无需关注.但可以发现,它们都是采用XML文件,再描述Bean Property和数据表字段的对应关系.
这种做法,在很大程度上已经成为一种习惯.可最终的后果是,它们带来了的XML文件,不是每个人都乐意接受的,甚至有些人一看到XX框架的XML配置就反感.
有所谓重量级和轻量级的判别中,XML配置的大小都成了一个说辞.
google的牛人,自已写了一个guice,实现了几乎和spring一样的IoC容器功能,而无一行XML配置,被人津津乐道,谓之"真正的轻量级诞生了"
呵呵,这个有些扯远了.之所以提到guice,只是想引出 annotation.
说回主题,XML即然麻烦,那最直接,最简单的做法就是Tiger版本的annotation了.
我们需要的就是,在目标Bean的某个property前,加上一行标注,给这个property定义一个可供映射的别名.
这样一来,无论是从ResultSet,还是Request,或者其它类型的源数据Bean中,将值copy到这个目标bean时,名称的对应关系就解决了.每个人的对象属性/表字段命名习惯也就得到最大程度地得到了满足.可以随心所欲.
简单的思路:用annotation来做别名映射,以支持更灵活的值copy.
这里用我工具包里的实现代码做示例说明,看代码可以一目了然!
再帖一段前述的代码,以做对比:
- CustBean bean = new CustBean () ;
- bean . setCustId ( request . getParameter ( " CUST_ID " ))
- bean . setCustName ( request . getParameter ( " CUST_NAME " ))
- ...
- //CustBean的代码一般会是:
- public class CustBean {
- private String custId ;
- private String custName ;
- ....
- // getter & setter
- }
这种情况下,页面参数名和Bean的property并不匹配,我们需要定义映身关系.就像Hibernate的mapping文件一样.
将CustBean的代码稍做修改.
- public class CustBean {
- @ ModelPropertyAlias ( " CUST_ID " )
- private String custId ;
- @ ModelPropertyAlias ( " CUST_NAME " )
- private String custName ;
- ....
- // getter & setter
- }
完成这样的标注定义后,我们再用回上面的 ModelValueUtils.setValues(),就完全搞定了!
可以看到上一节所帖的setValues()的实现代码片段,其中有一行:
- Map propAliasMap = getPropertyAliasMap ( dest , " alias_as_key " ) ;
这行就是先对dest对象进行了Annotation预分析,将定义了别名的属性记录下来,生成一张映射对应表即可.
然后,在将src对象转换成Map时,会使用到这张别名映射表,最终生成的值Map对象,就可以直接为beanutils.populate()方法所用了.
这样我们就成功解决了本节的任务:值copy时的key映射问题.
有两个延伸出来的提示点:
这点我在实际应用中,也有所考虑,并做了相应的AliasMap缓存处理,对于同一类型的对象,不会每次都去分析.
这里我也预留了一个接口,类似于JdbcTemplate的RowMapper处理方式,代码如下:
- public interface PropertyAliasMapper {
- public HashMap < String , String > getPropertyAliasMap ( Object obj , String key ) throws Exception ;
- }
使用它,可以自已对目标Bean的所有property进行遍历,批量处理映射关系,返回一个自定义的别名映射表即可.
当然,这时候已经不是基于Annotation进行处理了,而你往往得用Reflection机制自已搞定.如下面的代码:
- class ModelPropertyAliasMapper implements PropertyAliasMapper {
- public HashMap < String , String > getPropertyAliasMap ( Object obj , String key ) throws Exception {
- HashMap < String , String > m = new HashMap < String , String > () ;
- Field [] fields = obj . getClass () . getDeclaredFields () ;
- String alias ;
- for ( Field field : fields ) {
- alias = field . getName () . toUpperCase ()
- if ( key . equals ( " name_as_key " )) {
- m . put ( field . getName () , alias ) ;
- } else {
- m . put ( alias , field . getName ()) ;
- }
- }
- return m ;
- }
- }
这个ModelPropertyAliasMapper的实现,就是将所有property名称,统一映射一个"全大写"的别名.这对于从Oracle数据表中返回的ResultSet就可以直接进行值copy了.
不过,你的字段名组成字母,还是得和property一致.如果你非得加上下划线什么的,就得看看你的编程功力了,能否进行统一分词处理,然后在中间加上下划线了
五,总结一下使用上的代码
1, 如果你在Servlet/Jsp中直接给Bean赋值时,推荐只用这一句:
- ModelValueUtils . setValues ( someBean , request ) ;
2, 如果你在DAO中直接给Bean赋值时,推荐只用这一句:
- ModelValueUtils . setValues ( someBean , rs ) ;
3, 如果你在用Spring的JdbcTemplate,在需要返回特定类型的对象List,不妨看下这个RowMapper实现:
- class ModelRowMapper implements RowMapper {
- private Class cls ;
- public ModelRowMapper ( Class cls ) {
- this . cls = cls ;
- }
- public Object mapRow ( ResultSet rs , int index ) throws SQLException {
- Object model = null ;
- try {
- model = this . cls . newInstance () ;
- ModelValueUtils . setValues ( model , rs ) ;
- } catch ( Exception e ) {
- logger . error ( e , e ) ;
- }
- return model ;
- }
- }
- ...
- ...
- // 调用时,只需这样一行搞定! 而且,这个RowMapper实现是通用的,类型无关的.
- return this . jdbcTemplate . query ( sql , getModelRowMapper ( cls )) ;
- ...
4, 如果你也和我一样在用DWR/Buffalo,解析前端页面的大量Key=Value参数时,推荐用下面的代码:
- Map params = ModelValueUtils . keyValueToMap ( keyValueStr ) ;
至于key=value的生成,前面已经讲了.
或者,你有自已定义好的Bean来做为参数对象,那直接用它:
- ModelValueUtils . setValue ( someBean , keyValueStr ) ;
六,可以待续的部分
本文只讲了关于Bean值copy的辅助类 ModelValueUtils.其实它还有一个扩展类: ModelToSQLUtils,这个工具类从字面上你应该可以猜出它的功能.
ModelToSQLUtils就是基于已经被赋值的bean,生成一些常用的SQL语句,当然它仍然得依赖Annatation机制来标注类似于"表名"或"主键字段名"这样的特征描述.
我后面再单独写一篇来简单介绍一下.它主要就是基于ModelValueUtils来实现的,相对而言就更加简单了.
七,此工具包的开源Repository
开源小工具 J2EE MVC开发辅助包
应用场景:BEAN操作辅助
项目地址:http://code.google.com/p/cokemi-utils-mvc/
发表评论
-
数据库JDBC驱动下载大全
2017-03-26 14:14 22641.数据库驱动下载地址 Cache : http://w ... -
MINA粘包断包专题研究
2015-05-13 00:25 0一、前述: 近期做项目用到了MINA,其中遇到了一个 ... -
Mybatis版PropertyFilter实现
2014-07-03 23:50 1516<!--前段时间看到hibernate的Proper ... -
java字符串应用之表达式解析器
2013-12-26 13:33 5266一、表达式的组成 1、数字 2、运算符:+ - ... -
全文检索Lucene使用与优化
2012-03-22 13:09 991转自http://www.oecp.cn/hi/chengzh ... -
Spring 里JMS和DB的事务集成
2012-02-10 18:59 1717http://www.javaworld.com/jav ... -
Java实现在bmp图像文件中隐藏与导出信息
2011-08-21 00:20 1398BMP图像文件,即所谓的位图文件。在位图中,其表示方式是 ... -
Spring事务配置的五种方式
2011-06-10 20:07 1002前段时间对Spring的事务配置做了比较深入的研究,在此之间对 ... -
spring2.5 mvc common-validator 集成应用
2010-12-10 12:59 2907常常写客服端验证代码,写多了就感觉是否有啥东西可以简化处理的, ... -
通过java2dAPI绘制报表
2010-12-05 21:41 1460/* *只画直线,矩形,椭圆,只能向右下角 ... -
调整 JVM 开关以提高性能
2010-12-04 16:29 1060http://blog.csdn.net/petehero/a ... -
CGlib简单介绍
2010-07-06 21:58 936转载:http://hacker0825.blog.163.c ... -
java开源论坛系统
2010-01-04 22:52 4163java开源论坛系统 ================ m ... -
纯jsp日历
2009-12-16 09:44 1172网上找了一大堆日历,感觉跟自己的想要的有点差别,索性自己修改了 ... -
tomcat6学习笔记( 包括和apache2的集成,集群,SSI,SSL,安全域,嵌入应用程序,访问控制平台和管理平台)
2009-12-15 11:27 2458一.访问tomcat的控制平台和管理平台 首先下载tom ... -
用p6spy来观察Java程序中执行的所有SQL语句
2009-11-17 15:30 2166本想把 p6spy 结合 SQL Pro ... -
有用的ext grid 例子
2009-11-06 14:22 4338有用的ext grid 例子 ... -
Spring安全权限管理(Spring Security)
2009-11-04 14:02 6460Spring Security以前叫做acegi,是后来才成为 ... -
spring事务传播属性与隔离级别
2009-10-20 15:22 2077一、Propagation (事务的传播属性) Pro ... -
一个用Spring AOP实现异常处理和记录程序执行时间的实例
2009-10-20 15:05 31625.11 一个用Sprin ...
相关推荐
在JavaWeb开发中,BeanUtils工具类扮演着重要的角色,它是Apache Commons项目的一部分,具体是Apache Commons BeanUtils库。这个库提供了一系列方便的方法,用于处理JavaBeans,即那些符合JavaBeans规范的对象。在这...
JavaBean和BeanUtils工具类是Java开发中常用的技术,它们主要应用于对象属性的访问和操作。JavaBean是一种规范,用于创建可重用的组件,它的核心特点是在类中定义私有成员变量,并提供对应的getter和setter方法来...
`BeanUtils`工具类是Apache Commons项目中的一个组件,它为Java开发提供了一种便捷的方式来操作JavaBean属性,极大地简化了使用反射API的工作。在Java编程中,JavaBean是一种遵循特定规则的对象,通常用于封装数据并...
在这个例子中,`Source`和`Destination`类有相同的属性,`BeanUtils.copyProperties`会将`Source`对象的所有属性值复制到`Destination`对象中。注意,这种方法要求源对象和目标对象具有相同的属性名,并且这些属性都...
BeanUtils工具.jar包是Apache Commons项目中的一个核心组件,它为Java开发人员提供了一套方便的工具类,用于处理Java Bean对象之间的属性复制、类型转换等常见操作。这个库简化了对象模型之间的数据绑定,特别是在...
下面将详细介绍BeanUtils工具类的核心功能和使用方法。 1. **属性设置与获取** BeanUtils工具类通过反射机制实现了对JavaBean的属性设置。例如,我们有一个User类,包含name和age属性,我们可以用以下方式设置属性...
Spring BeanUtils工具类是Spring框架中的一个重要组成部分,它基于Apache Commons BeanUtils库,提供了一种简单而便捷的方式来处理JavaBean的属性。这个工具类极大地简化了对象之间属性的复制、类型转换以及对...
由于BeanUtils库的广泛适用性和便捷性,它是Java开发者日常开发中不可或缺的一个工具。 综上所述,Apache Commons BeanUtils是一个强大的工具,它通过简洁的API简化了JavaBean的使用,提高了开发效率。1.93版本的...
Java工具类是开发过程中不可或缺的一部分,它们提供了许多实用的功能,帮助开发者提高代码的效率和可维护性。Apache Commons Lang和BeanUtils是两个非常著名的Java工具库,由Apache软件基金会开发和维护。这两个库...
本资源包主要围绕`BeanUtils`工具类的使用进行讲解,旨在帮助开发者更好地理解和应用这个工具类。 首先,`BeanUtils`的核心功能是基于JavaBean规范,它提供了方便的方法来处理Java对象的属性。JavaBean是一种遵循...
在实际开发中,这样的工具类大大提高了代码的可读性和复用性,减少了手动转换和复制的繁琐工作。同时,由于不同的JSON库有不同的性能特性和API设计,选择合适的库并正确使用工具类是提高效率的关键。在使用过程中,...
这个包主要提供用于操作JavaBean的工具类,Jakarta-Common-BeanUtils的主要功能都在这个包里实现。
这篇文章将对比分析Apache BeanUtils、PropertyUtils、Spring BeanUtils以及Cglib BeanCopier这四个常用的Bean复制工具的性能和特点。 首先,Apache BeanUtils是Apache Commons项目的一部分,提供了一系列便捷的...
commons-beanutils-1.8.0.jar beanutils.jar beanutils.jar工具包
解决办法是把commons-beanutils中的org/apache/commons/collections删除,这里上传一个改好可以直接使用的。
`MapUtils`和`BeanUtils`这样的工具类能够帮助我们高效且灵活地进行这种转换。本文将详细探讨这两个工具类的功能以及它们在实际开发中的应用。 `MapUtils`类通常用于将Map对象转换为Java Bean对象,这在我们需要将...
commons-beanutils使用工具包
类必须具有符合小驼峰规范的JavaBean setter和getter。否则无法正常访问类。 类必须是公共可见的,否则会发生访问错误。 效率 在10000000次复制测试中 BeanUtils.copyProperties用时9809毫秒 StaticBeanMapper.copy...
BeanUtils工具是一种方便我们对JavaBean进行操作的工具,是Apache组织下的产品。beanUtils 可以便于对javaBean的属性、对象进行赋值,beanUtils可以将一个MAP集合的数据拷贝到一个javabean对象中。