??xml version="1.0" encoding="utf-8" standalone="yes"?>在线一区二区视频,国产乱码精品,尤物精品在线http://www.aygfsteel.com/fengtaishao/category/7212.htmlJAVA太极zh-cnWed, 28 Feb 2007 02:51:37 GMTWed, 28 Feb 2007 02:51:37 GMT60Validator 四步?/title><link>http://www.aygfsteel.com/fengtaishao/articles/10138.html</link><dc:creator>风太?/dc:creator><author>风太?/author><pubDate>Mon, 15 Aug 2005 05:23:00 GMT</pubDate><guid>http://www.aygfsteel.com/fengtaishao/articles/10138.html</guid><wfw:comment>http://www.aygfsteel.com/fengtaishao/comments/10138.html</wfw:comment><comments>http://www.aygfsteel.com/fengtaishao/articles/10138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/fengtaishao/comments/commentRss/10138.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/fengtaishao/services/trackbacks/10138.html</trackback:ping><description><![CDATA[<div class="wmqeeuq" id=divarticlecontent> <H3 class=title>Validator 四步?/H3><BR> <P>from:http://www.matrix.org.cn/blog/magicgod/</P><BR> <P>1.<FONT color=red>NewTaskGroupForm</FONT> extends <FONT color=red>ValidatorForm</FONT><BR>q且L<FONT color=red>validate</FONT>函数</P><BR> <P>2.validation.xml:<BR><form name="<FONT color=red>newTaskGroupForm</FONT>"><BR><field property="<FONT color=red>tg_name</FONT>" depends="<FONT color=red>required</FONT>"><BR><arg key="<FONT color=red>label.taskgroup.tg_name</FONT>" position="0"/><BR></field><BR><field property="starttime" depends="long"><BR><arg key="label.taskgroup.starttime" position="0"/><BR></field><BR><field property="interval" depends="long"><BR><arg key="label.taskgroup.interval" position="0"/><BR></field><BR></form><BR>其中QnewTaskGroupForm是抄<FONT color=red>struts-config.xml</FONT><BR>tg_name是字D名Q抄<FONT color=red>NewTaskGroupForm.java</FONT><BR>depends="required"里required是抄<FONT color=red>validation-rules.xml</FONT><BR>label.taskgroup.tg_nameQ抄<FONT color=red>ApplicationResources_zh_CN.properties</FONT><BR>position="0"是指参数位置Q用?errors.long=<FONT color=red>{0}</FONT> 必须输入长整?/P><BR> <P>3.<FONT color=red>ApplicationResources_zh_CN.properties</FONT><BR>q些是字D名Q跟validation.xml对应<BR>label.taskgroup.tg_name=dl名U?BR>label.taskgroup.starttime=开始时?BR>label.taskgroup.interval=每行q行间隔旉</P><BR> <P>以下q些是公׃息,跟validation-rules.xml对应<BR>errors.required=<FONT color=red>{0}</FONT> 不能为空Q必输?BR>errors.long={0} 必须输入长整?/P><BR> <P>4.以上是提交校验,如果需要加入js<BR><html:javascript formName="<FONT color=red>newTaskGroupForm</FONT>"/><BR>注意formName="newTaskGroupForm"要写正确</P><BR> <P>在form上加入onsubmit="return validate<FONT color=red>NewTaskGroupForm</FONT>(this)"<BR>函数名后半部分是formNameQ很有规律的</P></DIV><BR><IFRAME name=articleforum marginWidth=0 marginHeight=0 src="http://www.matrix.org.cn/articleforum.shtml" frameBorder=0 width=700 scrolling=no height=270></IFRAME><img src ="http://www.aygfsteel.com/fengtaishao/aggbug/10138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/fengtaishao/" target="_blank">风太?/a> 2005-08-15 13:23 <a href="http://www.aygfsteel.com/fengtaishao/articles/10138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts源代码阅读(struts 初始化)http://www.aygfsteel.com/fengtaishao/articles/10127.html风太?/dc:creator>风太?/author>Mon, 15 Aug 2005 04:31:00 GMThttp://www.aygfsteel.com/fengtaishao/articles/10127.htmlhttp://www.aygfsteel.com/fengtaishao/comments/10127.htmlhttp://www.aygfsteel.com/fengtaishao/articles/10127.html#Feedback0http://www.aygfsteel.com/fengtaishao/comments/commentRss/10127.htmlhttp://www.aygfsteel.com/fengtaishao/services/trackbacks/10127.htmlhttp://www.matrix.org.cn/resource/article/1/1071.html
说明Q本文可能由Matrix原创Q也可能由Matrix的会员整理,或者由
Matrix的Crawler在全球知名Java或者其他技术相关站Ҏ取ƈ怹
保留镜像QMatrix会保留所有原来的出处URLQƈ在显著地方作明,
如果你发觉出处URL有误Q请联系MatrixҎ.
我在几个月前曄发表q一个帖子,是和大家一起学习struts源代码。成Z名合格的E序员,阅读大量的优UE序是必不可的。只看书是不会让你水qx很大提高的,要多看多写?BR>本来是打等下面几篇文章写好后一起发布的Q这样大家可能才能看得明白些Q但是根据我现在的状况,估计q要一、两个月。所以,Z防止在struts源代码发生过大变化后我的文章没有太大hgQ所以就提前发表了,霍霍~~~
我的email为:mariah_fan@hotmail.comQ有什么不对的地方请大家指正:Q?BR>struts作ؓJ2EE的MVC框架已经取得了很大的成功Q下面将分几文章说明struts源程序的l构?BR>W一?struts的初始化

