[Background]

Since I had been developing other modules, I recently started to add them to my colleagues’ modules. It didn’t matter at all, the screen full of magic numbers made me almost out of breath. Although some colleagues have thought of using static variables to deal with it, but clearly the same thing must be separated by different cans, don’t you feel uncomfortable? I decided to document my previous experience with enumerations; Here are the magic numbers for your objective appreciation

@Override
public ReturnObject putCanceUser(UcasCancellationBo ucasCancellationBo) {
    UcasCancellationInfo ucasCancellationInfo = new UcasCancellationInfo();
    ucasCancellationInfo.setId(ucasCancellationBo.getId());
    ucasCancellationInfo.setIsDelete(1);
    int count = ucasCancellationInfoMapper.updateById(ucasCancellationInfo);
    if(count>0) {return ReturnObject.success();
    }else {
        return ReturnObject.fail("Operation failed"); }}Copy the code

[Enumerating mapping database fields]

If you use the MyBatis framework for the persistence layer, you can use mybatisPlus’s generic enumeration functionality, which also has several uses; I only record what I like to use, other methods can check the official website

Take me to

First configure the enumeration packet scan path

Mybatis -plus: # Scan universal enumeration type-enums-package: com.xxjqr.rbac.enumsCopy the code

[方法一 @EnumValue与@JsonValue]

Use annotations @enumValue and @jsonValue in enumeration

@getter @allargsconstructor Public enum SexEnum implements BaseEnum {MALE(1," MALE "), FEMALE(0," FEMALE "), UNKNOW(2," unknown "); @EnumValue private final Integer code; @JsonValue private final String desc; }Copy the code

When SexEnum is an attribute of an entity object, the database field mapped by the attribute is the value used by @EnumValue

@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class TbUser extends Model<TbUser> { private  static final long serialVersionUID = 1L; /** * ID */ private Long id; /** ** private SexEnum sex; /** * Status 0 Disabled 1 Normal */ private StatusEnum status; /** * Delete 1: deleted; 0: not deleted */ @TABLelogic private Integer isDelete; @Override protected Serializable pkVal() { return this.id; }}Copy the code

For example, the following pseudocode inserts a girl of gender 0 into the database

TbUser user = new TbUser(SexEnum.FEMALE)
userMapper.insert(user)
Copy the code

Similarly, when data is read from the database, the values of the database are translated into the corresponding enumerated objects

TbUser use = userMapper.selectById(id)
use.sex == SexEnum.FEMALE
Copy the code

If the entity object is returned to the front end, the value corresponding to the enumerated property is the @JsonValue modified field

[Method 2 Implementing the IEnum interface]

Overriding getValue is the same as overriding toString using the @EnumValue annotation

@AllArgsConstructor
@Getter
//IEnum
      
        Inteter Generic indicates the field type mapped to the database
      
public enum BusinessStatusEnum implements IEnum<Integer>{
    FAIL(0."Failure"),
    SUCCESS(1."Success"),;private final Integer code;
    private final String desc;

    @Override
    public Integer getValue(a) {
        return code;
    }

    @Override
    public String toString(a) {
        return this.desc; }}Copy the code

Then you need to configure Jackson’s deserialization enumeration, write_ENUMs_using_to_string

Spring: Jackson: date-format: YYYY-MM-DD HH: MM: SS time-zone: GMT+8 serialization: write_ENUMs_USING_TO_string: trueCopy the code

[Deserialize parameter to enumeration]

Some of the magic numbers in the code are now dead, but there are still some stubborn problems that need to be dealt with in other ways. Front, for example, to add and delete the call interface, will be introduced to a similar status = ‘1’, {‘ sex ‘: 1} parameters, such as how to participate in the space of the interface (technically called json deserialization) in the process of the magic number into the enumeration object?

[a: Get request and POST formData parameter transfer]

Such requests can be converted directly using the Convert converter provided by Spring

[1] Define the public enumeration interface

public interface BaseEnum {
    Integer getCode(a);
}
Copy the code

[2] Inherits the public enumeration interface

@AllArgsConstructor
@Getter
public enum BusinessStatusEnum implements BaseEnum{
    FAIL(0."Failure"),
    SUCCESS(1."Success"),;@EnumValue
    private final Integer code;
    @JsonValue
    private final String desc;
}

@Getter
@AllArgsConstructor
public enum MenuTypeEnum implements BaseEnum {
    CATALOG(1."Directory"),
    MENU(2."Menu"),
    BUTTON(3."Button");

    @EnumValue
    @JsonValue
    private final Integer code;
    private final String desc;
}

Copy the code

[3] Define String->Enum converter

