将用户输入转换为特定的类实例

时间:2011-03-18 08:28:41

标签: java class instantiation

背景

用户在Web表单输入中键入信息,例如:

<input type="text" name="report_name" value="First name" />
<select name="report_date_birthday">
  <option value="2038-01-19">Jan 19, 2038</option>
</select>
<input type="checkbox" name="report_array_colour[]" value="Blue" />Blue
<input type="checkbox" name="report_array_colour[]" value="Red" />Red

这些值最终会传递到报告软件中。报告软件API需要名称为String个实例的名称 - 值对,值为Java类。

问题

子类实现了一个抽象方法(将用户输入类型与Java类相关联),如下所示:

private static final String REPORT_VARIABLE_PREFIX = "report_";

protected Map<String, Class<?>> getPrefixes() {
  Map<String, Class<?>> map = new HashMap<String, Class<?>>();

  map.put( REPORT_VARIABLE_PREFIX + "", java.lang.String.class );
  map.put( REPORT_VARIABLE_PREFIX + "int_", java.lang.Integer.class );
  map.put( REPORT_VARIABLE_PREFIX + "float_", java.math.BigDecimal.class );
  map.put( REPORT_VARIABLE_PREFIX + "array_", java.util.List.class );
  map.put( REPORT_VARIABLE_PREFIX + "date_", java.util.Date.class );
  map.put( REPORT_VARIABLE_PREFIX + "time_", java.sql.Time.class );
  map.put( REPORT_VARIABLE_PREFIX + "timestamp_", java.sql.Timestamp.class );

  return map;
}

所有用户输入均以java.lang.String值提交,report_array_值除外。

问题

忽略report_array_输入值:

  1. 使用用户提供的值实例化映射到用户输入类型的Java类的最有效方法是什么?
  2. 是否有更好的机制来映射用户输入类型,以便更容易实现其代表类?
  3. 是否有更好的方法来表示Web表单中的用户输入类型?
  4. 谢谢!

2 个答案:

答案 0 :(得分:2)

将类型信息放入名称 - 值对的名称中是一种很好的方法。它允许流程自动化。例如,您可以编写一个迭代请求参数的过滤器,为每个参数执行转换,并将新对象存储为请求属性。

此外,每个类(List除外)都包含.valueOf(String)方法,它将为您完成大部分转换。您最好使用SimpleDateFormat来创建时间和日期对象。这样您就可以清理数据了。

答案 1 :(得分:1)

我发现转换值的唯一方法是手动执行:

protected Object convertValue( String prefix, String value ) {
  Class<?> c = getPrefixes().get( prefix );
  Object result = value;

  try {
    if( c == java.lang.String.class ) {
      result = new String( value );
    }
    else if( c == java.sql.Timestamp.class ) {
      result = Timestamp.valueOf( value );
    }
    else if( c == java.sql.Time.class ) {
      result = Time.valueOf( value );
    }
    else if( c == java.util.Date.class ) {
      DateFormat sdf = createDateFormat();
      result = sdf.parse( value );
    }
    else if( c == java.math.BigDecimal.class ) {
      result = new BigDecimal( value );
    }
    else if( c == java.lang.Integer.class ) {
      result = Integer.valueOf( value );
    }
    else if( prefix.equalsIgnoreCase( PARAM_VARIABLE_PREFIX + "array_int_" ) ) {
      result = parseIntegerArray( value );
    }
  }
  catch( Exception e ) {
    throw new RuntimeException( e );
  }

  return result;
}

请注意,这意味着地图不是必需的,因为它会添加一个未使用的复杂层:

  map.put( REPORT_VARIABLE_PREFIX + "", java.lang.String.class );
  map.put( REPORT_VARIABLE_PREFIX + "int_", java.lang.Integer.class );
  map.put( REPORT_VARIABLE_PREFIX + "float_", java.math.BigDecimal.class );
  map.put( REPORT_VARIABLE_PREFIX + "array_", java.util.List.class );
  map.put( REPORT_VARIABLE_PREFIX + "date_", java.util.Date.class );
  map.put( REPORT_VARIABLE_PREFIX + "time_", java.sql.Time.class );
  map.put( REPORT_VARIABLE_PREFIX + "timestamp_", java.sql.Timestamp.class );

由于地图没有为转化过程添加任何值,因此可以将其删除,这意味着convertValue方法变为:

  protected Object convertValue( String prefix, String value ) {
    Object result = value;

    try {
      if( prefix.equalsIgnoreCase( PARAM_VARIABLE_PREFIX + "" ) ) {
        result = new String( value );
      }
      else if( prefix.equalsIgnoreCase( PARAM_VARIABLE_PREFIX + "timestamp_" ) ) {
        result = Timestamp.valueOf( value );
      }
      // ... etc.