struts 的核心类是org.apache.struts.action.ActionServletQ这个类会在strutsW一ơ用时Q?BR>作ؓservlet初始化ƈ存入tomcat容器。很昄的,初始化将会调用initҎ初始化相应的数据?BR>
一、initInternal()ҎQ?BR>通过调用MessageResources.getMessageResources(internalName)Ҏ生成一?BR>MessageResourcesc,getMessageResources是通过调用MessageResourcesFactory.
createResources(config)来实现的。至于MessageResourcesFactory是一个abstractc,M
l承自它的类都要实现createResourcesҎQ生成MessageResources对象。整个程序生?BR>MessageResourcesFactory使用了如下技巧:
MessageResourcesFactory.factoryClass = factoryClass;
MessageResourcesFactory.clazz = null;
首先会通过factoryClass来定义一个类全名Q然后通过ClassLoader.loadClass
(factoryClass)Ҏ来生成这个类Qƈ赋给clazzQ然后通过newInstance来生成一个对象?BR>在本E序中,生成MessageResources对象实际是对如下属性进行了初始化:
this.factory = factory;("org.apache.struts.util.PropertyMessageResourcesFactory")
this.config = config;("org.apache.struts.action.ActionResources")
this.returnNull = returnNull;(true/false)

对于MessageResourcescȝ作用是根据不同的Locate来格式化相应的string。或者把你需要改?BR>的string存放到数l中Q然后通过getMessage(Locale locale, String key, Object args[])
Ҏ来格式化。然后把格式好的string存放到HashMap里,q样可以ؓ以后重用。这里的key?BR>使用的locale.toString() + "." + key

在PropertyMessageResources中的loadLocaleҎ用来dresource的初始化信息。首先它?BR>通过一个HashMap这个localKey相关的message是否已经被初始化了,如果被初始化q就?BR>出,的Ҏ是locales.get(localeKey) != null?BR>然后会读取如下一个文Ӟ
org/apache/struts/action/ActionResources_(localKey).propertiesQ然后进行如下操作:
Properties props = new Properties();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
is = classLoader.getResourceAsStream(name);
props.load(is);
Iterator names = props.keySet().iterator();
while (names.hasNext()) {
String key = (String) names.next();
if (log.isTraceEnabled()) {
log.trace(" Saving message key '" + messageKey(localeKey, key));
}
messages.put(messageKey(localeKey, key), props.getProperty(key));
}

PropertyMessageResources 是通过上面的loadLocaleҎ查找与Locale locale, String key
相对对应的Message.查找的次序如下locale.toString()Q然后是
localeKey = localeKey.substring(0, underscore)Q然后是defaultLocaleQ然后是key?BR>
最后,resourcecȝl构如下Q?BR>PropertyMessageResources extends MessageResources
PropertyMessageResourcesFactory extends MessageResourcesFactory

