本文将对struts form中不能定义日期类型的变量进行讲解。在实际应用中,Struts确实连有些简单的时间都处理不了,在本文中会给出一些解决方法。

Struts form中运用时刻类型?这谁不会,不便是java.util下的几个类吗,在不加上java.sql和java.text下的几个类,这会有什么问题吗?Struts form要是连时刻都处理不了,那还能干嘛?

Struts form中不能界说日期类型变量的处理  struts form 日期类型 第1张

在实践运用中,我就发现Struts form的确连有些简略的时刻都处理不了(不知是我运用的办法不对仍是Struts form的确没有考虑到)。趁便你也能了解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 form中运用的是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实例,直接运用即可。

Struts form运用办法是:

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,
key, newValue);
} else {
PropertyUtils.setProperty(target, propName, newValue);
}

当然还能够在盯梢下去,不过和这个主题没什么关系了。大约的流程是:

setProperty()办法再调用setNestedProperty()办法(仍是署理),在调用setSimpleProperty(),***经过java.lang.reflect包调用你在ActionForm里写的setXXX()办法,如setUserAge(Integer userAge)等。

现在说说为什么不能populate java.util.Date类型的数据。关键是ConvertUtils.convert(),即上文有注释的当地。假如这个办法回来的是一个java.util.Date类型的目标,当然后边都不会有问题。但我发现实践运转的结果是,newValue仍是String类型的,因而在后边经过reflection调用setXXX时犯错。

你或许会古怪ConvertUtils包居然连java.util.Date都不支撑,我也觉得不行思异。我还以为是我运用的不对,然后进入这个类一看,的确是不支撑:

/**
*

Utility methods for converting String scalar values to objects of the
* specified Class, String arrays to arrays of the specified Class. The
* actual {@link Converter} instance to be used can be registered for each
* possible destination Class. Unless you override them, standard
* {@link Converter} instances are provided for all of the following
* destination Classes:


*

    *
  • java.lang.BigDecimal
    *
  • java.lang.BigInteger
    *
  • boolean and java.lang.Boolean
    *
  • byte and java.lang.Byte
    *
  • char and java.lang.Character
    *
  • java.lang.Class
    *
  • double and java.lang.Double
    *
  • float and java.lang.Float
    *
  • int and java.lang.Integer
    *
  • long and java.lang.Long
    *
  • short and java.lang.Short
    *
  • java.lang.String
    *
  • java.sql.Date
    *
  • java.sql.Time
    *
  • java.sql.Timestamp
    *

*
*

For backwards compatibility, the standard Converters for primitive
* types (and the corresponding wrapper classes) return a defined
* default value when a conversion error occurs. If you prefer to have a
* {@link ConversionException} thrown instead, replace the standard Converter
* instances with instances created with the zero-arguments constructor. For
* example, to cause the Converters for integers to throw an exception on
* conversion errors, you could do this:


*

* // No-args constructor gets the version that throws exceptions
* Converter myConverter =
* new org.apache.commons.beanutils.converter.IntegerConverter();
* ConvertUtils.register(myConverter, Integer.TYPE); // Native type
* ConvertUtils.register(myConverter, Integer.class); // Wrapper class
*

*
* @author Craig R. McClanahan
* @author Ralph Schaer
* @author Chris Audley
* @version $Revision: 1.12 $ $Date: 2003/01/15 21:59:38 $
*/

别的,会不会即时是字符串的,org.apache.commons.beanutils.PropertyUtils.setProperty()也有才能处理呢?

所以又写了个小程序测验。

public class SetSimplePropertyTest {
public SetSimplePropertyTest() {
}
public static void main(String[] args) {
SetSimplePropertyTest setSimplePropertyTest1 = new SetSimplePropertyTest();
String dateStr="2004-01-01 19:00:00";
test.DataBean dataBean=new DataBean();
try {
org.apache.commons.beanutils.PropertyUtils.setProperty(dataBean,
"receiveTime", dateStr);
}
catch (Exception e){
e.printStackTrace();
}
System.out.println(dataBean.getReceiveTime().toString());
}

运转是抛出反常,证明处理不了。

问题找到了,那该怎样处理呢?当然最简略的办法便是运用ConvertUtils能转的java.sql.DateTime等,比较复杂一点的办法便是自己写一个ConvertUtils。当然,假如你把日前存成String,那更没问题,但假如要将它存入数据库,还得转。尤其在运用DAO形式时,咱们或许用BeanUtils.CopyProperties()办法实现将一个ActionForm拷贝到一个DTO(or VO)目标中时会很费事。

还有一个比较好的办法是,特色界说成java.util.Date,但为Struts form进步另一个getter/setter办法。这种办法是在middlegen主动生成的JSP页面看到的。

例如:

// 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);

}

0

【修改引荐】

  1. 在Eclipse中开发struts运用程序
  2. 手把手教你在Eclipse中装备开发Struts
  3. Eclipse下开发struts完好处理乱码问题
  4. Struts相关布景介绍
  5. 运用Easy Struts for Eclipse开发Struts
转载请说明出处
知优网 » Struts form中不能界说日期类型变量的处理

发表评论

您需要后才能发表评论