SpringMVC中将前端请求参数转为枚举类并将响应信息中的枚举类转为对应的值
(1)定义一个接口 声名获取枚举中值的方法
public interface IEnum<T> {
T getValue();
}
(2)自定义JsonSerializer和JsonDeserializer
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
public class InstanceOfIEnumJsonDeserializer<T extends IEnum> extends JsonDeserializer<IEnum>
implements Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(InstanceOfIEnumJsonDeserializer.class);
@Override
public IEnum deserialize(JsonParser parser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
final String text = parser.getText();
if (StringUtils.isEmpty(text)) {
return null;
}
JsonStreamContext parsingContext = parser.getParsingContext();
String currentName = parsingContext.getCurrentName();
Object currentValue = parsingContext.getCurrentValue();
Field declaredField = null;
try {
declaredField = currentValue.getClass().getDeclaredField(currentName);
} catch (NoSuchFieldException e) {
LOGGER.error("No such field warning: " + currentName, e);
return null;
}
Class<?> targetType = declaredField.getType();
if (!IEnum.class.isAssignableFrom(targetType)) {
return null;
}
T[] values = (T[]) targetType.getEnumConstants();
for (T t : values) {
if (text.equals(t.getValue().toString())) {
return t;
}
}
return null;
}
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.io.Serializable;
public class InstanceOfIEnumJsonSerializer<T extends IEnum> extends JsonSerializer<IEnum>
implements Serializable {
@Override
public void serialize(IEnum value, JsonGenerator gen, SerializerProvider serializers)
throws IOException, JsonProcessingException {
gen.writeString(value == null ? null : value.getValue().toString());
}
}
(3)写枚举类并实现IEnum接口,重写getValue()方法并且在枚举类上面添加@JsonSerialize和@JsonDeserialize注解分别using上面自定义的JsonSerializer和JsonDeserializer
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@JsonSerialize(using = InstanceOfIEnumJsonSerializer.class)
@JsonDeserialize(using = InstanceOfIEnumJsonDeserializer.class)
public enum ModuleEnum implements IEnum<Integer> {
SSDB(1, "三算对比");
ModuleEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
private Integer value;
private String desc;
@Override
public Integer getValue() {
return this.value;
}
@Override
public String toString() {
return "ModuleEnum{" +
"value=" + value +
", desc='" + desc + '\'' +
'}';
}
}
(4)到此为止,RequestBody中请求参数中枚举值就可以自动转为对应枚举并且响应信息中枚举也可以自动的转为其枚举值 但是Get请求时url中参数还是不可以自动转为枚举的
(5)继续处理get请求枚举转换 实现Converter完成String到IEnum的转换
import org.springframework.util.StringUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.stereotype.Component;
@Component
public class EnumConvertFactory implements ConverterFactory<String, IEnum> {
@Override
public <T extends IEnum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToIEnum<>(targetType);
}
private static class StringToIEnum<T extends IEnum> implements Converter<String, T> {
private Class<T> targerType;
public StringToIEnum(Class<T> targerType) {
this.targerType = targerType;
}
@Override
public T convert(String source) {
if(StringUtils.isEmpty(source)){
return null;
}
for (T t : targerType.getEnumConstants()) {
if (source.equals(String.valueOf(t.getValue()))) {
return t;
}
}
return null;
}
}
}
(6)WebMvcConfigurer配置类中添加自定义的EnumConvertFactory对象
import org.springframework.format.FormatterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Autowired
private EnumConvertFactory enumConvertFactory;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(enumConvertFactory);
}
}
(7)对于Dao层如果是Mybatis-plus的话 我这用的版本是2.x
自定义BaseTypeHandler实现类 重写下面的一堆方法,并且
添加注解@MappedTypes(value = {ModuleEnum.class}) value中添加枚举类
import com.glodon.bim5d.costproject.dao.ModuleEnum;
import com.glodon.cost.IEnum;
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 org.apache.ibatis.type.MappedTypes;
@MappedTypes(value = {ModuleEnum.class})
public class InstanceOfIEnumTypeHandler<E extends IEnum> extends BaseTypeHandler<E> {
private Class<E> type;
public InstanceOfIEnumTypeHandler(Class<E> type) {
this.type = type;
}
public InstanceOfIEnumTypeHandler() {
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
throws SQLException {
if (jdbcType == null) {
ps.setObject(i, parameter.getValue());
} else {
ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
return getByValue(rs.getString(columnName));
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getByValue(rs.getString(columnIndex));
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getByValue(cs.getString(columnIndex));
}
private E getByValue(String value) {
E[] values = type.getEnumConstants();
for (E e : values) {
if (e.getValue().toString().equals(value)) {
return e;
}
}
return null;
}
}
(8)application.yml中,添加属性mybatis-plus.typeHandlersPackage,值为步骤7中自定义BaseTypeHandler实现类所在的包路径
mybatis-plus:
typeHandlersPackage: xx.xx.xxx
(9)配置类创建MybatisSqlSessionFactoryBean 时 setTypeHandlersPackage方法中获取yml中对应的值
@Bean
@ConditionalOnMissingBean
public MybatisSqlSessionFactoryBean sqlSessionFactory(
MybatisPlusProperties properties){
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
......
sqlSessionFactoryBean.setTypeHandlersPackage(properties.getTypeHandlersPackage());
......
return sqlSessionFactoryBean;
}
至此结束