使用时间类型?这谁不会不就是javautil下的几个类吗在不加上javasql和javatext下的几个类这会有什么问题吗?Struts要是连时间都处理不了那还能干嘛? 在实际应用中我就发现Struts确实连有些简单的时间都处理不了(不知是我使用的方法不对还是Struts确实没有考虑到)顺便你也能了解Struts是怎么把form里的请求参数populate到ActionForm里面的
今天下午同事告诉我把有javautilDate类型属性的类存入数据库时出错把这个属性删除就没有问题了当时我就想到是RequestProcessor在processPopulate()时出错了因此在它的这个方法设了断点并跟蹤了进去当然它最先要调用ActionForm的reset()方法然后调用实际处理populate(将请求参数传给ActionForm)的RequestUtilspopulate()方法RequestUtils的这个静态方法最先是处理Multipart的(即文件上传等多部分)的方法然后将所有的请求都放在叫properties的HashMap里并循环处理它
names = requestgetParameterNames();
while (nameshasMoreElements()) {
String name = (String) namesnextElement();
String stripped = name;
if (prefix != null) {
if (!strippedstartsWith(prefix)) {
continue;
}
stripped = strippedsubstring(prefixlength());
}
if (suffix != null) {
if (!strippedendsWith(suffix)) {
continue;
}
stripped = strippedsubstring( strippedlength() suffixlength());
}
if (isMultipart) {
propertiesput(stripped multipartParametersget(name));
} else {
propertiesput(stripped requestgetParameterValues(name));
}
}
实际处理它们的是下面的BeanUtilspopulate(bean properties); 其中bean就是接受数据的ActionForm而properties里面则是所有的请求的键-值对(键和值都是字符串http协议的特点)
再看看BeanUtils的静态(类)方法populate是怎么处理的
// Loop through the property name/value pairs to be set
Iterator names = propertieskeySet(erator();
while (nameshasNext()) {
// Identify the property name and value(s) to be assigned
String name = (String) namesnext();
if (name == null) {
continue;
}
Object value = propertiesget(name);
// Perform the assignment for this property
setProperty(bean name value);
}
它是循环所有的请求参数把实际的工作又交给了setProperty方法呵呵弄了半天这帮人原来都是代理
这个方法还是代理吗?计算了一下它有行的代码这么长应该是个实干家了吧错!千万不要被有些人的外表欺骗了!有些人一天上班个小时可够敬业的可有小时在打CS这个类就是一上来多行都在一个if (logisTraceEnabled()){}里面
log在这说明一下Struts中使用的是Jakarta Commons Logging的包它使用的优先级是Logj(念four好像比较有意义大概是Logger For Java的意思我听有的人年Log si J感觉很别扭呵呵)Java Logging APISimple Logging功能是依次减弱
建议在写Action 的execute()或被execute()调用的业务方法中使用Commons Logging 来代替Systemoutprintln()--当要你把成百上千的Systemoutprintln()去掉的时候你就会觉得Commons Logging是个多好的东东了它的用法是
import monsloggingLog;
import monsloggingLogFactory;
private/protected static Log log = LogFactorygetLog(DispatchActionclass);
如果你用的是DispatchAction那你就不要自己定义Log的实例了因为它已经有一个protected的Log实例直接使用即可
使用方法是
if (logisInfoEnabled()) {
logInfo(some information);
}
Logging把消息分为种级别debugerrorfatalinfotracewarn比如你想记录一条消息它只是为了给用户一个警告则可以使用warn为什么在每个logInfo()前做一次判断呢?难道如果log级别不允许InfologInfo()仍然能Info吗?当然不是它的作用是提高效率
比如有个消息是计算前一万个自然数的和(这种消息可能少见)用直接logInfo()
int sum=;
for(int i=;i<;i++){
sum+=i;
}
logInfo(the sum of form to is : _sum);
如果logInfo是不允许的那求个数的和就白求的当然如果你的计算机很快或和高斯一样聪明直接logInfo()也每什么问题
闲话少说回到多行的BeanUtilssetProperty()方法这个方法先是处理nested属性也就是xxxxxx的请求参数我们只看看处理简单属性的必须过程下面这端代码有点长但它只做了一件事将字符串的请求参数转成ActionForm的类型比如你在ActionForm里有个Integer userAge然后HTTP请求参数里可能会有传人的是字符串目标是专程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 (typeisArray() && (index < )) { // Scalar value into array
if (value == null) {
String values[] = new String[];
values[] = (String) value;
newValue = nvert((String[]) values type);
} else if (value instanceof String) {
String values[] = new String[];
values[] = (String) value;
newValue = nvert((String[]) values type);
} else if (value instanceof String[]) {
newValue = nvert((String[]) value type);
} else {
newValue = value;
}
} else if (typeisArray()) { // Indexed value into array
if (value instanceof String) {
newValue = nvert((String) value
typegetComponentType());
} else if (value instanceof String[]) {
newValue = nvert(((String[]) value)[]
typegetComponentType());
} else {
newValue = value;
}
} else { // Value into scalar
if ((value instanceof String) || (value == null)) {
newValue = nvert((String) value type);
} else if (value instanceof String[]) {
newValue = nvert(((String[]) value)[]
type);
} else if (ConvertUtilslookup(valuegetClass()) != null) {
newValue = nvert(valuetoString() type);// Here is my programs break point
} else {
newValue = value;
}
}
最后是调用PropertyUtils的一些方法设置值下面代码的第一种情况是有索引的即你在请求参数里传了field[]=之类的参数第二种是Map类型的传的是map(key)=value之类的参数最一般的就是调用第三个方法
if (index >= ) {
PropertyUtilssetIndexedProperty(target propName
index newValue);
} else if (key != null) {
PropertyUtilssetMappedProperty(target propName