JAVA教程之简化烦琐的赋值――反射在Jdbc和Struts...
手机用到的是用j2me所编出来的小程序。缘起在Jdbc使用中,我们常常必要有这么样的一个Javabean:当我们从数据库里取值时,我们但愿把对应的值赋给Javabean,尔后再操纵Javabean举行各类营业处置;而我们保留数据的时分,也但愿把经由营业处置后的值赋给Javabean,再由该Javabean与Jdbc交互,将数据保留在数据库里。
而在Struts使用中,我们常常要跟ActionForm或DynaActionForm打交道,比方从业面获得用户输出的数据,在Struts使用中,我们实践上是从ActionForm中获得数据;而将数据显现给用户的时分,我们实践上是将数据赋给ActionForm。在实践的使用中,我们常常也有一其中间的Javabean,用来和ActionForm举行打交道,也就是取值、赋值。
以上两种使用,都必要一其中间的Javabean,从数据源获得数据,赋给Javabean;然后再操纵Javabean举行营业逻辑的处置;最初经由过程赋值,将数据从Javabean交给数据源。
这个中都有以下的赋值历程:
stmt=(OracleCallableStatement)conn.prepareCall("{CallFT_Save_Fabric.ft_fab_colorway_general_insert("+"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}");
stmt.setLong(1,fabric.getBom_id());
stmt.setLong(2,general.getColorway_number());
stmt.setLong(3,general.getColor_number());
stmt.setFloat(4,general.getColorway_type_id());
stmt.setString(5,general.getPrint_id());
stmt.setString(6,general.getPrint_name());
stmt.setFloat(7,general.getPrint_type_id());
stmt.setFloat(8,general.getPrint_repeat_type_id());
stmt.setFloat(9,general.getPrint_repeat_height());
stmt.setLong(10,general.getPrint_repeat_height_uom_id());
stmt.setFloat(11,general.getPrint_repeat_width());
stmt.setLong(12,general.getPrint_repeat_width_uom_id());
stmt.setLong(13,general.getPrint_status_id());
stmt.setString(14,general.getYarn_dye_id());
stmt.setString(15,general.getYarn_dye_name());
stmt.setInt(16,general.getYarn_wrap_color_number());
stmt.setInt(17,general.getYarn_weft_color_number());
stmt.setFloat(18,general.getYarn_repeat_height());
stmt.setLong(19,general.getYarn_repeat_height_uom_id());
stmt.setFloat(20,general.getYarn_repeat_width());
stmt.setLong(21,general.getYarn_repeat_width_uom_id());
stmt.setLong(22,general.getYarn_status_id());
stmt.setLong(23,general.getPrint_process_id());
stmt.execute();
例一
以上是关于针对Jdbc的赋值代码片段,让我们再看一个例子:
publicintsetFabricWebBaseData(DynaActionFormform,HttpServletRequestrequest,LE_FabricBeanbean){
bean.setFabric_no((String)form.get("txtID"));
bean.setBarcode_id((String)form.get("txtBarcodeID"));
bean.setStatus_id(TransformTools.getObjectInt((String)form.get("ddlStatus")));
bean.setMaterial_type_id(TransformTools.getObjectInt((String)form.get("ddlMaterialType")));
bean.setFabric_type_id(TransformTools.getObjectInt((String)form.get("ddlFabricType")));
bean.setFabric_end_use_id(TransformTools.getObjectInt((String)form.get("ddlEndUse")));
bean.setVendor_number((String)form.get("txtArticle"));
bean.setRegion_id(TransformTools.getObjectInt((String)form.get("ddlRegion")));
bean.setCountry_id(TransformTools.getObjectInt((String)form.get("ddlCountry")));
bean.setColor_range_id(TransformTools.getObjectInt((String)form.get("ddlColorRange")));
bean.setPattern_id(TransformTools.getObjectInt((String)form.get("ddlPattern")));
System.out.println("====================>>"+form.get("txtComments"));
bean.setDescription((String)form.get("txtDescription"));
bean.setDetail((String)form.get("txtComments"));
bean.setFormSet_id(TransformTools.getObjectString(request.getParameter("hidFormSetID")));
LIBImageManage.setImageData(request,bean);
return0;
}
例二
很分明,这个例子是关于ActionForm与Javabean之间的赋值。
由下面两个例子,我们能够看到在Jdbc中、或Struts中,Javabean与数据源、Javabean与ActionForm之间的赋值是非常烦琐的,也带来了大批的代码冗余;出格是在一个实践的B/S构架的使用中,我们常常接纳Struts+Jdbc的开辟形式,这个中有大批的Javabean在Jdbc中与数据源之间往返赋值,Javabean与ActionForm之间的往返赋值,二者相加起来,代码的冗余量年夜得惊人,对程序员来讲,举行如许的赋值,切实其实是单调而有趣的。
这么冗杂的代码,我一眼看下往,就发明实在代码的布局都一样,都是从一个对象内里取值,再赋到别的一个对象外头往。如许,我的第一设法是做一个公用的办法,然后我们来举行for轮回挪用。再往下,我就傻眼了,由于不论是哪一个类的取值大概赋值,他们的办法都不是一样的,如例一中,既有stmt.setString,又有stmt.setLong。如许,我们用惯例的办法提取不出一个公用的办法来。
剖析到这里,我感应一种进进逝世胡同的感到。但不论怎样,我能断定办理之道是必定要抽掏出一个公用的办法来,然后经由过程for轮回来挪用该办法。能够断定,成绩是怎样机关出这个公用的办法。
关于这个公用的办法,我们手头有的是:对象、对象的办法名、该办法的参数,而我们必要挪用该办法。说的明白一些,是在运转期内挪用对象的办法。如许,我们就内心有底了,Java的反射机制能办理该成绩。
反射机制的片段回忆
如今我们往返顾一下Java的反射机制:
之以是说是片段回忆,由于我们不盘算把全部Java的反射机制在这里报告一遍,这不是本文的目标。本文的目标是让已进修过Java反射机制的读者大概没有进修过Java反射机制的读者看一个Java反射机制在实践中使用的例子;关于没有进修过Java反射机制的读者来讲,经由过程本文,晓得Java反射机制在实践中是怎样使用的,增添读者进修Java反射机制的热忱,从而进一步深切的进修Java反射机制;关于已进修过Java反射机制的读者来讲,能够经由过程本文,看看Java反射机制在实践中是怎样使用的,进一步深切的了解Java反射,这一点我深有体味,我在进修了Java反射后的很长一段工夫内,没有深切的了解它,进而不晓得怎样在实践顶用到它。
假如读者想深切的进修Java反射机制,能够参考本文所列的参考文章进修,这些文章都是我在进修Java反射机制的时分用过的,能够说是有必定的代表性。
一句话来讲,这里所要报告的Java反射机制,都是在本文中所要用到的Java反射机制。读者在看到本文的成绩的办理思绪时,无妨将实践成绩的办理办法和我行将报告的Java反射机制分离起来看,以增添对Java反射机制的了解。
好,闲话少说,让我们来看一看本文所要用到的Java反射机制:
1.获得对象的Class对象
每个对象都有一个getClass()办法,能够获得该对象的Class对象。如获得对象o的Class对象的代码以下:
Classc=o.getClass();
2.对象的属性
Java反射机制能够发掘对象自己的元数据,好比,对象的父类、对象的属性、对象的办法等等。这里我们来看看Java反射机制是怎样来获得对象的属性的。
有了对象的Class对象,我们就能够用getDeclaredFields()办法来获得该对象一切的属性;我们也能够经由过程某一个属性的属性名来获得该属性,办法为:getDeclaredField(StringfieldName)。如,我们想获得o对象里的一个name属性,代码以下:
Classc=o.getClass();
Fieldf=c.getDeclaredField(“name”);
有了属性对象,我们能够进一步猎取该属性的信息。如属性的感化域,属性的范例等等。我们来看一下怎样获得属性的范例,代码以下:
Classt=f.getType();
如许,我们能够取得属性范例名:
StringtypeName=t.getName();
3.获得对象的办法
下面获得了对象的属性,一样我们也能够获得对象的办法和该办法的元数据,如该办法的感化域、输出参数、前往值范例等等。
getDeclaredMethod(StringfunctionName,Class[]types)
该办法有两个输出参数,第一个是functionName,我们一看就晓得是我们必要猎取的办法的办法名;第二个参数types是一个Class范例的数组对象,是我们必要猎取的办法的输出参数的范例所构成的Class数组。
如,我们想获得o对象的publicStringfunc(Strings,Hashtableht)如许一个办法。
起首我们晓得该办法的办法名为:“func”
上面我们来机关getDeclaredMethod办法的第二个输出参数:
Classptypes[]=newClass;
ptypes=Class.forName("java.lang.String");
ptypes=Class.forName("java.util.Hashtable");
如许,我们就能够获得该办法了:
Methodm=c.getMethod("func",ptypes);
4.运转期内挪用对象的办法
能够说,运转期内挪用对象的办法是Java反射机制的中心地点。
这里所说的运转期内挪用对象的办法,包含运转期内挪用类的机关器,即在运转期内天生类的实例,这在实践的使用中也是非常有效的Java反射机制。但在本文中的例子因为没有利用到,因而不再报告,有乐趣的读者能够到本文前面的参考文献中往进修。
这里重点说一说在运转期内挪用对象的一般办法
invoke(Objecto,Object[]args)
该办法也有两个输出参数:一个是Object对象,就是我们必要在运转期内挪用的办法地点的对象,如下面一向提到的o对象;第二个参数是一个由Object对象构成的数组,是指我们必要在运转期内挪用的办法的实践输出参数。
假如输出参数为”Hello,World!”和null,我们想挪用o对象的publicStringfunc(Strings,Hashtableht)如许一个办法,惯例的挪用体例为:
Strings=o.func(“Hello,World!”,null);
我们使用Java的反射机制在运转期内的挪用体例为:
Objectargs[]=newObject;
arg=newString("Hello,world");
arg=null;
Objectr=m.invoke(obj,arg);
Strings=(String)r;
个中,对象m已经由过程后面的Java反射机制猎取。
到这里,在本文中要用到的Java反射机制就已全体报告了一遍。能够看到,本文真正要用到的关于Java反射机制的常识点并非良多,但Java反射机制如许的一个牛刀小试,就让我们的代码优化了良多,可见Java反射机制切实其实是魅力无量。
成绩的办理
我们先看例一的成绩的处置历程:
经由过程后面的剖析,能够得出,我们必要如许一个公用的办法:在这个办法外头,我们能够供应的输出参数为:
一.Stmt,用来获得table中字段的值。
二.在数据库table中,我们要获得的字段的地位,如例一中是从1到23,我们能够机关一个int型的数组:int[]ports=newint[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
三.Javabean的对象,在例一为:general
四.一个Javabean的属性名所构成数组,跟后面的字段地位逐一对应。在例一中为:String[]propNames=newString[]{“bom_id”,”colorway_number”,”color_number”,”colorway_type_id”,”print_id”,”print_name”,”print_type_id”,”print_repeat_type_id”,”print_repeat_height”,”print_repeat_height_uom_id”,”print_repeat_width”,”print_repeat_width_uom_id”,”print_status_id”,”yarn_dye_id”,”yarn_dye_name”,”yarn_wrap_color_number”,”yarn_weft_color_number”,”yarn_repeat_height”,”yarn_repeat_height_uom_id”,”yarn_repeat_width”,”yarn_repeat_width_uom_id”,”yarn_status_id”,”print_process_id”};能够看出,这些属性名都是Javabean的setXXX()办法对应的属性的称号。
有了下面的四个输出参数,我们但愿挪用了如许一个公用的办法,stmt中的字段的值就会赋到Javabean中响应的属性中往。
能够断定必要机关以下的一个公用的办法:
publicstaticvoidStmtToBean(String[]propNames,Objecto,int[]ports,oracle.jdbc.OracleCallableStatementstmt)
在这个办法里,我们起首要做一个轮回;在轮回体内,我们先从stmt中掏出值来;再赋给Javabean对象o。
我们来看一下实践的代码:
publicstaticvoidStmtToBean(String[]propNames,Objecto,int[]ports,OracleCallableStatementstmt)throwsValueManagerException
{
//起首我们判别属性名数组是不是和字段地位逐一对应,假如不是抛出背例。
if(propNames.length!=ports.length)
{
System.out.println(“inputargswrong:thepropNames’lengthisnotthesamewiththeports’length!”);
ThrownewValueManagerException(“inputargswrong:thepropNames’lengthisnotthesamewiththeports’length!”);
}
try
{
//对属性名数组举行轮回
for(inti=0;i<fieldNames.length;i++)
{
//鄙人面的语句中,我们起首获得属性名propNames;再对Javabean对象o获得它的Class对象,o.getClass();最初经由过程Class对象获得属性名对应的属性。
Fieldf=o.getClass().getDeclaredField(propNames)
//我们经由过程属性获得该属性对应的范例的称号。
Stringtype=f.getType().getName();
//上面的语句作为重点,我们做一个标志,在前面来报告。
ValueSetter.valueToBean(type,Tools.getSetterName(propNames),o,ValueGetter.getStmtValue(type,ports,stmt));语句一
}
}
catch(Exceptione)
{
e.printStackTrace();
}
在下面的语句一中,
我们先看valueToBean办法的输出参数:
第一个参数,type是我们后面获得的属性的范例;
第二个参数,内里有一个getSetterName办法,明显是想获得属性名对应的set办法,我们来看Tools类外头的getSetterName办法,
publicstaticStringgetSetterName(StringpropName)
{
return"set"+propName.substring(0,1).toUpperCase()+propName.substring(1,propName.length());
}
能够看出该办法切实其实是由属性名获得了该属性对应的set办法名;
第三个参数,o是对应的Javabean对象;
第四个参数,外头有一个getStmtValue办法,能够看出该办法是想获得stmt中对应地位的值,我们来看ValueGetter类中的getStmtValue办法的完成:
publicstaticStringgetStmtValue(Stringtype,intport,OracleCallableStatementstmt)
{
try
{
if(type.equals("java.lang.String"))
{
returnstmt.getString(port);
}
elseif(type.equals("int"))
{
returnString.valueOf(stmt.getInt(port));
}
elseif(type.equals("long"))
{
returnString.valueOf(stmt.getLong(port));
}
elseif(type.equals("float"))
{
returnString.valueOf(stmt.getFloat(port));
}
else
{
System.out.println("nosuchtype!");
returnnull;
}
}
catch(Exceptione)
{
e.printStackTrace();
returnnull;
}
}
公然是从stmt中获得对应地位的值。注重:读者能够看到,在该办法中列出的几品种型明显是不敷的,读者能够本人加上其他的范例的取值。
最初,我们来看ValueSetter类的valueToBean办法。我们能够剖析出,该办法的功效是将从数据源stmt中获得的值赋给Javabean对象o对应的字段。
ValueToBean的完成以下:
publicstaticvoidvalueToBean(Stringtype,StringmethodName,Objecto,Stringvalue)
{
try
{
if(Tools.isBlank(s)&&!(type.equals(“String”)))return;
//起首仍是获得o对象对应的Class对象。
Classc=o.getClass();
//关于上面的两个语句,我们也作了标志,在前面报告。
Class[]types=Tools.getTypes(type);语句二
Object[]args=Tools.getArgs(type,value);语句三
//获得Javabean的办法对象。
Methodm=c.getMethod(methodName,types);
//挪用该办法。
m.invoke(o,args);
}
catch(Exceptione)
{
e.printStackTrace();
}
}
我们来看语句二:
明显是用来机关参数范例的Class数组。由于在Javabean中setXXX办法只要一个参数,该参数的范例名为type,以是Tools.getTypes(type)只要一个参数范例type必要机关,getTypes办法的完成以下:
publicstaticClass[]getTypes(Stringtype)
{
if(type.equals("java.lang.String"))
{
returnnewClass[]{String.class};
}
elseif(type.equals("int"))
{
returnnewClass[]{Integer.TYPE};
}
elseif(type.equals("long"))
{
returnnewClass[]{Long.TYPE};
}
elseif(type.equals("float"))
{
returnnewClass[]{Float.TYPE};
}
else
{
System.out.println("nosuchtype!");
returnnull;
}
}
在这个办法外头,一样,没有枚举出来的范例读者能够增补。
语句三是依据invoke办法的必要,机关输出参数值的Object范例的数组,getArgs的完成以下:
publicstaticObject[]getArgs(Stringtype,Stringvalue)
{
if(type.equals("java.lang.String"))
{
returnnewObject[]{newString(value)};
}
elseif(type.equals("int"))
{
returnnewObject[]{newInteger(Integer.parseInt(value))};
}
elseif(type.equals("long"))
{
returnnewObject[]{newLong(Long.parseLong(value))};
}
elseif(type.equals("float"))
{
returnnewObject[]{newFloat(Float.parseFloat(value))};
}
else
{
System.out.println("nosuchtype!");
returnnull;
}
}
以上我们就完全的将例一的成绩的办理思绪剖析了一遍。
如今我们来看挪用该共用办法的例一的代码完成:
stmt=(OracleCallableStatement)conn.prepareCall("{CallFT_Save_Fabric.ft_fab_colorway_general_insert("+"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}");
int[]ports=newint[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
String[]propNames=newString[]{“bom_id”,”colorway_number”,”color_number”,”colorway_type_id”,”print_id”,”print_name”,”print_type_id”,”print_repeat_type_id”,”print_repeat_height”,”print_repeat_height_uom_id”,”print_repeat_width”,”print_repeat_width_uom_id”,”print_status_id”,”yarn_dye_id”,”yarn_dye_name”,”yarn_wrap_color_number”,”yarn_weft_color_number”,”yarn_repeat_height”,”yarn_repeat_height_uom_id”,”yarn_repeat_width”,”yarn_repeat_width_uom_id”,”yarn_status_id”,”print_process_id”};
ValueManager.StmtToBean(propNames,general,ports,stmt);
stmt.execute();
一样,我们对例二的挪用公用办法的完成以下:
publicintsetFabricWebBaseData(DynaActionFormform,HttpServletRequestrequest,LE_FabricBeanbean){
String[]propNames=newString[]{“fabric_no”,”barcode_id”,”status_id”,”material_type_id”,”fabric_type_id”,”fabric_end_use_id”,”vendor_number”,”region_id”,”country_id”,”color_range_id”,”pattern_id”,”detail”,”formSet_id”};
String[]fieldnames=newString[]{"txtID","txtBarcodeID","ddlStatus","ddlMaterialType","ddlFabricType","ddlEndUse","txtArticle","ddlRegion","ddlCountry","ddlColorRange","ddlPattern","txtDescription","txtComments","hidFormSetID"};
ValueManager.formToBean(propNames,bean,fieldnames,form);
LIBImageManage.setImageData(request,bean);
return0;
}
关于公用办法formToBean(String[]propNames,Objecto,String[]fieldNames,DynaActionFormform)的详细完成,我们能够到附录的代码里找到他们,这里就不再报告。
后话
至此,我们已运转Java反射机制来办理了在Jdbc和Struts使用中的一些烦琐的赋值成绩。能够看出,使用Java反射机制,切实其实能使程序代码变得加倍天真与便利。恰是因为这个缘故原由,Java反射机制在一个使用的中心代码里被普遍利用。
在良多时分,我们必要晓得一个由客户输出的类的元数据,在运转期内挪用类的办法,在运转期内实例化一个类,等等都必要用到Java反射机制;另有工场形式假如和Java反射机制分离起来,将加倍天真;Java反射机制和代办署理形式分离起来,构成静态代办署理形式等等。
一句话,Java反射机制让我们的代码加倍的天真与便利,使用的局限非常普遍。
参考文献
1.侯捷概念——Java反射机制
http://editblog.csdn.net/programmer/archive/2004/10/27/806.aspx
2.Java编程的静态性
http://www-900.ibm.com/developerWorks/cn/java/j-dyn0429/index.shtml
3.JavaReflection(JAVA反射)
http://dev.csdn.net/article/58/58798.shtm
附录
其实产生见解的过程就是训练自己发现问题,分析问题的能力。根据以上的认识我想谈下传统的学习与通过视频独立学习的优缺点: 是一种语言,用以产生「小应用程序(Applet(s)) Java是一种计算机编程语言,拥有跨平台、面向对java 是一种语言,用以产生「小应用程序(Applet(s)) 另外编写和运行Java程序需要JDK(包括JRE),在sun的官方网站上有下载,thinking in java第三版用的JDK版本是1.4,现在流行的版本1.5(sun称作J2SE 5.0,汗),不过听说Bruce的TIJ第四版国外已经出来了,是专门为J2SE 5.0而写的。 一般学编程语言都是从C语开始学的,我也不例外,但还是可能不学过程语言而直接学面向对象语言的,你是刚接触语言,还是从C开始学比较好,基础会很深点,如果你直接学习JAVA也能上手,一般大家在学语言的时候都记一些语言的关键词,常有的包和接口等。再去做逻辑代码的编写,以后的学习过程都是从逻辑代码编写中提升的,所以这方面都是经验积累的。你要开始学习就从 有时间再研究一下MVC结构(把Model-View-Control分离开的设计思想) 是一种简化的C++语言 是一种安全的语言,具有阻绝计算机病毒传输的功能 其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。 是一种将安全性(Security)列为第一优先考虑的语言 我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。 你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢? 是一种突破用户端机器环境和CPU 《JAVA语言程序设计》或《JAVA从入门到精通》这两本书开始学,等你编程有感觉的时候也可以回看一下。《JAVA读书笔记》这本书,因为讲的代码很多,也很容易看懂,涉及到面也到位。是你学习技术巩固的好书,学完后就看看《JAVA编程思想》这本书,找找一个自己写的代码跟书上的代码有什么不一样。 关于设计模式的资料,还是向大家推荐banq的网站 http://www.jdon.com/,他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。 设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧 是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言 是一种简化的C++语言 是一种安全的语言,具有阻绝计算机病毒传输的功能 所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。 Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台
页:
[1]