java學習

          java學習

           

          Form 表單域與 Java 對象屬性的自動裝配功能

          時下很多 Web 框架 都實現了 Form 表單域與 Java 對象屬性的自動裝配功能,該功能確實非常有用,試想如果沒這功能則勢必到處沖積著 request.getParameter() 系列方法與類型轉換方法的調用。重復代碼量大,容易出錯,同時又不美觀,影響市容。

            現在的問題是,這些框架通過什么方法實現自動裝配的?如果不用這些框架我們自己如何去實現呢?尤其對于那些純 JSP/Servlet 應用,要是擁有自動裝配功能該多好啊!本座深知各位之期盼,決定把自動裝配的原理和實現方法娓娓道來。

            實現原理其實比較簡單,主要由以下3個步驟構成:

            1. 通過 request.getParameterMap() 獲取被提交的 Form 的所有表單域的名稱-值映射,其中名稱和值均為字符串類型。
            2. 利用 java.beans.PropertyDescriptor 對象獲取 Java Bean 的所有屬性的名稱及其類型。
            3. 把表單域的名稱與 Bean 的屬性的名稱逐個進行匹配,當找到相匹配的屬性時就調用 Bean 的 setter 方法把表單域的值設置給該 Bean 屬性。當然,因為表單域的值總是字符串類型,很可能與 Bean 屬性的類型不一致,所以在設置 Bean 屬性前要進行必要的類型轉換。

            上面所表述的3點原理不知大家是否完全理解,沒關系,下面我們通過一個具體的表單提交的例子來看一看實際的效果,首先看看待提交的表單頁面及其代碼:



          <form action="checkbean.action" method="post">
              First Name: <input type="text" name="firstName" value="丑">
              <br>
              Last Name: <input type="text" name="lastName" value="怪獸">
              <br>
              Birthday: <input type="text" name="birthday" value="1978-11-03">
              <br>
              Gender: 男 <input type="radio"" name="gender" value="false">
                  &nbsp;女 <input type="radio"" name="gender" value="true" checked="checked">
              <br>
              Working age: <select name="working-Age">
                  <option value="-1">-請選擇-</option>
                  <option value="3">三年</option>
                  <option value="5" selected="selected">五年</option>
                  <option value="10">十年</option>
                  <option value="20">二十年</option>
              </select>
              <br>
              Interest: 游泳 <input type="checkbox" name="its" value="1" checked="checked">
                  &nbsp;打球 <input type="checkbox" name="its" value="2" checked="checked">
                  &nbsp;下棋 <input type="checkbox" name="its" value="3">
                  &nbsp;打麻將 <input type="checkbox" name="its" value="4">
                  &nbsp;看書 <input type="checkbox" name="its" value="5" checked="checked">
              <br>
          <br>
          <input type="submit" value="確 定">&nbsp;&nbsp;<input type="reset" value="重 置">
          </form>


          從上圖可以看出,總共有6個表單域,其名稱-值分別是:{"firstName" - "丑","lastName" - "怪獸","birthday" - "1978-11-03","gender" - "女","working-Age" - "5","its" - "1,2,5"},該表單需要提交給 checkbean.action 進行處理(請注意:不要一看到 .aciton 就以為是 struts2,騎白馬的不一定都是唐僧!),下面來看看 CheckBean Action 的處理代碼和 Bean 的定義:
          import java.util.HashMap;
          import java.util.Map;

          import vo.Persion;

          import com.bruce.mvc.ActionSupport;

          public class CheckBean extends ActionSupport
          {
              @Override
              public String execute()
              {
                  // 如果表單元素的名稱和 Form Bean 屬性名不一致則使用 keyMap 進行映射
                  // key: 表單元素名稱, value: Form Bean 屬性名
                  Map<String, String> keyMap = new HashMap<String, String>();
                  keyMap.put("working-Age", "workingAge");
                  keyMap.put("its", "interest");
                  
                  /* 自動裝配方法一 */
                  // 使用表單元素創建 Form Bean
                  // 如果表單元素的名稱和 Form Bean 屬性名完全一致則不需使用 keyMap 進行映射
                  Persion p = createFormBean(Persion.class, keyMap);
                  
                  /* 自動裝配方法二 */
                  // 先創建 Form Bean 對象, 然后再填充它的屬性
                  Persion p2 = new Persion();
                  fillFormBeanProperties(p2, keyMap);
                  
                  // 可以獲取 Form Bean 的所有屬性值
                  //Map<String, Object> result = BeanHelper.getProperties(p);
                  
                  // 把 p 設置為 request 屬性,并最終在結果頁面展示
                  setRequestAttribute("persion", p);
                  
                  return SUCCESS;
              }
          }


          import java.util.Date;
          import java.util.List;

          public class Persion
          {
              private String firstName;
              private String lastName;
              private Date birthday;
              private boolean gender;
              private int workingAge;
              private int[] interest;
              private List<String> photos;

              // getter 和 setter 方法
              // (略)。。。。。。
          }


          從 CheckBean 的代碼可以看出,它是通過 createFormBean() 或 fillFormBeanProperties() 方法來自動裝配 Persion 的,它們之間的區別是:前者會直接創建新的 Persion 對象,而后者填充原有 Persion 對象的屬性。請注意,如果表單域的名稱與 Persion 對應的屬性名不一致則用 keyMap 進行映射,如表單域 "working-Age" 是對應 Persion 的 workingAge 屬性的,但它們的名稱不一致,所以要進行映射。另外,Persion 有一個 photos 屬性,而我們的表單域卻沒有,自動裝配時會忽略該屬性。最后看一下輸出的結果頁面及其代碼:



          <body>
            <br>
            <div align="right">
                <a href="index.action"><u:msg key="jsp-set_locale.back-to-index"/></a>
            </div>
              <br><br><br><br>
              <div align="center">
              <table border="1">
              <caption>Persion Attributs</caption>
              
                  <tr><td>Name</td><td><c:out value="${persion.firstName} ${persion.lastName}"/>&nbsp;</td></tr>
                  <tr><td>Brithday</td><td><c:out value="${persion.birthday}"/>&nbsp;</td></tr>
                  <tr><td>Gender</td><td><c:out value="${persion.gender}"/>&nbsp;</td></tr>
                  <tr><td>Working Age</td><td><c:out value="${persion.workingAge}"/>&nbsp;</td></tr>
                  <tr><td>Interest</td><td><c:forEach var="its" items="${persion.interest}">
                                               <c:out value="${its}" /> &nbsp;
                                        </c:forEach>&nbsp;</td></tr>
                  <tr><td>Photos</td><td><c:forEach var="p" items="${persion.photos}">
                                               <c:out value="${p}" /><br>
                                        </c:forEach>&nbsp;</td></tr>
              </table>
             </div>
            </body>

          通過上面的例子可以看到,通過自動裝配 Bean,我們獲得了非常大的便利。現在我們就從createFormBean() 和 fillFormBeanProperties() 開始,逐步揭開自動裝配的神秘面紗,先看看下面兩個類及其方法的定義:

          package com.bruce.mvc;

          import com.bruce.util.http.HttpHelper;

          /** {@link Action} 對象公共基類 */
          public class ActionSupport implements Action
          {
              private ServletContext servletContext;
              private HttpServletRequest request;
              private HttpServletResponse response;
              private HttpSession session;

              /** 默認 {@link Action} 入口方法(返回 {@link Action#SUCCESS}) */
              public String execute()
              {
                  return SUCCESS;
              }

              /** 使用表單元素創建 Form Bean (表單元素的名稱和 Form Bean 屬性名完全一致) */
              public final <T> T createFormBean(Class<T> clazz)
              {
                  return HttpHelper.createFormBean(request, clazz);
              }

              /** 使用表單元素創建 Form Bean (用 keyMap 映射與表單元素名稱不對應的 Form Bean 屬性) */
              public final <T> T createFormBean(Class<T> clazz, Map<String, String> keyMap)
              {
                  return HttpHelper.createFormBean(request, clazz, keyMap);
              }
              
              /** 使用表單元素填充 Form Bean (表單元素的名稱和 Form Bean 屬性名完全一致) */
              public final <T> void fillFormBeanProperties(T bean)
              {
                  HttpHelper.fillFormBeanProperties(request, bean);
              }
              
              /** 使用表單元素填充 Form Bean (用 keyMap 映射與表單元素名稱不對應的 Form Bean 屬性) */
              public final <T> void fillFormBeanProperties(T bean, Map<String, String> keyMap)
              {
                  HttpHelper.fillFormBeanProperties(request, bean, keyMap);
              }
              
              // 其它方法
              // (略)。。。
          }


          package com.bruce.util.http;

          import com.bruce.util.BeanHelper;

          /** HTTP 幫助類 */
          public class HttpHelper
          {
              /** 使用表單元素創建 Form Bean (表單元素的名稱和 Form Bean 屬性名完全一致) */
              public final static <T> T createFormBean(HttpServletRequest request, Class<T> clazz)
              {
                  return createFormBean(request, clazz, null);
              }

              /** 使用表單元素創建 Form Bean (用 keyMap 映射與表單元素名稱不對應的 Form Bean 屬性) */
              public final static <T> T createFormBean(HttpServletRequest request, Class<T> clazz, Map<String, String> keyMap)
              {
                  Map<String, String[]> properties = getParamMap(request);
                  return BeanHelper.createBean(clazz, properties, keyMap);
              }
              
              /** 使用表單元素填充 Form Bean (表單元素的名稱和 Form Bean 屬性名完全一致) */
              public final static <T> void fillFormBeanProperties(HttpServletRequest request, T bean)
              {
                  fillFormBeanProperties(request, bean, null);
              }
              
              /** 使用表單元素填充 Form Bean (用 keyMap 映射與表單元素名稱不對應的 Form Bean 屬性) */
              public final static <T> void fillFormBeanProperties(HttpServletRequest request, T bean, Map<String, String> keyMap)
              {
               Map<String, String[]> properties = getParamMap(request);
               BeanHelper.setProperties(bean, properties, keyMap);
              }
              
              /** 獲取 {@link HttpServletRequest} 的所有參數名稱和值 */
              public final static Map<String, String[]> getParamMap(HttpServletRequest request)
              {
                  return request.getParameterMap();
              }

              // 其它方法
              // (略)。。。
          }
           哈哈,大家看到了吧,我們迂回了那么久,但 ActionSupport 類和 HttpHelper 類并沒有并沒有做多少事情,他們只是獲取請求參數 Map,并傳遞給 BeanHelper 類的 createBean() 和 setProperties() 方法進行裝配,實際負責裝配工作的是 BeanHelper 。這里解析一下為何要寫得那么迂回,其實這些代碼是從本座自己寫的 “Portal Web 開發框架” 中摘錄出來的,總之一句話:是因為框架的需要而寫得那么迂回的,并非本座有意而為之。順便做下廣告:“Portal Web 開發框架是 一套功能完備的 Web 服務端開發框架,內置 MVC Web 基礎架構,支持可擴展的數據訪問接口(已內置 Hibernate、MyBaits 和 JDBC 支持),集成攔截器、國際化、文件上傳下載和緩存等基礎 Web 服務,基于純 Jsp/Servlet API 實現,非常容易學習和使用尤其適合那些希望使用純 Jsp/Servlet API 進行開發或對 SSH 等主流框架的復雜性感到繁瑣與無奈的人士使用。該框架已通過多個商業項目考驗,并不是寫來玩的哦。如果各位有興趣,本座以后再找個機會開個專貼詳細介紹下這個框架。

            不扯遠了,回到我們的正題,我們再來看看 BeanHelper 的裝配工裝是如何實現的:


          /** Java Bean 幫助類,執行 Java Bean 屬性的 get / set 相關操作 */
          public class BeanHelper
          {
              /** 創建指定類型的 Java Bean,并設置相關屬性
               *
               *  @param clazz        : Bean 類型
               *  @param properties    : 屬性名 / 值映射<br>
               *                        其中名稱為 {@link String} 類型,與屬性名稱可能一直也可能不一致<br>
               *                        屬性值可能為以下 3 中類型:<br>
               *                        &nbsp; &nbsp; 1) 屬性的實際類型:直接對屬性賦值<br>
               *                        &nbsp; &nbsp; 2) {@link String} 類型:先執行自動類型轉換再對屬賦值<br>
               *                        &nbsp; &nbsp; 3) {@link String}[] 類型:先執行自動類型轉換再對屬賦值<br>
               *  @param keyMap        : properties.key / Bean 屬性名映射,當 properties 的 key 與屬性名不對應時,
               *                        用 keyMap 把它們關聯起來
               *  @return                  生成的 Bean實例  
               */
              public static final <B, T> B createBean(Class<B> clazz, Map<String, T> properties, Map<String, String> keyMap)
              {
                  B bean = null;
                  
                  try
                  {
                      // 創建 Bean 實例
                      bean = clazz.newInstance();
                      // 設置 Bean 屬性
                      setProperties(bean, properties, keyMap);
                  }
                  catch(Exception e)
                  {
                      throw new RuntimeException(e);
                  }
                  
                  return bean;
              }
              
              public static final <B, T> B createBean(Class<B> clazz, Map<String, T> properties)
              {
                  return createBean(clazz, properties, null);
              }

              /** 設置 Java Bean 的屬性
               *
               *  @param bean            : Bean 實例
               *  @param properties    : 屬性名 / 值映射<br>
               *                        其中名稱為 {@link String} 類型,與屬性名稱可能一直也可能不一致<br>
               *                        屬性值可能為以下 3 中類型:<br>
               *                        &nbsp; &nbsp; 1) 屬性的實際類型:直接對屬性賦值<br>
               *                        &nbsp; &nbsp; 2) {@link String} 類型:先執行自動類型轉換再對屬賦值<br>
               *                        &nbsp; &nbsp; 3) {@link String}[] 類型:先執行自動類型轉換再對屬賦值<br>
               *  @param keyMap        : properties.key / Bean 屬性名映射,當 properties 的 key 與屬性名不對應時,
               *                        用 keyMap 把它們關聯起來  
               */
              public static final <T> void setProperties(Object bean, Map<String, T> properties, Map<String, String> keyMap)
              {
                  // 獲取所有 Bean 屬性
                  Map<String, PropertyDescriptor> pps = getPropDescMap(bean.getClass());
                  Set<Map.Entry<String, T>> set        = properties.entrySet();
                  
                  // 根據屬性名稱設置 Bean 的每個屬性值
                  for(Map.Entry<String, T> o : set)
                  {
                      String name    = null;    // 屬性名稱
                      String key    = o.getKey();
                      
                      if(keyMap != null)
                          name = keyMap.get(key);
                      if(name == null)
                          name = key;

                      T value    = o.getValue();
                      PropertyDescriptor pd = pps.get(name);    // 名稱對應的 PropertyDescriptor
                      
                      if(pd != null && value != null)
                          // 設置指定屬性值
                          setProperty(bean, pd, value);
                  }
              }

              public static final <T> void setProperties(Object bean, Map<String, T> properties)
              {
                  setProperties(bean, properties, null);
              }

              // 設置指定屬性值
              private static final <T> boolean setProperty(Object bean, PropertyDescriptor pd, T value)
              {
                  // 獲取屬性的 setter 方法
                  Method method = pd.getWriteMethod();
                  // 只處理 public 的實例 setter 方法
                  if(method != null && isPublicInstanceMethod(method))
                  {
                      method.setAccessible(true);
                      
                      Class<?> clazz = pd.getPropertyType();
                      // 設置具體屬性值
                      setProperty(bean, value, method, clazz);
                      
                      return true;
                  }
                  
                  return false;
              }

              // 設置具體屬性值
              private static <T> void setProperty(Object bean, T value, Method method, Class<?> clazz)
              {
                  Object param                = null;
                  Class<?> valueType        = value.getClass();
                  Class<?> valueComType    = valueType.getComponentType();
                  Class<?> clazzComType    = clazz.getComponentType();
                  
                  // 檢查是否需要作類型轉換        
                  if(
                      !clazz.isAssignableFrom(valueType)            &&
                      (    
                          (valueType.equals(String.class))        ||
                          (valueType.isArray() && valueComType.equals(String.class))
                      )                                            &&
                      (    
                          (GeneralHelper.isSimpleType(clazz))        ||
                          (clazz.isArray() && GeneralHelper.isSimpleType(clazzComType))
                      )
                  )
                      // 轉換為目標類型的屬性值
                      param = parseParameter(clazz, value);
                  else
                      param = value;
                  
                  // 調研 setter 方法設置屬性值
                  invokeMethod(bean, method, param);
              }
              
              // 執行類型轉換 (不解釋了,看官們自己參詳吧 ^_^)
              private static final <T> Object parseParameter(Class<?> clazz, T obj)
              {
                  Object param        = null;
                  Class<?> valueType    = obj.getClass();
                  
                  if(clazz.isArray())
                  {
                      String[] value = null;
                      
                      if(valueType.isArray())
                          value    = (String[])obj;
                      else
                      {
                          String str    = (String)obj;
                          StringTokenizer st = new StringTokenizer(str, " ,;\t\n\r\f");
                          value    = new String[st.countTokens()];

                          for(int i = 0; st.hasMoreTokens(); i++)
                              value[i] = st.nextToken();
                      }
                      
                      int length        = value.length;
                      Class<?> type    = clazz.getComponentType();
                      param            = Array.newInstance(type, length);

                      for(int i = 0; i < length; i++)
                      {
                          String v = value[i];
                          Object p = GeneralHelper.str2Object(type, v);
                          Array.set(param, i, p);
                      }
                  }
                  else
                  {
                      String value = null;
                      
                      if(valueType.isArray())
                      {
                          String[] array    = (String[])obj;
                          if(array.length > 0)
                              value = array[0];
                      }
                      else
                          value = (String)obj;
                      
                      param = GeneralHelper.str2Object(clazz, value);
                  }
                  
                  return param;
              }
              
              // 其他方法
              // (略)。。。
          }

          public class GeneralHelper
          {
              /** 簡單數據類型集合 */
              public static final Set<Class<?>> SMIPLE_CLASS_SET    = new HashSet<Class<?>>(18);

              static
              {
                  SMIPLE_CLASS_SET.add(int.class);
                  SMIPLE_CLASS_SET.add(long.class);
                  SMIPLE_CLASS_SET.add(float.class);
                  SMIPLE_CLASS_SET.add(double.class);
                  SMIPLE_CLASS_SET.add(byte.class);
                  SMIPLE_CLASS_SET.add(char.class);
                  SMIPLE_CLASS_SET.add(short.class);
                  SMIPLE_CLASS_SET.add(boolean.class);
                  SMIPLE_CLASS_SET.add(Integer.class);
                  SMIPLE_CLASS_SET.add(Long.class);
                  SMIPLE_CLASS_SET.add(Float.class);
                  SMIPLE_CLASS_SET.add(Double.class);
                  SMIPLE_CLASS_SET.add(Byte.class);
                  SMIPLE_CLASS_SET.add(Character.class);
                  SMIPLE_CLASS_SET.add(Short.class);
                  SMIPLE_CLASS_SET.add(Boolean.class);
                  SMIPLE_CLASS_SET.add(String.class);
                  SMIPLE_CLASS_SET.add(Date.class);
              }

              /** 檢查 clazz 是否為簡單數據類型 */
              public final static boolean isSimpleType(Class<?> clazz)
              {
                  return SMIPLE_CLASS_SET.contains(clazz);
              }

              /** String -> Any,如果 handler 為 null 則把字符串轉換為 8 種基礎數據類型、及其包裝類、 {@link Date} 或 {@link String},
               *                   如果 handler 不為 null 則由 handler 執行轉換
               *
               * @param type    : 目標類型的 {@link Class} 對象
               * @param v        : 要轉換的字符串
               * @param handler    : 類型轉換處理器
               * @return        : 轉換結果,如果轉換不成功返回 null
               * @throws         : 如果目標類型不支持拋出 {@link IllegalArgumentException}
               *
               */
              @SuppressWarnings("unchecked")
              public static final <T> T str2Object(Class<T> type, String v, TypeHandler<T> handler)
              {
                  Object param = null;
                  
                  if(handler != null)
                      return handler.handle(v);
                  
                  if(type == String.class)
                      param =  safeTrimString(v);
                  else if(type == int.class)
                      param =  str2Int_0(v);
                  else if(type == long.class)
                      param =  str2Long_0(v);
                  else if(type == byte.class)
                      param =  str2Byte_0(v);
                  else if(type == char.class)
                      param =  str2Char_0(v);
                  else if(type == float.class)
                      param =  str2Float_0(v);
                  else if(type == double.class)
                      param =  str2Double_0(v);
                  else if(type == short.class)
                      param =  str2Short_0(v);
                  else if(type == boolean.class)
                      param =  str2Boolean_False(v);
                  else if(type == Integer.class)
                      param =  str2Int(v);
                  else if(type == Long.class)
                      param =  str2Long(v);
                  else if(type == Byte.class)
                      param =  str2Byte(v);
                  else if(type == Character.class)
                      param =  str2Char(v);
                  else if(type == Float.class)
                      param =  str2Float(v);
                  else if(type == Double.class)
                      param =  str2Double(v);
                  else if(type == Short.class)
                      param =  str2Short(v);
                  else if(type == Boolean.class)
                      param =  str2Boolean(v);
                  else if(Date.class.isAssignableFrom(type))
                      param =  str2Date(v);
                  else
                      throw new IllegalArgumentException(String.format("object type '%s' not valid", type));
                  
                  return (T)param;
              }
              
              public static final <T> T str2Object(Class<T> type, String v)
              {
                  return str2Object(type, v, null);
              }
              
              // 其他方法
              // (略)。。。
          }
          從上面的代碼可以看出,BeanHelper 支持8種簡單數據類型及其包裝類、String 和 Date 類型以及它們的數組類型的自動裝配,最后強調一下:BeanHelper 和 GeneralHelper 其實是兩個用途非常廣泛的類,其作用不單是為了協助 Form 表單域自動裝配 Bean 。下面列出一些使用例子,幫助大家進一步了解 BeanHelper 的使用方法:
          View Code
           package test;
           
           import java.beans.IntrospectionException;
           import java.util.Date;
           import java.util.HashMap;
           import java.util.Map;
           import java.util.StringTokenizer;
           
           import com.bruce.util.BeanHelper;
           import com.bruce.util.GeneralHelper;
           
           @SuppressWarnings("unused")
           public class TestBeanHelper extends Object
           {
               public static void main(String[] args) throws Exception
               {
                   test();
                   testStr2Object();
                   test_setProperty();
                   test_setProperties_1();
                   test_setProperties_2();
               }
           
               private static void test()
               {
                   //System.out.println(GeneralHelper.str2Date("  1978-11-03  "));
           //System.out.println(GeneralHelper.str2Date("  1978-11-03  "));
           //GeneralHelper.str2Byte(null);
           //GeneralHelper.str2Char_0(null);
           //GeneralHelper.str2Boolean(null);
           //GeneralHelper.str2Boolean_False(null);
               }
           
               private static void testStr2Object() throws IntrospectionException
               {
                   int i = GeneralHelper.str2Object(int.class, "123");
                   Date dt = GeneralHelper.str2Object(Date.class, "1978-11-03");
                   String[] arr = GeneralHelper.str2Object(String[].class, "12, 34, 56, 78", new GeneralHelper.TypeHandler<String[]>()
                   {
                       @Override
                       public String[] handle(String v)
                       {
                           StringTokenizer st = new StringTokenizer(v, " ,;\t\r\n\f");
                           String[] result = new String[st.countTokens()];
                           
                           for(int i = 0; st.hasMoreTokens(); i++)
                               result[i] = st.nextToken();
                           
                           return result;
                       }
                   });
                   
                   // !! error !!
           // String[] arr2 = GeneralHelper.str2Object(String[].class, "12, 34, 56, 78");
               }
           
               private static void test_setProperty()
               {
                   C c = new C();
                   BeanHelper.setProperty(c, "dt", "2010-10-10");
                   BeanHelper.setProperty(c, "i", 456);
                   BeanHelper.setProperty(c, "l", "999");
                   int i = BeanHelper.getProperty(c, "i");
                   double l = BeanHelper.getProperty(c, "l");
                   boolean b = BeanHelper.getProperty(c, "b");
                   Date dt = BeanHelper.getProperty(c, "dt");
                   System.out.println(c);
               }
           
               private static void test_setProperties_1() throws Exception
               {
                   Map<String, String[]> objs = new HashMap<String, String[]>();
                   objs.put("si", new String[] {"888"});
                   objs.put("fi", new String[] {"999"});
                   objs.put("b", new String[] {"true"});
                   objs.put("i", new String[] {"1"});
                   objs.put("l", new String[] {"2.3"});
                   objs.put("dt", new String[] {"2011-09-17"});
                   objs.put("__str", new String[] {"我是怪獸"});
                   objs.put("__ia", new String[] {"12", "34", "56"});
                   objs.put("__sa", new String[] {"ab", "cd", "ef"});
                   
                   Map<String, String> keyMap = new HashMap<String, String>();
                   keyMap.put("__str", "str");
                   keyMap.put("__ia", "ia");
                   keyMap.put("__sa", "sa");
                   
                   C c = BeanHelper.createBean(C.class, objs, keyMap);
                   Map<String, Object> result = BeanHelper.getProperties(c);
                   System.out.println(result);
               }
               
               private static void test_setProperties_2() throws Exception
               {
                   java.sql.Date dt = new java.sql.Date(new java.util.Date().getTime());
                   
                   Map<String, Object> objs = new HashMap<String, Object>();
                   objs.put("si", 888);
                   objs.put("fi", 999);
                   objs.put("b", "True");
                   objs.put("i", 123);
                   objs.put("l", "2.3");
                   //objs.put("dt", new String[] {"2011-09-17"});
                   objs.put("dt", dt);
                   objs.put("str", "我是怪獸");
                   objs.put("ia", new int[] {12, 34, 56});
                   objs.put("sa", "ab, cd, ef");
                   
                   C c = new C();
                   BeanHelper.setProperties(c, objs);
                   Map<String, Object> result = BeanHelper.getProperties(c);
                   System.out.println(result);
               }
               
               
           }
          View Code
           package test;
           
           import java.util.Date;
           
           
           class A
           {
               private boolean b;
           
               public boolean isB()
               {
                   return b;
               }
           
               public void setB(boolean b)
               {
                   this.b = b;
               }
           
           }
           
           public class C extends A
           {
               static int si;
               final int fi = 100;
               
               private int i;
               private Double l;
               private Date dt;
               private String str;
               private int[] ia;
               private String[] sa;
           
               public String[] getSa()
               {
                   return sa;
               }
               public void setSa(String[] sa)
               {
                   this.sa = sa;
               }
               public static int getSi()
               {
                   return si;
               }
               public static void setSi(int si)
               {
                   C.si = si;
               }
               public int getFi()
               {
                   return fi;
               }
               public String getStr()
               {
                   return str;
               }
               public void setStr(String str)
               {
                   this.str = str;
               }
               public int[] getIa()
               {
                   return ia;
               }
               public void setIa(int[] ia)
               {
                   this.ia = ia;
               }
               public int getI()
               {
                   return i;
               }
               public void setI(int i)
               {
                   this.i = i;
               }
               public Double getL()
               {
                   return l;
               }
               public void setL(Double l)
               {
                   this.l = l;
               }
               public Date getDt()
               {
                   return dt;
               }
               public void setDt(Date dt)
               {
                   this.dt = dt;
               }    
           }

          posted on 2013-01-07 09:40 楊軍威 閱讀(4471) 評論(1)  編輯  收藏

          評論

          # re: Form 表單域與 Java 對象屬性的自動裝配功能[未登錄] 2016-03-15 16:11 alex

          沒排版,看著好累  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          常用鏈接

          留言簿

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 潍坊市| 莆田市| 开鲁县| 邯郸县| 宝山区| 新干县| 西林县| 嘉祥县| 渭南市| 靖远县| 济源市| 开阳县| 昭平县| 乌拉特前旗| 新蔡县| 五大连池市| 临夏市| 泊头市| 公安县| 西安市| 嵊泗县| 普格县| 尚义县| 池州市| 隆昌县| 临泽县| 张北县| 长武县| 抚顺市| 鸡泽县| 滦平县| 普兰县| 陇西县| 秭归县| 永安市| 岳普湖县| 五峰| 浪卡子县| 云霄县| 闵行区| 洪雅县|