java枚举自动转换

前后端交互枚举转换

get请求(参数放url)

提供两个接口,分别处理以code(int类型)和name(String类型)进行转换的枚举

public interface IFeIntegerEnum {
	
	int getCode();

	static <E extends Enum<?> & IFeIntegerEnum> Optional<E> codeOf(Class<E> enumClass, int value) {
		return Arrays.stream(enumClass.getEnumConstants()).filter(e -> e.getCode() == value).findAny();
	}
}
public interface IFeStringEnum {
	
	int getName();

	static <E extends Enum<?> & IFeStringEnum> Optional<E> codeOf(Class<E> enumClass, String name) {
		return Arrays.stream(enumClass.getEnumConstants()).filter(e -> e.getName().equals(name)).findAny();
	}
}

然后需要两个枚举转换工厂

@Component
public class IntegerToEnumConvertFactory implements ConverterFactory<String, IFeIntegerEnum> {
	
	@Override
	@Nonnull
	public <T extends IFeIntegerEnum> Converter<String, T> getConverter(@Nonnull Class<T> targetType) {
		return new IntegerToEnum(targetType);
	}

	private static class IntegerToEnum<T extends Enum<T> & IFeIntegerEnum> implements Converter<String, T> {
		
		private final Class<T> type;

		public IntegerToEnum(Class<T> type) {
			this.type = type;
		}
	
		@Override
		public T convert(@Nonnull String source) {
			return IFeIntegerEnum.codeOf(this.type,Integer.parseInt(source)).orElseThrow(IllegalArgumentException::new);
		}
	}
}
@Component
public class StringToEnumConvertFactory implements ConverterFactory<String, IFeStringEnum> {
	
	@Override
	@Nonnull
	public <T extends IFeStringEnum> Converter<String, T> getConverter(@Nonnull Class<T> targetType) {
		return new StringToEnum(targetType);
	}

	private static class StringToEnum<T extends Enum<T> & IFeIntegerEnum> implements Converter<String, T> {
		
		private final Class<T> type;

		public StringToEnum(Class<T> type) {
			this.type = type;
		}
	
		@Override
		public T convert(@Nonnull String source) {
			return IFeStringEnum.codeOf(this.type,source).orElseThrow(IllegalArgumentException::new);
		}
	}
}

还需要在WebMvcConfigurer中配置下

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
		
		@Override
		public void addFormatters(FormatterRegistry registry) {
			registry.addConverterFactory(integerToEnumConvertFactory);
			registry.addConverterFactory(stringToEnumConvertFactory);
		}
}

最后如何看下实际使用

public enum LolEnum implements IFeIntegerEnum,IFeStringEnum { 

	Q(0,"q技能"),
	W(1,"w技能"),
	E(2,"e技能"),
	R(3,"r技能");
	
	private final int code;
	
	private final String name;

	LolEnum (int code,String name){
		this.code = code;
		this.name = name;
	}
	
	@Override
	public int getCode(){
		return code;
	}

	@Override
	public int getName(){
		return name;
	}
}

则此时无论前端传0,1,2,3还是qwer技能到后端,后端用此枚举都能正常转换,注意这是传参放url的形势,比较麻烦,如果放body就很简单了

post请求(参数放body)

此时可以用json工具自动处理,以jackson为例,直接用@JsonCreator和@JsonValue即可

public enum LolEnum { 

	Q(0,"q技能"),
	W(1,"w技能"),
	E(2,"e技能"),
	R(3,"r技能");
	
	private final int code;
	
	private final String name;

	LolEnum (int code,String name){
		this.code = code;
		this.name = name;
	}
	
	/**
	 * 前端传参反序列化为枚举
	 */
	@JsonCreator
	public static LolEnum valueOfCode(int code ) {
		return Arrays.stream(LolEnum.values()).filter(item -> item.getCode() == code).findFirst().orElseThrow(IllegalArgumentException::new);
	}
	
	/**
	 * 序列化到前端时返回数字,同理加到getName上则返回字符串
	 */
	@JsonValue
	public int getCode(){
		return code;
	}

	public int getName(){
		return name;
	}
}

后端与数据库交互枚举转换

public interface IDBIntegerEnum {
	
	int getCode();

	static <E extends Enum<?> & IDBIntegerEnum> Optional<E> codeOf(Class<E> enumClass, int value) {
		return Arrays.stream(enumClass.getEnumConstants()).filter(e -> e.getCode() == value).findAny();
	}
}
@MappedTypes(IDBIntegerEnum.class)
@MappedJdbcTypes(JdbcType.INTEGER)
public class IntegerEnumTypeHandler<E extends Enum<?> & IDBIntegerEnum> extends BaseTypeHandler<E> {

	private final Class<E> type;

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

	/**
	 * 用于定义在Mybatis设置参数时该如何把Java类型参数转换为对应的数据库类型
	 * 
	 * @param ps 当前PreparedStatement对象
	 * @param i 当前参数的位置
	 * @param parameter 当前参数的Java对象
	 * @param jdbcType 当前参数的数据库类型
	 */
	 @Override
	 public void setNonNullParameter(PreparedStatement ps,int i,E parameter,JdbcType jdbcType) throws SQLException {
		ps.setInt(i,parameter.getCode());
	}

	/**
	 * 用于在Mybatis获取数据结果集时如何把数据库类型转换为对应的java类型
	 * 
	 * @param rs 当前的结果集
	 * @param columnName 当前的字段名称
	 * @return 转换后的java对象
	 */
	 @Override
	 public E getNullableResult(ResultSet rs,String columnName) throws SQLException {
		int columnValue = rs.getInt(columnName);
		return rs.wasNull()?null:enumOf(columnValue);
	}

	/**
	 * 用于在Mybatis通过字段位置获取数据结果集时如何把数据库类型转换为对应的java类型
	 * 
	 * @param rs 当前的结果集
	 * @param columnIndex 当前的字段位置
	 * @return 转换后的java对象
	 */
	 @Override
	 public E getNullableResult(ResultSet rs,int columnIndex) throws SQLException {
		int columnValue = rs.getInt(columnIndex);
		return rs.wasNull()?null:enumOf(columnValue);
	}

	/**
	 * 用于在Mybatis在调用存储过程后把数据库类型转换为对应的java类型
	 * 
	 * @param cs 当前CallableStatement
	 * @param columnIndex 当前的字段位置
	 * @return 转换后的java对象
	 */
	 @Override
	 public E getNullableResult(CallableStatement cs,int columnIndex) throws SQLException {
		int columnValue = cs.getInt(columnIndex);
		return rs.wasNull()?null:enumOf(columnValue);
	}

	private E enumOf(int value){
		return IDBIntegerEnum.codeOf(type,value).orElseThrow(()->new IllegalArgumentException("Cannot convert "+value+" to "+type.getSimpleName()+" by code value."));
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值