二、initOther()ҎQ?BR>从servlet中获取config和debug两个参数Q然后初始化ConvertUtils对象。由?BR>ConvertUtils.deregister()的初始化Q所有的Converter都是有初始值的Q所以这里Struts自己
把这些初始D|ؓnullQ即转换出错的时候返回nullQ而不是初始倹{用ConvertUtilscȝ
原因是由于从form传输q来的都是Stringcd的|所以我们要把它们{换成相应的类型?BR>
提到几个技巧:
*public boolean isIndexed() {
if (type == null) {
return (false);
//技巧一Q判断是否是一个ArraycȝҎ
} else if (type.isArray()) {
return (true);
//技巧二Q判断type是否是List的一个父cL者父接口Q或者与List为同一个类
//要注意如果List是另一个primitive的TYPEc,那么type必须也是q个cL?BR>//q回trueQ否则都是false。注意long.TYPE与Long.class是不同的
} else if (List.class.isAssignableFrom(type)) {
return (true);
} else {
return (false);
}
}

*//componentType为ArraycL存储的元素的cd
Class componentType = indexedProperty.getClass().getComponentType();
//生成一个新的Array
Object newArray = Array.newInstance(componentType, (index + 1));
System.arraycopy(indexedProperty, 0, newArray, 0, length);
indexedProperty = newArray;
set(name, indexedProperty);
int newLength = Array.getLength(indexedProperty);
for (int i = length; i < newLength; i++) {
Array.set(indexedProperty, i, createProperty(name+"["+i+"]", componentType));
}

三、initServlet()ҎQ?BR>q个Ҏ主要是通过digesterc解析web.xmlQ对String servletMapping属性进行初始化。对?BR>digester说明如下Q这是一个基于DOM的SAX实现的类Q它是事件触发的Q根据xml文g的结构,
每次d一个节点元素就会触发一个事件?BR>
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/web.xml");
q是一个比较少见的Ҏ。首先通过this.servletName = getServletConfig().
getServletName()获取servlet的名Uͼ然后Ҏ
if (servletName.equals(this.servletName)) {
this.servletMapping = urlPattern;
}
来判断当前读到的servlet名称是否是我们运行的servlet的名Uͼ如果是,把url-pattern作ؓ
我们的servletMapping?BR>
四、getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this)
把自己存储到servletContext中,属性名为Globals.ACTION_SERVLET_KEY?BR>
五、ModuleConfig moduleConfig = initModuleConfig("", config)
q个Ҏ使用由initOther()Ҏ获取的configgؓ要解析的xml路径Q用来初始化ModuleConfig?BR>它首先采用与生成MessageResourcesFactory同样的方法生一个MessageResourcesFactory对象Q?BR>MessageResourcesFactoryZ个抽象类Q每一个承它的类都要实现
createModuleConfig(String prefix)Ҏ。本E序使用的缺省的MessageResourcesFactorycMؓ
org.apache.struts.config.impl.DefaultModuleConfigFactoryQ它
的createModuleConfig(String prefix)Ҏ会生成一个ModuleConfigImplcR?BR>
ModuleConfigImplcȝ当于一个JavaBeanQ用来存放一个web模块q行时所需要的配置信息。当
Ӟ一个web模块可以拥有多个ModuleConfigQ但是缺省的是prefix长度?的ModuleConifg。它
的每个属性几乎都是由HashMapl成的,它通过一个configured布尔值来描述当前的ModuleConfig
是否已经被初始化完毕Q在每存放一个属性的时候都会监这个倹{如果初始化完毕而还要改?BR>里面的属性|则会报出IllegalStateException("Configuration is frozen")异常Q现在对?BR>的属性简单说明如下:
* protected HashMap actionConfigsQ?BR>q个HashMap用来存储ActionConfig对象?BR>* protected HashMap dataSources
q个HashMap用来存储DataSourceConfig对象?BR>* protected HashMap exceptions
q个HashMap用来存储ExceptionConfig对象?BR>* protected HashMap formBeans
q个HashMap用来存储FormBeanConfig对象?BR>* protected HashMap forwards
q个HashMap用来存储ForwardConfig对象?BR>* protected HashMap messageResources
q个HashMap用来存储MessageResourcesConfig对象?BR>* protected ArrayList plugIns
q个HashMap用来存储PlugInConfig对象?BR>* protected ControllerConfig controllerConfig
ControllerConfigc?BR>* protected boolean configured
标志q个ModuleConfig?true)?false)配置完成?BR>* protected String prefix
用来标志和区分ModuleConfigc,同时在用上面的configcd始化相应的资源以后,也是?BR>q这个prefix来区分所属的不同的web模块?BR>* protected String actionMappingClass = "org.apache.struts.action.ActionMapping"
ActionMappingcdQ缺省ؓorg.apache.struts.action.ActionMapping?BR>
初始化ModuleConfig的方法如下:
首先是用getServletConfig().getInitParameter("mapping")来获取设定的ActionMappingc?BR>名,然后通过initConfigDigester()Ҏ来生成一个digester。最后用","分隔configQ对每一
块调用parseModuleConfigFile(prefix, paths, config, digester, path)Ҏ解析。注意,q?BR>个方法实际上只有两个参数是有意义的:path为我们要解析的xml文gQconfig用来初始化完?BR>后保存到servletContext中?BR>
如果ModuleConfig中存攄FormBeanConfig为DydamiccdQ那么就调用
DynaActionFormClass.createDynaActionFormClass(FormBeanConfig)初始?BR>DynaActionFormClassQƈ存放到DynaActionFormClass.dynaClasses ?static HashMap中。这
里的key为FormBeanConfig.getName() + moduleConfig.getPrefix()?BR>
如果当前的ModuleConfig为缺省的ModuleConfigQ那么将会调用如下几个方法:
defaultControllerConfig(config)
defaultMessageResourcesConfig(config)
defaultFormBeansConfig(config)
defaultForwardsConfig(config)
defaultMappingsConfig(config)
在struts1.1以后Q这个特例将会被废弃Q?BR>
defaultControllerConfig(config)为ControllerConfig通过getInitParameter(s)Ҏ初始化如
下几个属性:bufferSizeQcontentQlocale(true/false)QmaxFileSizeQnocache(true/false)
QmultipartClassQtempDir?BR>
defaultMessageResourcesConfig(config)为MessageResourcesConfig通过getInitParameter(s)
Ҏ初始化如下几个属性:applicationQfactoryQnull(true/false)?BR>
其它的几个方法就是获取不同的对象Q然后把它们相应的存储到servlet中。关心如下:
ActionFormBeans=>FormBeanConfigQActionForwards=>ForwardConfigQ?BR>ActionMappings=>ActionConfig?BR>
六、initModuleMessageResources(ModuleConfig config)
通过存储在ModuleConfig中的MessageResourcesConfig对象Q逐个初始化MessageResourceQ?BR>然后再把初始化好的MessageResources存放到ServletContext中,attributeName?BR>MessageResourcesConfig.getKey() + ModuleConfig.getPrefix()?BR>
七、initModuleDataSources(ModuleConfig config)
通过存储在ModuleConfig中的DataSourceConfig对象Q逐个初始化DataSource。然后对于每一?BR>DateSource通过BeanUtils.populate(ds, dscs[i].getProperties())Ҏ初始化其属性。再把初
始化好的DateSource存放到ServletContext中,attributeName?BR>DataSourceConfig.getKey() + ModuleConfig.getPrefix()。同时也存放到名位dataSources?BR>FastHashMap中,key为DataSourceConfig.getKey()?BR>
q里q会Ҏ生成的DateSource对象是否是GenericDataSourcecdQ如果是则调?BR>GenericDataSource.open()Ҏ。GenericDataSource是一个非常简单的数据库连接池Q它?BR>open()Ҏ用来初始化连接池Q生成最数目的GenericConnectionQ这里的open()ҎҎ
String driver变量是否为null来判断是否已l被初始化过。需要仔l说明的是getConnection()
ҎQ它首先从连接池中取出GenericConnection对象Q然后检查其是否是可链接的,如果是就
q回Q否则l取出,同时activeCount-1。如果没有取刎ͼ则会查当前可使用?BR>GenericConnection是否辑ֈ最大?activeCount < maxCount)Q如果没有,调用
createConnection()Ҏ声成一个新的GenericConnectionQ然后检查其是否是可链接Q如果可?BR>则返回。returnConnection(GenericConnection conn)Ҏ则是通过把GenericConnection攑֛?BR>q接池,然后activeCount-1?BR>
q个Ҏ中用到了ServletContextWriterc,DateSource的log信息通过q个cd入。对q个
c说明如下:
它承自PrintWriterQ而PrintWriter又承自Writer。WritercL作的事情是在同步的情况?BR>调用abstractҎQabstract public void write(char cbuf[], int off, int len)Q这个方?BR>会Ҏ调用者的需要由调用者实现?BR>PrintWriter则首先通过ensureOpen()Ҏ验这个类中是否有写入的对?WritercL其子c?Q?BR>如果有则Ҏ不同的情况调用这个写入对象的writeҎ(out.write(....))。这个类的print(...)
Ҏ是据不同的情况调用相应的write(...)Ҏ。而println(...)与之的区别就是每ơ多写入一
个换行字W串。还有一个区别是println(...)会根据是否需要autoflushq行flushQ而write(...)
Ҏ不会?BR>ServletContextWritercȝ作用是把字符写入ServletContext中。ServletContextWritercL法中
真正实现了writeҎQ?BR>public void write(char c) {
if (c == '\n')
flush();
else if (c != '\r')
buffer.append(c);
}
public void flush() {
if (buffer.length() > 0) {
context.log(buffer.toString());
buffer.setLength(0);
}
}

