Java 枚举抽象使用,Mybatis通用枚举约束

1,241 阅读4分钟

开发中,大量的枚举定义风格不一致。统一接口

public interface BaseEnum {
    String getCode();
    String getTitle();
    String getName();
}
import BaseEnum;

public enum StatusEnum implements BaseEnum {

    normal("1", "正常"), delete("0", "删除"), disabled("2", "不可用");

    private String index;
    private String title;

    // 构造方法
    private StatusEnum(String index, String title) {
        this.title = title;
        this.index = index;
    }
    
    //getter,setter

}

Mybatis 类型处理器添加

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.EnumTypeHandler;
import org.apache.ibatis.type.JdbcType;

import BaseEnum;

public class DefaultEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {

	private BaseTypeHandler<E> typeHandler = null;

	public DefaultEnumTypeHandler(Class<E> type) {
		if (type == null) {
			throw new IllegalArgumentException("Type argument cannot be null");
		}
		if (BaseEnum.class.isAssignableFrom(type)) {
			typeHandler = new EnumCodeTypeHandler(type);
		} else {
			typeHandler = new EnumTypeHandler<>(type);
		}
	}

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
		typeHandler.setNonNullParameter(ps, i, parameter, jdbcType);
	}

	@Override
	public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
		return (E) typeHandler.getNullableResult(rs, columnName);
	}

	@Override
	public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		return (E) typeHandler.getNullableResult(rs, columnIndex);
	}

	@Override
	public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		return (E) typeHandler.getNullableResult(cs, columnIndex);
	}
}
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import BaseEnum;

public class EnumCodeTypeHandler<E extends Enum<E> & BaseEnum> extends BaseTypeHandler<E> {

    private final Class<E> type;

	public EnumCodeTypeHandler(Class<E> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter.getCode());
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String code = rs.getString(columnName);
        return rs.wasNull() ? null : codeOf(this.type, code);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String code = rs.getString(columnIndex);
        return rs.wasNull() ? null : codeOf(this.type, code);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String code = cs.getString(columnIndex);
        return cs.wasNull() ? null : codeOf(this.type, code);
    }

    public static <T extends Enum<?> & BaseEnum> T codeOf(Class<T> enumClass, String code) {
        T[] enumConstants = enumClass.getEnumConstants();
        for (T t : enumConstants) {
            if (t.getCode()
                    .equals(code)) {
                return t;
            }
        }
        return null;
    }
}

注册到Mybatis配置类

        //MyBatis configuration
        Configuration configuration = new Configuration();
      
        //...
        configuration.getTypeHandlerRegistry()
                .setDefaultEnumTypeHandler(DefaultEnumTypeHandler.class);

结合Spring Boot使用,参数自动转枚举。转换器是否生效,取决你的配置是否正确

  • 类型转换器
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;

import BaseEnum;

public class EnumConverter<T extends BaseEnum> implements Converter<String, T> {
	private final Class<T> enumType;

	public EnumConverter(Class<T> enumType) {
		this.enumType = enumType;
	}

	@Override
	public T convert(String source) {
		if (StringUtils.isNotBlank(source)) {
			// 得到枚举的所有值
			T[] enums = this.enumType.getEnumConstants();
			for (T e : enums) {
				if (e.getCode().equals(source)) {
					return e;
				}
			}
		}
		throw new IllegalArgumentException("No element matches " + source);
	}
}
  • 添加转换工厂
import java.util.Map;
import java.util.WeakHashMap;

import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;

import BaseEnum;
import EnumConverter;

public class BaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
	private static final Map<Class, Converter> converterMap = new WeakHashMap<>();

	@Override
	public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
		Converter result = converterMap.get(targetType);
		if (result == null) {
			result = new EnumConverter<T>(targetType);
			converterMap.put(targetType, result);
		}
		return result;
	}
}

  • 注册
public class DefaultMvcConfig extends WebMvcConfigurationSupport {