Spring: Jackson: Generator: write_numbers_as_strings spring: Jackson: Generator: write_numbers_as_strings Public class implements BaseEnum <T extends BaseEnum> Implements Converter<String, BaseEnum> { private Map<String, T> enumMap = new HashMap<>(); /** * @; /** * @; Public StringToEnumConverter(Class<T> enumType) {public StringToEnumConverter(Class<T> enumType) {public StringToEnumConverter(Class<T> enumType) enumType.getEnumConstants(); For (T e: enums) {// Enumeration object code as key, enumeration object as value enummap.put (LLDB code ().toString(), e); }} /** * @override public T convert(String source) {if (StrUtil.isEmpty(source)) { return null; } T t = enumMap.get(source); If (objectutil. isNull(t)) {throw new IllegalArgumentException(" Cannot match the corresponding enumeration type "); } return t; }}Copy the code

[4] Define the corresponding converter factory

public class StringToEnumConverterFactory implements ConverterFactory<String.BaseEnum> {

    private static final Map<Class, Converter> CONVERTERS = new HashMap<>();

    /** * Returns * from finding the corresponding converter in the converter factory@paramTargetType Converted type *@returnReturn a converter */
    @Override
    public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
        StringToEnumConverter converter = (StringToEnumConverter) CONVERTERS.get(targetType);
        if (converter == null) {
            converter = new StringToEnumConverter(targetType);
            CONVERTERS.put(targetType, converter);
        }
        returnconverter; }}Copy the code

[5] Add the converter factory to the SpringBoot configuration

@configuration public class WebMvcConfig implements WebMvcConfigurer {/** * enumeration class addConverterFactory */ @override public void addFormatters(FormatterRegistry registry) { registry.addConverterFactory(new StringToEnumConverterFactory()); }}Copy the code

[expansion]

If sex=’FEMAIL’ is passed from the front end, how to convert it to the corresponding enumeration object?

[1] Public enumeration interface adds the getName() method

public interface BaseEnum {
    Integer getCode(a);
    String getName(a);
}
Copy the code

[2] Enumeration object override getName()

@Getter
@AllArgsConstructor
public enum SexEnum implements BaseEnum {
    MALE(1."Male"),
    FEMALE(0."Female"),
    UNKNOW(2."Unknown");@EnumValue
    private final Integer code;
    @JsonValue
    private final String desc;

    @Override
    public String getName(a) {
        returnname(); }}Copy the code

[3] Converter added a name->enum cache

public class StringToEnumConverter<T extends BaseEnum> implements Converter<String.BaseEnum> {
    private Map<String, T> enumMap = new HashMap<>();
    private Map<String, T> nameEnumMap = new HashMap<>();

    /** * @stringToenumconverter constructor (); /** * @stringToEnumconverter constructor ()
    public StringToEnumConverter(Class<T> enumType) {
        // Read all enumeration objects out
        T[] enums = enumType.getEnumConstants();
        for (T e : enums) {
            // The code of the enumeration object is the key, and the enumeration object is the value
            enumMap.put(e.getCode().toString(), e);
            // The name of the enumeration object is the key, and the enumeration object is the valuenameEnumMap.put(e.getName(), e); }}/** * @ Description code->enum Core code * @ code * @ date 2021/5/24 15:33 */
    @Override
    public T convert(String source) {
        if (StrUtil.isEmpty(source)) {
            return null;
        }
        T t = enumMap.get(source);
        // If code->enum is not available in the cache, try to fetch it from name->enum
        if (ObjectUtil.isNull(t)) {
            t = nameEnumMap.get(source);
            if (ObjectUtil.isNull(source)) {
                throw new IllegalArgumentException("Cannot match the corresponding enumeration type"); }}returnt; }}Copy the code

[2: Post JSON parameter]

Springboot uses Jackson deserialization by default when the POST request is passed in JSON format and the @RequstBody annotation is used on the back end, so we can arrange it from Jackson







[1] Use the @JsonCreator annotation to customize how enumerations are created

@Getter
@AllArgsConstructor
public enum StatusEnum implements BaseEnum{
    ENABLE(1."Normal"),
    DISABLE(0."Disabled");@EnumValue
    @JsonValue
    private final Integer code;
    private final String desc;


    / / when reduced to 2.10.5 version can run normally, version 2.11 only amend the @ JsonCreator to @ JsonCreator (mode = JsonCreator. Mode. DELEGATING)
    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
    public static StatusEnum valueOf(int code) {
        //StatusEnum.values() == values()
        for (StatusEnum statusEnum : values()) {
            if (statusEnum.code == code) {
                returnstatusEnum; }}return null;
    }

    @Override
    public String getName(a) {
        returnname(); }}Copy the code

When a parameter is specified, it is automatically converted to the corresponding enumeration object

{

    "status":"0"
}
Copy the code

[expansion]

The following article from Zhihu, about more usage, but at present I do not have this need, you go to have a look!

Take me to