枚举的高级用法

枚举的高级用法

Scroll Down

我们在平时开发中.肯定会遇到很多类似状态的东西.

 比如:未支付用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. 这样就不会报错了.