	@Autowired
	ServletContext servletContext;

	@Override
	protected void addInterceptors(InterceptorRegistry registry) {
		super.addInterceptors(registry);
	}

	@Override
	protected void addFormatters(FormatterRegistry registry) {
		registry.addConverter(new DateConverter());
		registry.addConverterFactory(new BaseEnumConverterFactory());
	}

    //...
}

结合fastjson,web接口参数时接收枚举参数,其他json库类似

public enum StatusEnum implements BaseEnum {

    @JSONField(name = "1")
    normal("1", "正常"),
    @JSONField(name = "0")
    delete("0", "删除"),
    @JSONField(name = "1")
    disabled("1", "不可用");

    // ...
}

配上通用的工具类

import BaseEnum;

import java.util.*;

public class EnumUtils {

    private static final String key_code = "code";
    private static final String key_title = "title";
    private static final String key_name = "name";


    public static List<Map<String, Object>> nameTitleMaps(BaseEnum... baseEnums) {
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        for (BaseEnum baseEnum : baseEnums) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_title, baseEnum.getTitle());
            map.put(key_name, baseEnum.getName());
            maps.add(map);
        }
        return maps;
    }

    public static List<Map<String, Object>> nameMaps(BaseEnum... baseEnums) {
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        for (BaseEnum baseEnum : baseEnums) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_name, baseEnum.getName());
            maps.add(map);
        }
        return maps;
    }


    public static List<Map<String, Object>> titleMaps(BaseEnum... baseEnums) {
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        for (BaseEnum baseEnum : baseEnums) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_title, baseEnum.getTitle());
            maps.add(map);
        }
        return maps;
    }


    public static List<Map<String, Object>> maps(BaseEnum... baseEnums) {
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        for (BaseEnum baseEnum : baseEnums) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_code, baseEnum.getCode());
            map.put(key_title, baseEnum.getTitle());
            map.put(key_name, baseEnum.getName());
            maps.add(map);
        }
        return maps;
    }


    public static <T extends BaseEnum> List<Map<String, Object>> nameMaps(Class<T> clazz) {
        if (!clazz.isEnum()) {
            return null;
        }
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        T[] ts = (T[]) clazz.getEnumConstants();
        for (T t : ts) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_name, t.getName());
            maps.add(map);
        }
        return maps;
    }

    public static <T extends BaseEnum> List<Map<String, Object>> titleMaps(Class<T> clazz) {
        if (!clazz.isEnum()) {
            return null;
        }
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        T[] ts = (T[]) clazz.getEnumConstants();
        for (T t : ts) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_title, t.getTitle());
            maps.add(map);
        }
        return maps;
    }

    public static <T extends BaseEnum> List<Map<String, Object>> nameTitleMaps(Class<T> clazz) {
        if (!clazz.isEnum()) {
            return null;
        }
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        T[] ts = (T[]) clazz.getEnumConstants();
        for (T t : ts) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_title, t.getTitle());
            map.put(key_name, t.getName());
            maps.add(map);
        }
        return maps;
    }

    public static <T extends BaseEnum> List<Map<String, Object>> maps(Class<T> clazz) {
        if (!clazz.isEnum()) {
            return null;
        }
        List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
        T[] ts = (T[]) clazz.getEnumConstants();
        for (T t : ts) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(key_code, t.getCode());
            map.put(key_title, t.getTitle());
            map.put(key_name, t.getName());
            maps.add(map);
        }
        return maps;
    }

    public static <T extends BaseEnum> List<T> toList(Class<T> clazz, String... codes) {
        if (codes == null || codes.length == 0 || !clazz.isEnum()) {
            return Collections.emptyList();
        }
        List<T> list = new ArrayList<>(codes.length);
        T[] ts = (T[]) clazz.getEnumConstants();
        for (T t : ts) {
            for (String code : codes) {
                if (t.getCode().equals(code)) {
                    list.add(t);
                }
            }
        }
        return list;
    }
}