使用时间类型?这谁不会,不就是java.util下的几个类吗,在不加上java.sql和java.text下的几个类,这会有什么问题吗?struts要是连时间都处理不了,那还能干嘛? 在实际应用中,我就发现struts确实连有些简单的时间都处理不了(不知是我使用的方法不对还是struts确实没有考虑到)。顺便你也能了解struts是怎么把form里的请求参数populate到actionform里面的。
今天下午同事告诉我把有java.util.date类型属性的类存入数据库时出错,把这个属性删除就没有问题了。当时我就想到是requestprocessor在processpopulate()时出错了,因此在它的这个方法设了断点并跟踪了进去。当然,它最先要调用actionform的reset()方法,然后调用实际处理populate(将请求参数传给actionform)的requestutils.populate()方法。requestutils的这个静态方法最先是处理multipart的(即文件上传等多部分)的方法,然后将所有的请求都放在叫properties的hashmap里并循环处理它:
names = request.getparameternames();
while (names.hasmoreelements()) {
string name = (string) names.nextelement();
string stripped = name;
if (prefix != null) {
if (!stripped.startswith(prefix)) {
continue;
}
stripped = stripped.substring(prefix.length());
}
if (suffix != null) {
if (!stripped.endswith(suffix)) {
continue;
}
stripped = stripped.substring(0, stripped.length() - suffix.length());
}
if (ismultipart) {
properties.put(stripped, multipartparameters.get(name));
} else {
properties.put(stripped, request.getparametervalues(name));
}
}
实际处理它们的是下面的:beanutils.populate(bean, properties); 其中bean就是接受数据的actionform,而properties里面则是所有的请求的键-值对(键和值都是字符串,http协议的特点)。
再看看beanutils的静态(类)方法populate是怎么处理的:
// loop through the property name/value pairs to be set
iterator names = properties.keyset().iterator();
while (names.hasnext()) {
// identify the property name and value(s) to be assigned
string name = (string) names.next();
if (name == null) {
continue;
}
object value = properties.get(name);
// perform the assignment for this property
setproperty(bean, name, value);
}
它是循环所有的请求参数,把实际的工作又交给了setproperty方法。呵呵,弄了半天,这帮人原来都是代理。
这个方法还是代理吗?计算了一下它有180行的代码。这么长应该是个实干家了吧,错!千万不要被有些人的外表欺骗了!有些人一天上班16个小时,可够敬业的,可有8小时在打cs。这个类就是:一上来20多行都在一个if (log.istraceenabled()){}里面。
log在这说明一下。struts中使用的是jakarta commons logging的包,它使用的优先级是:log4j(4念four好像比较有意义,大概是logger for java的意思,我听有的人年log si j,感觉很别扭,呵呵),java 1.4 logging api,simple logging。功能是依次减弱。
建议在写action 的execute()或被execute()调用的业务方法中使用commons logging 来代替system.out.println()--当要你把成百上千的system.out.println()去掉的时候你就会觉得commons logging是个多好的东东了。它的用法是:
import org.apache.commons.logging.log;
import org.apache.commons.logging.logfactory;
private/protected static log log = logfactory.getlog(dispatchaction.class);
如果你用的是dispatchaction,那你就不要自己定义log的实例了,因为它已经有一个protected的log实例,直接使用即可。
使用方法是:
if (log.isinfoenabled()) {
log.info("some information.");
}
logging把消息分为6种级别,debug,error,fatal,info,trace,warn。比如,你想记录一条消息,它只是为了给用户一个警告,则可以使用warn。为什么在每个log.info()前做一次判断呢?难道如果log级别不允许info,log.info()仍然能info吗?当然不是。它的作用是提高效率。
比如有个消息是计算前一万个自然数的和(这种消息可能少见)。用直接log.info()
int sum=0;
for(int i=0;i<10000;i++){
sum+=i;
}
log.info("the sum of form 1 to 10000 is : "_sum);
如果log.info是不允许的,那求10000个数的和就白求的。当然如果你的计算机很快或和高斯一样聪明,直接log.info()也每什么问题。
闲话少说,回到180多行的beanutils.setproperty()方法。这个方法先是处理nested属性,也就是xxx.xxx的请求参数。我们只看看处理简单属性的必须过程。下面这端代码有点长,但它只做了一件事:将字符串的请求参数转成actionform的类型。比如:你在actionform里有个integer userage;然后http请求参数里可能会有http://localhost:8080/xxx.do?userage=21。传人的是字符串,目标是专程integer。
首先它当然会根据userage这个字符串查找相应的actionform,如果这个actionform有个属性也叫userage,然后就会把这个userage的类型存到type里,type的定义是:class type = null; 得到type的代码很长,这是因为要它考虑很多情况,例如dynaactionform。
// convert the specified value to the required type
object newvalue = null;
if (type.isarray() && (index < 0)) { // scalar value into array
if (value == null) {
string values[] = new string[1];
values[0] = (string) value;
newvalue = convertutils.convert((string[]) values, type);
} else if (value instanceof string) {
string values[] = new string[1];
values[0] = (string) value;
newvalue = convertutils.convert((string[]) values, type);
} else if (value instanceof string[]) {
newvalue = convertutils.convert((string[]) value, type);
} else {
newvalue = value;
}
} else if (type.isarray()) { // indexed value into array
if (value instanceof string) {
newvalue = convertutils.convert((string) value,
type.getcomponenttype());
} else if (value instanceof string[]) {
newvalue = convertutils.convert(((string[]) value)[0],
type.getcomponenttype());
} else {
newvalue = value;
}
} else { // value into scalar
if ((value instanceof string) || (value == null)) {
newvalue = convertutils.convert((string) value, type);
} else if (value instanceof string[]) {
newvalue = convertutils.convert(((string[]) value)[0],
type);
} else if (convertutils.lookup(value.getclass()) != null) {
newvalue = convertutils.convert(value.tostring(), type);// here is my program's break point
} else {
newvalue = value;
}
}
最后是:调用propertyutils的一些方法设置值。下面代码的第一种情况是有索引的,即你在请求参数里传了field[0]=123之类的参数,第二种是map类型的,传的是map(key)=value之类的参数,最一般的就是调用第三个方法。
if (index >= 0) {
propertyutils.setindexedproperty(target, propname,
index, newvalue);
} else if (key != null) {
propertyutils.setmappedproperty(target, propname,
闽公网安备 35060202000074号