自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Struts form中不能定義日期類型變量的解決

開發(fā) 后端
本文將對(duì)struts form中不能定義日期類型的變量進(jìn)行講解。在實(shí)際應(yīng)用中,Struts確實(shí)連有些簡(jiǎn)單的時(shí)間都處理不了,在本文中會(huì)給出一些解決方法。

Struts form中使用時(shí)間類型?這誰(shuí)不會(huì),不就是java.util下的幾個(gè)類嗎,在不加上java.sql和java.text下的幾個(gè)類,這會(huì)有什么問題嗎?Struts form要是連時(shí)間都處理不了,那還能干嘛?

 在實(shí)際應(yīng)用中,我就發(fā)現(xiàn)Struts form確實(shí)連有些簡(jiǎn)單的時(shí)間都處理不了(不知是我使用的方法不對(duì)還是Struts form確實(shí)沒有考慮到)。順便你也能了解Struts是怎么把form里的請(qǐng)求參數(shù)populate到ActionForm里面的。

今天下午同事告訴我把有java.util.Date類型屬性的類存入數(shù)據(jù)庫(kù)時(shí)出錯(cuò),把這個(gè)屬性刪除就沒有問題了。當(dāng)時(shí)我就想到是RequestProcessor在processPopulate()時(shí)出錯(cuò)了,因此在它的這個(gè)方法設(shè)了斷點(diǎn)并跟蹤了進(jìn)去。當(dāng)然,它***要調(diào)用ActionForm的reset()方法,然后調(diào)用實(shí)際處理populate(將請(qǐng)求參數(shù)傳給ActionForm)的RequestUtils.populate()方法。RequestUtils的這個(gè)靜態(tài)方法***是處理Multipart的(即文件上傳等多部分)的方法,然后將所有的請(qǐng)求都放在叫properties的HashMap里并循環(huán)處理它:

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

實(shí)際處理它們的是下面的:BeanUtils.populate(bean, properties); 其中bean就是接受數(shù)據(jù)的ActionForm,而properties里面則是所有的請(qǐng)求的鍵-值對(duì)(鍵和值都是字符串,http協(xié)議的特點(diǎn))。

再看看BeanUtils的靜態(tài)(類)方法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);

        }

它是循環(huán)所有的請(qǐng)求參數(shù),把實(shí)際的工作又交給了setProperty方法。呵呵,弄了半天,這幫人原來(lái)都是代理。

這個(gè)方法還是代理嗎?計(jì)算了一下它有180行的代碼。這么長(zhǎng)應(yīng)該是個(gè)實(shí)干家了吧,錯(cuò)!千萬(wàn)不要被有些人的外表欺騙了!有些人一天上班16個(gè)小時(shí),可夠敬業(yè)的,可有8小時(shí)在打CS。這個(gè)類就是:一上來(lái)20多行都在一個(gè)if (log.isTraceEnabled()){}里面。

log在這說(shuō)明一下。Struts form中使用的是Jakarta Commons Logging的包,它使用的優(yōu)先級(jí)是:Log4j(4念four好像比較有意義,大概是Logger For Java的意思,我聽有的人年Log si J,感覺很別扭,呵呵),Java 1.4 Logging API,Simple Logging。功能是依次減弱。

建議在寫Action 的execute()或被execute()調(diào)用的業(yè)務(wù)方法中使用Commons Logging 來(lái)代替System.out.println()--當(dāng)要你把成百上千的System.out.println()去掉的時(shí)候你就會(huì)覺得Commons Logging是個(gè)多好的東東了。它的用法是:

import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
        private/protected static Log log = LogFactory.getLog(DispatchAction.class);

如果你用的是DispatchAction,那你就不要自己定義Log的實(shí)例了,因?yàn)樗呀?jīng)有一個(gè)protected的Log實(shí)例,直接使用即可。

Struts form使用方法是:

if (log.isInfoEnabled()) {
             log.Info("some information.");
        }

Logging把消息分為6種級(jí)別,debug,error,fatal,info,trace,warn。比如,你想記錄一條消息,它只是為了給用戶一個(gè)警告,則可以使用warn。為什么在每個(gè)log.Info()前做一次判斷呢?難道如果log級(jí)別不允許Info,log.Info()仍然能Info嗎?當(dāng)然不是。它的作用是提高效率。

比如有個(gè)消息是計(jì)算前一萬(wàn)個(gè)自然數(shù)的和(這種消息可能少見)。用直接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個(gè)數(shù)的和就白求的。當(dāng)然如果你的計(jì)算機(jī)很快或和高斯一樣聰明,直接log.Info()也每什么問題。

閑話少說(shuō),回到180多行的BeanUtils.setProperty()方法。這個(gè)方法先是處理nested屬性,也就是xxx.xxx的請(qǐng)求參數(shù)。我們只看看處理簡(jiǎn)單屬性的必須過(guò)程。下面這端代碼有點(diǎn)長(zhǎng),但它只做了一件事:將字符串的請(qǐng)求參數(shù)轉(zhuǎn)成ActionForm的類型。比如:你在ActionForm里有個(gè)Integer userAge;然后HTTP請(qǐng)求參數(shù)里可能會(huì)有http://localhost:8080/xxx.do?userAge=21。傳人的是字符串,目標(biāo)是專程Integer。

