在使用 Apache Commons BeanUtils 進行表單綁定、屬性複製時,預設不支援直接將請求參數(字串)轉為 Enum 型別。實作 `org.apache.commons.beanutils.Converter` 介面即可實現通用 Enum 自動轉換。
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
import org.apache.commons.beanutils.Converter;
public class EnumConverter implements Converter {
@Override
public Object convert(Class> type, Object value) {
if (value == null) return null;
if (!type.isEnum()) throw new IllegalArgumentException("目標型別必須是 Enum: " + type);
String strVal = value.toString().trim();
if (strVal.isEmpty()) return null;
try {
// Enum.valueOf 需精確匹配 Enum 常數名稱 (大小寫敏感)
return Enum.valueOf((Class) type, strVal);
} catch (IllegalArgumentException e) {
// 可選:支援忽略大小寫
for (Enum> eNum : type.getEnumConstants()) {
if (eNum.name().equalsIgnoreCase(strVal)) return eNum;
}
throw new ConversionException("無法轉換 '" + strVal + "' 為 " + type.getSimpleName(), e);
}
}
}
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.BeanUtilsBean;
// 1. 註冊 (應用啟動時一次即可)
ConvertUtilsBean convertUtils = new ConvertUtilsBean();
convertUtils.register(new EnumConverter(), Status.class); // 針對特定 Enum
// 或註冊通用 (BeanUtils 1.9.2+ 支援)
convertUtils.register(new EnumConverter(), Enum.class); // 所有 Enum
BeanUtilsBean.getInstance().setConvertUtils(convertUtils);
// 2. 使用範例
public class OrderForm {
private Status status; // Enum: PENDING, PAID, SHIPPED, CANCELLED
// getter/setter
}
// 請求參數 status=PAID 自動轉為 Status.PAID
OrderForm form = new OrderForm();
BeanUtils.populate(form, request.getParameterMap()); // status 字串自動轉 Enum
System.out.println(form.getStatus()); // PAID
若使用 Spring MVC,建議使用內建的 `ConversionService` 或 `@InitBinder` 註冊 `Formatter
@Component
public class EnumFormatter implements Formatter {
@Override public Enum parse(String text, Locale locale) {
return Enum.valueOf((Class) getTargetType(), text.toUpperCase());
}
@Override public String print(Enum object, Locale locale) { return object.name(); }
}
// WebMvcConfigurer
@Override public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldType(Status.class, new EnumFormatter());
}