我们在平时开发中.肯定会遇到很多类似状态的东西.
比如:未支付用0表示 订单支付成功用1表示 支付失败用2表示
然后在代码中各种if(status==0)
... if(status==1)
.... 及其混乱,而且维护性和可读性非常差. 有什么解决方法呢. 答案:枚举
默认情况下枚举序列化是这样返回给页面的. 代码比如:
public enum TestEnum implements BaseEnum {
/**
*
*/
TEST_A("测试枚举A"),
TEST_B("测试枚举B"),
TEST_C("测试枚举C");
private String desc;
@Override
public int getOrdinal() {
return this.ordinal();
}
}
@Data
public class Test {
private TestEnum testEnum;
}
Test
对象返回给页面后显示为:
{"testEnum":"TEST_B"}
如果我们要返回给页面自定的code或者ordinal呢? 很简单 直接在get方法上面加入@JsonValue
即可(如果有统计继承的接口,在接口方法上加就行了). 比如:
public interface BaseEnum {
@JsonValue
int getOrdinal();
}
此时你看到的返回值就是这样的啦:
{"testEnum":2}
看到这里已经能解决一大部分问题了. 但是还有个小细节需要完善下.
如果我要返回整个枚举对象呢??????
很简单. 继续往下看
你只需要给你的类或者继承的枚举接口上面加入 @JsonFormat(shape= JsonFormat.Shape.OBJECT)
就ok了.然后返回给前端的数据就是这样的啦:
{
"testEnum": {
"desc": "测试枚举C",
"ordinal": 2
}
}
还没完,继续补充
默认情况下前端给我枚举的值时, 是你定义的属性. 比如上面的 TEST_A
TEST_B
TEST_C
前端传值时默认格式为:testEnum=TEST_B
或 {"testEnum":"TEST_B"}
那假如前端想传数字呢.
↓
↓
↓
↓
直接上代码了
package com.example.yiran.converter;
import com.example.yiran.enums.BaseEnum;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import java.util.HashMap;
import java.util.Map;
/**
* @description:
* @author: wajn
* @create: 2020-04-25 19:50
**/
public class BaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
/**
* 目标类型与对应转换器的Map
*/
private static final Map<Class, Converter> CONVERTER_MAP=new HashMap<>();
/**
* 根据目标类型获取相应的转换器
* @param targetType 目标类型
* @param <T> BaseEnum的实现类
* @return
*/
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
Converter converter=CONVERTER_MAP.get(targetType);
if(converter==null){
converter=new IntegerStrToEnumConverter<>(targetType);
CONVERTER_MAP.put(targetType,converter);
}
return converter;
}
/**
* 将int对应的字符串转换为目标类型的转换器
* @param <T> 目标类型(BaseEnum的实现类)
*/
class IntegerStrToEnumConverter<T extends BaseEnum> implements Converter<String,T>{
private Map<String,T> enumMap=new HashMap<>();
private IntegerStrToEnumConverter(Class<T> enumType){
T[] enums=enumType.getEnumConstants();
for (T e:enums){
enumMap.put(e.getOrdinal()+"",e);
//从枚举字面量反序列回枚
//是Spring默认的方案
//此处添加可避免下面convert方法抛出IllegalArgumentException异常后被系统捕获再次调用默认方案
enumMap.put(((Enum)e).name()+"",e);
}
}
@Override
public T convert(String source) {
T result=enumMap.get(source);
if(result==null){
//抛出该异常后,会调用 spring 的默认转换方案,即使用 枚举字面量进行映射
throw new IllegalArgumentException("No element matches "+source);
}
return result;
}
}
}
package com.example.yiran.config;
import com.example.yiran.converter.BaseEnumConverterFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @description:
* @author: wajn
* @create: 2020-04-25 19:40
**/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new BaseEnumConverterFactory());
}
}
然后前端想传啥就传啥. `抛出该异常后,会调用 spring 的默认转换方案,即使用 枚举字面量进行映射` 这里你可以选择return null. 这样就不会报错了.