八、initModulePlugIns(moduleConfig)
通过存储在ModuleConfig中的PlugInConfig对象Q逐个初始化PlugIn对象Q存攑ֈ一个数l中Q?BR>然后再把q个数组存放到ServletContext中,attributeName?BR>Globals.PLUG_INS_KEY + ModuleConfig.getPrefix()?BR>
Ҏ一个生成的PlugIn对象通过
BeanUtils.populate(plugIns[i], plugInConfigs[i].getProperties())Ҏ初始化其属性。然?BR>再把PlugInConfig对象存放到由其生成的PlugIn对象中?BR>
最后,通过plugIns[i].init(this, (ModuleConfig) config)初始化这个plugIn对象?BR>
九、初始化l束
完成了这个初始化以后Q会调用ModuleConfig.freeze()令这个ModuleConfig变得不可改变。然?BR>会遍历ServletConfig中的initParameterNamesQ如果有?config/"开头的Q则通过q个parameter
的值l初始化其它的ModuleConfigQ且q个ModuleConfig的prefix?config/"后的字符丌Ӏ?BR>
同样调用如下ҎQ?BR>initModuleMessageResources(moduleConfig);
initModuleDataSources(moduleConfig);
initModulePlugIns(moduleConfig);
moduleConfig.freeze();