首先它當(dāng)然會(huì)根據(jù)userAge這個(gè)字符串查找相應(yīng)的ActionForm,如果這個(gè)ActionForm有個(gè)屬性也叫userAge,然后就會(huì)把這個(gè)userAge的類型存到type里,type的定義是:Class type = null; 得到type的代碼很長(zhǎng),這是因?yàn)橐紤]很多情況,例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;
            }
        }

***是:調(diào)用PropertyUtils的一些方法設(shè)置值。下面代碼的***種情況是有索引的,即你在請(qǐng)求參數(shù)里傳了field[0]=123之類的參數(shù),第二種是Map類型的,傳的是map(key)=value之類的參數(shù),最一般的就是調(diào)用第三個(gè)方法

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

當(dāng)然還可以在跟蹤下去,不過(guò)和這個(gè)主題沒什么關(guān)系了。大概的流程是:

setProperty()方法再調(diào)用setNestedProperty()方法(還是代理),在調(diào)用setSimpleProperty(),***通過(guò)java.lang.reflect包調(diào)用你在ActionForm里寫的setXXX()方法,如setUserAge(Integer userAge)等。

現(xiàn)在說(shuō)說(shuō)為什么不能populate java.util.Date類型的數(shù)據(jù)。關(guān)鍵是ConvertUtils.convert(),即上文有注釋的地方。如果這個(gè)方法返回的是一個(gè)java.util.Date類型的對(duì)象,當(dāng)然后面都不會(huì)有問題。但我發(fā)現(xiàn)實(shí)際運(yùn)行的結(jié)果是,newValue還是String類型的,因此在后面通過(guò)reflection調(diào)用setXXX時(shí)出錯(cuò)。

你或許會(huì)奇怪ConvertUtils包竟然連java.util.Date都不支持,我也覺得不可思異。我還以為是我使用的不對(duì),然后進(jìn)入這個(gè)類一看,確實(shí)是不支持:

/**
 *

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 $
 */
         

另外,會(huì)不會(huì)即時(shí)是字符串的,org.apache.commons.beanutils.PropertyUtils.setProperty()也有能力處理呢?

于是又寫了個(gè)小程序測(cè)試。

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());
  }
 

運(yùn)行是拋出異常,證明處理不了。

問題找到了,那該怎么解決呢?當(dāng)然最簡(jiǎn)單的方法就是使用ConvertUtils能轉(zhuǎn)的java.sql.DateTime等,比較復(fù)雜一點(diǎn)的方法就是自己寫一個(gè)ConvertUtils。當(dāng)然,如果你把日前存成String,那更沒問題,但如果要將它存入數(shù)據(jù)庫(kù),還得轉(zhuǎn)。尤其在使用DAO模式時(shí),我們可能用BeanUtils.CopyProperties()方法實(shí)現(xiàn)將一個(gè)ActionForm拷貝到一個(gè)DTO(or VO)對(duì)象中時(shí)會(huì)很麻煩。

還有一個(gè)比較好的方法是,屬性定義成java.util.Date,但為Struts form提高另一個(gè)getter/setter方法。這種方法是在middlegen自動(dòng)生成的JSP頁(yè)面看到的。

例如:


             

 private java.util.Date saveDate;
              //普通的set/get方法
              public void setSaveDate(java.util.Date saveDate){
                  this.saveDate=saveDate;
              }
              public java.util.Date getSaveDate(){
                  return this.saveDate;
              }
              //為Struts準(zhǔn)備的方法,時(shí)期的格式假定是 2000-12-31 23:59:59
              public void setSaveDateAsString(String saveDate){
                 java.text.DateFormat dateFormat =new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                 this.saveDate=dateFormat.parse(saveDate);
              }
              public String getSaveDateAsString(){
                 java.text.DateFormat dateFormat =new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                 return dateFormat.Format(this.saveDate);                
       }

              然后在JSP中使用:
              < ?xml:namespace prefix = html />< html:form action="xxx.do">
                < html:text property="saveDateAsString">< /html:text>
              < /html:form>< /pre>

【編輯推薦】

  1. 在Eclipse中開發(fā)struts應(yīng)用程序
  2. 手把手教你在Eclipse中配置開發(fā)Struts
  3. Eclipse下開發(fā)struts完整解決亂碼問題
  4. Struts相關(guān)背景介紹
  5. 使用Easy Struts for Eclipse開發(fā)Struts
責(zé)任編輯:張燕妮 來(lái)源: csdn.net
相關(guān)推薦

2009-06-18 11:37:24

Struts2中ForJavaScript

2010-05-10 15:06:37

Oracle stru

2010-04-27 15:48:23

Oracle stru

2022-03-01 23:31:29

Python編程語(yǔ)言變量

2010-01-25 10:25:19

C++變量

2023-10-31 09:10:39

2009-06-25 15:22:03

Struts2教程一個(gè)form多個(gè)sub

2009-09-21 17:10:14

struts Hibe

2009-06-19 16:05:39

時(shí)間類型Struts

2021-01-05 08:12:42

SQL日期Spt

2011-03-25 11:25:26

Cacti圖像

2009-02-04 11:00:44

2009-12-03 19:06:44

PHP關(guān)鍵字globa

2009-06-05 09:55:50

struts 亂碼Eclipse工具

2009-06-30 14:02:00

Struts亂碼Eclipse

2009-06-05 10:12:36

Struts標(biāo)簽庫(kù)HTML標(biāo)簽

2010-03-18 16:17:29

Python 變量類型

2010-11-26 16:18:13

MySQL變量定義

2010-01-20 09:54:27

C++數(shù)據(jù)類型

2022-03-27 09:06:04

React類型定義前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)