#1. Java默认枚举类存在的问题 Java的枚举类的设计不能很好的满足中文应用的需求,因为它只提供了2个属性:name(String)和ordinal(Integer)。 而我们在应用枚举时通常需要3个属性:
name(String):英文名称,编码时用,可以沿用Java枚举的name。
text(String):枚举文本,用于在页面显示。
value(String):枚举值,用于数据库存储。
以最常见的 Sex(性别) 枚举类来举例:
name:MALE/FEMALE
text:男/女
value:1/2
这是一个在应用中经常遇见的需求,从上面的例子可以看到,text在Java枚举类中没有对应属性,而value用ordinal又不合适。这样我们需要在枚举类中定义text和value两个属性,以满足应用的需求。为了能够统一的处理这样的枚举类型,首先得定义一个枚举类的接口,因为枚举类是内置的不支持继承。
#2. 创建一个枚举类型接口 从上面的需求看到,应用真正需要使用的是text和value两个属性,定义一个枚举类型接口 IEnum,如下:
public interface IEnum {
String getText();
String getValue();
}
创建 Sex (性别)的枚举类,实现IEnum接口,如下:
public enum Sex implements IEnum {
MALE("男", "1"), FEMALE("女", "2");
private String text;
private String value;
private Sex(String text, String value) {
this.text = text;
this.value = value;
}
@Override
public String getText() {
return text;
}
@Override
public String getValue() {
return value;
}
}
#3. 创建对应的转换器 如果使用Hibernate,为了在数据层透明的存取自定义枚举类型,需要创建针对该枚举类型的UserType,可以参考这里 IEnumUserType.java 。
如果使用Spring MVC,为了在表现层透明的传递自定义枚举类型,需要创建针对该枚举类型的Converter,可以参考这里 IEnumToString.java 和 StringToIEnum.java 。
有了转换器,我们就不需要另外编写代码来处理枚举类了,就像在使用一个基本类型变量一样。它可以用来当作Entity属性类型,也可以在页面的下拉列表或单选、多选框组件中方便的使用。
#4. 使用自定义枚举类 在Entity类User中使用Sex枚举类型作为属性,如下:
@Entity
@Table(name = "Tmp_User")
public class User extends UuidEntity {
...
@Type(type = "IEnum")
private Sex sex = Sex.MALE;
...
}
在数据库中存入value值,在页面上展示text值,freemarker中可以这样写:${user.sex.text}。如果需要在页面上显示一个下拉列表让用户选择性别,也很简单:通过Sex.values()方法可以拿到枚举列表,循环枚举列表用value和text值填充options即可。