最后调用destroyConfigDigester()释放内存?


]]>
struts源代码阅读(Commons-Beanutils包)http://www.aygfsteel.com/fengtaishao/articles/10126.html风太?/dc:creator>风太?/author>Mon, 15 Aug 2005 04:28:00 GMThttp://www.aygfsteel.com/fengtaishao/articles/10126.htmlhttp://www.aygfsteel.com/fengtaishao/comments/10126.htmlhttp://www.aygfsteel.com/fengtaishao/articles/10126.html#Feedback0http://www.aygfsteel.com/fengtaishao/comments/commentRss/10126.htmlhttp://www.aygfsteel.com/fengtaishao/services/trackbacks/10126.html摘要Q?BR>既然是说Struts源代码,Z么要讲Commons-Beanutils包呢Q原因很单,Struts的DynaFormBean是通过q个包里的相关类实现的。本文对Commons-Beanutils 源代码进行了分析..


本文Matrix怹镜像Q?A >http://www.matrix.org.cn/resource/article/1/1708_struts.html
说明Q本文可能由Matrix原创Q也可能由Matrix的会员整理,或者由
Matrix的Crawler在全球知名Java或者其他技术相关站Ҏ取ƈ怹
保留镜像QMatrix会保留所有原来的出处URLQƈ在显著地方作明,
如果你发觉出处URL有误Q请联系MatrixҎ.
既然是说Struts源代码,Z么要讲Commons-Beanutils包呢Q原因很单,Struts的DynaFormBean是通过q个包里的相关类实现的。同P留下我的邮箱Q方便和大家共同交流。我的邮是Qmariah_fan@hotmail.com?BR>
Commons-BeanutilsQ一Q?

Commons-Beanutils q个是jakarta commons目中的一个子目。这个项目开发的目的是帮助开发者动态的获取/讑րJava Bean的属性,同时解决每次都要写getXXX和setXXX的麻烦?BR>
一、XXXConvert
q些c都实现Converter接口Q提供把valueD{化成为相应XXXcȝ实现。现在只针对四种cdQ数字,旉QBoolean和String。在Converter 接口中只有一个方法convert(Class type, Object value)Q把value对象转换为type所要求的类。XXXConvertcMq个Ҏ的思\是:
1、如果value==nullQƈ且自己内部有~省的值那么就q回q个~省的倹{如果没有缺省|抛出ConversionException异常?BR>2、如果value instanceOf XXXc,那么q接返回value?BR>3、如果上面的都不行,那么调用new XXX(value.toString())或者XXX.valueOf(value.toString())Ҏ来返回。{化失败时Q抛出ConversionException异常?BR>
二、特D的实现
1、对于ClassConverterc,当进入第三种情Ş的时候,实际执行的是
ClassLoader classLoader =Thread.currentThread().getContextClassLoader();
   if (classLoader == null) {
       classLoader = ClassConverter.class.getClassLoader();
   }
   return (classLoader.loadClass(value.toString()));


2、对于BooleanConverterc,当进入第三种情Ş的时候,实际执行的是Q根据value.toString()的|yesQyQtrue, on, 1 q回trueQnoQnQfalseQoffQ? q回false。如果这些情形都不符合,q且有缺省值的时候则q回~省倹{否则抛出ConversionExceptionQ?BR>
三、XXXArrayConverter
q些cȝ承自AbstractArrayConvertercR?AbstractArrayConverter 实际只实C一个List parseElements(String svalue)Ҏ。这个方法接受的是{value1, value2,...}格式的字W串Q逐个解析出来后,攑օ一个ArrayList中。它通过StreamTokenizer解析字符ԌStreamTokenizer是用来分input stream中读取的字符Ԍq且可以Ҏ标记区分不同的内容,比如数字Q字W或者注释。XXXArrayConverter׃要{换的是一个数l,所以convert(....)Ҏ的实现过E有所不同?BR>1、如果value==nullQƈ且自己内部有~省的值那么就q回q个~省的倹{如果没有缺省|抛出ConversionException异常?BR>2、如果model.getClass() == value.getClass()Q那么就直接q回value?BR>3、如果上面的都不行,那么通过parseElements(value.toString())生成一个数l,再对数组的元素逐个调用new XXX(list.get(i))或者XXX.valueOf(list.get(i))ҎQ{换成为数l对元素要求的类型。{化失败时Q抛出ConversionException异常?BR>
Commons-BeanutilsQ二Q?

一、LocaleConverter ?BaseLocaleConverter
LocaleConverterl承?Converter接口Q定义了一个新Ҏconvert(Class type, Object value, String pattern)?BR>抽象cBaseLocaleConverter实现了LocaleConverter接口。它的locPattern属性用来表C个对象的pattern是否是本地化的格式。patttern 是指把何U格式的旉或者数字D{换成标准倹{convert(...)的执行过E是Q?BR>1、如果value==nullQƈ且自己内部有~省的值那么就q回q个~省的倹{如果没有缺省|抛出ConversionException异常?BR>2、根据参数pattern值是否ؓnullQ调用parse(Object value, String pattern)ҎQ如果这个参C为null那么׃用这个参数的|否则使用对象预存的pattern倹{如果这
样做引v了异常,会首先判断是否能够返回缺省的|不能则抛出ConversionException异常?BR>3、parse(Object value, String
pattern)Ҏ的实现被抛至l承了它的类具体实现。这个方法虽然把valueDqCؓObjectcdQ但是最后都是通过强制转换Q{换成为Stringcd。也是说它实际上需要的
是Stringcd的value?BR>
二?XXXLocaleConverter
把pattern格式的value转换成标准格式的相应的XXXcR这些类可以分ؓ两大c:一cMؓ旉Q一cMؓ数倹{?BR>1、时间类最后都会通过SimpleDateFormatcdD行{换,E序如下Q?BR>
 if(pattern == null) {      
       pattern = locPattern ? new SimpleDateFormat().toLocalizedPattern() :
                 new SimpleDateFormat().toPattern();
   }
   SimpleDateFormat format = new SimpleDateFormat(pattern, locale);
   if (locPattern) {
       formatter.applyLocalizedPattern(pattern);
   }else {
       formatter.applyPattern(pattern);
   }
   return formatter.parse((String) value);


2、数值类最后都会通过DecimalFormatcdD行{换,E序如下Q?BR>
DecimalFormat formatter = (DecimalFormat) DecimalFormat.getInstance(locale);
   if (pattern != null) {
       if (locPattern) {
           formatter.applyLocalizedPattern(pattern);
       } else {
           formatter.applyPattern(pattern);
       }
   }
   return formatter.parse((String) value);

q个转化q程要注意精度的问题。由于NumbercL所有的数值类的父c,所以{换完成后要检查最后的l果是否是当前要求的_ֺQ如果大于所要求的精度,则抛出ConversionException异常?BR>
Commons-BeanutilsQ三Q?/B>

Dyna开头的c,是专门ؓDynaFormBean而设计的?BR>
一、DynaBeanQDynaClass ?DynaProperty
DynaBeanq不是Java中所定义的BeanQ而是一U“假”的Bean。因为它q不是通过getXXX和setXXXҎQ对XXX属性进行取值和讑ր的。它通过一个实CDynaClass接口的类Q帮助管理其所有的属性的cdQ而自己则理对XXX属性值的讑֮和获取。在讑ր的时候会通过与name对应的DynaProperty对象Q检查赋值的cd是否正确?BR>DynaPropertycLq的是DynaBean中所包含的属性的cd。DynaPropertycL三个属性:属性的名称QnameQ属性的名称QtypeQ属性的cdQcontentTypeQ如果DynaProperty描述的是个容器对?List或者Map)Q那么这个contentType׃表这个容器内元素的类别。这个类值得x的地ҎwriteObject和readObjectҎ的实现。它会首先判断自qtype是否是一个primitive的类Q如果是Q则先写入true标志Q再写入对应的primitivecȝ~号Q否则写入false标志Q再写入type。因为在调用readObjectҎӞ如果得出的是primitivecdQ则type的gؓXXX.TYPE而不是XXX.class?BR>DynaClass 是一个接口,用来理DynaBean中所有的DynaProperty属性?BR>
二、BasiceDyanBean ?BasicDynaClass
BasiceDyanBean 实现自DynaBean接口。它包含一个实CDynaClass接口的类的对象,和一个用来存攑ր的HashMap。这个HashMap的key与DynaClass中HashMap的key是一一对应的?BR>BasicDynaClass 实现了DynaClass接口Q以DynaProperty的name为key保存所有这些DynaProperty对象。它通过newInstanceҎ动态生成实CDynaBean接口的类的对象;注意q个cL可以动态指定的Q如果没有,那么是默认的BasicDynaBeancR动态指定类是通过反射实现的,E序如下Q?BR>//dynaBeanClassZQ意的实现了DynaBean接口的类QconstructorTypes?BR>//cȝ构造方法所需要的参数的类?BR>constructor = dynaBeanClass.getConstructor(constructorTypes);
//constructorValues为构造方法的参数|实际上它的gؓ当前的BasicDynaClass
return ((DynaBean) constructor.newInstance(constructorValues));

Commons-BeanutilsQ四Q?/B>

一、ConvertUtils ?ConvertUtilsBean
ConvertUtils 是ConvertUtilsBeancȝ一个简单封装,即ConvertUtils中的所有方法都是通过直接调用ConvertUtilsBean中的同名Ҏ实现的。如果你需要更复杂的功能,׃用ConvertUtilsBeanQ否则用ConvertUtils?BR>ConvertUtilsBean 通过一个HashMap理所有的XXXConverter。这个HashMap的key为XXX的类全名Qgؓ相应的XXXConverter对象。通过deregister()ҎQ初始化q个HashMap。这个初始化Ҏ会ؓ每一个XXXConvertercL供一个缺省的倹{用户可以动qsetDefaultXXX(...)Ҏ来自行设|XXXConverter对象的缺省倹{这个类q提供了convert(...)ҎQ对String valueq行相应的{化?BR>
二、PropertyUtils ?PropertyUtilsBean
PropertyUtils 是PropertyUtilsBeancȝ一个简单封装,同样它的所有方法都是通过直接调用PropertyUtilsBean 中同名方法实现的?BR>PropertyUtilsBean 对DynaBean或者一个java标准Bean中的属性动态的赋值和取?非通过getXXX和setXXXҎ)?BR>1、这个类支持多层嵌套Q比如:XXX[i].YYY(key).ZZZQ那么它会ؓ你得到或者设|ZZZ的属性?BR>2、所有的set/getҎ介绍Q?BR>//对XXX(key)格式的name讑ր?BR>setMappedProperty(Object bean, String name,String key, Object value)
//对XXX[i]格式的name讑ր?BR>setIndexedProperty(Object bean, String name, int index, Object value)
//对XXX格式的name讑ր?BR>setSimpleProperty(Object bean, String name, Object value)
//对XXX(key).YYY[i].ZZZ格式的名U设倹{注意,name必须要遵照这U格式?BR>//q个Ҏ实际做的是以?”ؓ分隔W,逐层的根据情况分别调用上面的几个ҎQ?BR>//获取相应的bean?BR>setNestedProperty(Object bean, String name, Object value)
//它直接调用setNestedPropertyҎ
setProperty(Object bean, String name, Object value)
3、getPropertyType(Object bean, String name)Ҏ中用来获取Bean的某一个property的类型的代码Q?BR>PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
if (descriptor == null) {
return (null);
}else if (descriptor instanceof IndexedPropertyDescriptor) {
return (((IndexedPropertyDescriptor) descriptor).getIndexedPropertyType());
} else if (descriptor instanceof MappedPropertyDescriptor) {
return (((MappedPropertyDescriptor) descriptor).getMappedPropertyType());
} else {
return (descriptor.getPropertyType());
}
4、getIndexedProperty(Object bean, String name, int index)
q个Ҏ用来获取一个数l或者一个List中的属性。它会首先看q个bean是否是DynaBeancd的,如果是,再其查是否有nameq个属性,如果有那么就直接调用get(String name, int index)Ҏq回|如果不是DynaBeancdQ那么就会执行如下方法:
//有没有ؓ数组的某个特定元素取值的Ҏ
if (descriptor instanceof IndexedPropertyDescriptor) {
Method readMethod = ((IndexedPropertyDescriptor) descriptor).
getIndexedReadMethod();
if (readMethod != null) {
Object subscript[] = new Object[1];
subscript[0] = new Integer(index);
return (invokeMethod(readMethod,bean, subscript));
}
}
// 如果没有Q就先取出整个对?BR>Method readMethod = getReadMethod(descriptor);
if (readMethod == null) {
throw new NoSuchMethodException("Property '" + name +
"' has no getter method");
}
Object value = invokeMethod(readMethod, bean, new Object[0]);
//如果q个对象实际上是一个ListQ那么调用get()Ҏ
if (!value.getClass().isArray()) {
if (!(value instanceof java.util.List)) {
throw new IllegalArgumentException("Property '" + name
+ "' is not indexed");
} else {
//get the List's value
return ((java.util.List) value).get(index);
}
//否则通过ArraycL供的相应Ҏ取?BR>} else {
//get the array's value
return (Array.get(value, index));
}

三、BeanUtil ?BeanUtilBean
BeanUtils 是BeanUtilsBeancȝ一个简单封装,同样它的所有方法都是通过直接调用BeanUtilsBean 中同名方法实现的?BR>BeanUtilBean中大多数核心Ҏ都是通过调用PropertyUtilsBean中的Ҏ实现的。而populate(Object bean, Map properties)是自己实现的Q因个赋DE要首先对valueq行格式的{化;q个Ҏ把properties中的key为属性名Qvalue为属性的|分别对应的设值给bean对象。它通过setProperty(Object bean, String name, Object value)Ҏ实现逐个讑ր的。由于此时的value不一定符合bean中name属性的cdQ所以首先要把value转换成合适的|然后再设倹{具体的cd转换Ҏ如下Q?BR>
//q种cd转换的原则是Q如果value是String或者String[]Q那么这个值可能ؓL的类型, 
    //需要进行{换。如果ؓ其它的类型,则不q行M转换?BR>    if (type.isArray() && (index < 0)) {
        // 如果是直接对一个数l赋|则用convert(String values[], Class clazz)Ҏ转换
        if (value == null) {
            String values[] = new String[1];
            values[0] = (String) value;
            newValue = getConvertUtils().convert((String[]) values, type);
        } else if (value instanceof String) {
            String values[] = new String[1];
            values[0] = (String) value;
            newValue = getConvertUtils().convert((String[]) values, type);
        } else if (value instanceof String[]) {
            newValue = getConvertUtils().convert((String[]) value, type);
        } else {
            newValue = value;
        }
    } else if (type.isArray()) {
        // 如果是对数组的某一个元素赋|则用convert(String value, Class clazz)Ҏ转换
        if (value instanceof String) {
            newValue = getConvertUtils().convert((String) value, type.getComponentType());
        } else if (value instanceof String[]) {   
            newValue = getConvertUtils().convert(((String[]) value)[0],type.getComponentType());
        } else {
            newValue = value;     
        }
    } else {                 
        // 否则是一对一的简单赋|则用convert(String value, Class clazz)Ҏ转换
        if ((value instanceof String) || (value == null)) {
            newValue = getConvertUtils().convert((String) value, type);
        } else if (value instanceof String[]) {
            newValue = getConvertUtils().convert(((String[]) value)[0], type);       
        } else if (getConvertUtils().lookup(value.getClass()) != null) {
            newValue = getConvertUtils().convert(value.toString(), type);
        } else {
            newValue = value;        }
    }


]]>
վ֩ģ壺 | ͩ| ͩ| | | Ϫ| | Ӧ| | ͼʲ| | ʡ| | Ƥ| Ϫ| | | | ֲ| | ״| | Ĵʡ| ½| | | ɽ| | ˮ| | | | ҵ| | | | | | | Ѯ| ͼʲ|