spring-boot rest controller 使用枚举作为参数,重写反序列化实现任意值转枚举类型

目录

  1. BaseEnum
  2. MyEnum
  3. StringToEnumConverterFactory
  4. FormatterConfig
  5. DTO
  6. RestController
  7. 参考

BaseEnum

package com.src.xxx.constant.enums;

public interface BaseEnum<ValueType> {    
    ValueType getValue();
}

MyEnum

package com.src.xxx.constant.enums;

import com.fasterxml.jackson.annotation.JsonValue;
import com.src.xxx.constant.enums.BaseEnum;

public enum MyEnum implements BaseEnum<Integer> {
    Request(34, "请求"),
    Response(59, "响应");

    private final int value;
    private final String describe;

    private MyEnum(int value, String describe) {
        this.value = value;
        this.describe = describe;
    }
   
    @Override
    public Integer getValue() {
        return this.value;
    }

    @JsonValue
    @Override
    public String toString() {
        return this.describe;
    }
}

StringToEnumConverterFactory

package com.src.xxx.configuration.converter;

import com.google.common.collect.Maps;
import com.src.xxx.constant.enums.BaseEnum;
import com.sun.istack.Nullable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.util.ObjectUtils;

import java.util.Map;

@SuppressWarnings({"rawtypes", "unchecked"})
public final class StringToEnumConverterFactory implements ConverterFactory<String, BaseEnum<String>> {
    private static final Map<Class, Converter> CONVERTERS = Maps.newHashMap();

    /**
     * Get the converter to convert from S to target type T, where T is also an instance of R.
     *
     * @param targetType the target type to convert to
     * @return a converter from S to T
     */
    @Override
    public <T extends BaseEnum<String>> Converter<String, T> getConverter(Class<T> targetType) {
        Converter<String, T> converter = CONVERTERS.get(targetType);
        if(converter == null){
            converter = new ObjectToEnumConverter(targetType);
            CONVERTERS.put(targetType, converter);
        }

        return converter;
    }

    static final class ObjectToEnumConverter<E extends BaseEnum> implements Converter<String, E> {
        private final Map<String, E> enumMap = Maps.newHashMap();

        ObjectToEnumConverter(Class<E> enumType){
            E[] enums = enumType.getEnumConstants();
            for (E e : enums) {
                enumMap.put(e.getValue().toString(), e);
            }
        }

        @Override
        @Nullable
        public E convert(String source) {
            E e = enumMap.get(source);
            if(ObjectUtils.isEmpty(e)) {
                return null;
            }

            return e;
        }
    }
}

FormatterConfig

package com.src.xxx.configuration;

import com.src.xxx.configuration.converter.StringToEnumConverterFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class FormatterConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(new StringToEnumConverterFactory());
    }
}

DTO

package com.src.xxx.dto.test;

import com.src.xxx.constant.enums.MyEnum;
import lombok.Data;

@Data
public class EnumQueryDTO {
    private MyEnum myEnum;
}
package com.src.xxx.dto.test;

import com.src.xxx.constant.enums.MyEnum;
import lombok.Data;

@Data
public class EnumBodyDTO {
    private MyEnum myEnum;
}

RestController

package com.src.xxx.controller;

import com.src.xxx.dto.test.EnumBodyDTO;
import com.src.xxx.dto.test.EnumQueryDTO;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/api/test")
public class TestController {

    @GetMapping("/enum")
    public ResponseEntity<MyEnum> getEnum(EnumQueryDTO query) {
        return ResponseEntity.ok(query.getMyEnum());
    }

    @PostMapping("/enum")
    public ResponseEntity<MyEnum> postEnum(@RequestBody EnumBodyDTO body) {
        return ResponseEntity.ok(body.getMyEnum());
    }
}

参考

  1. Spring Boot 使用枚举类型作为请求参数
  2. Spring Framework/StringToEnumConverterFactory
原文地址:https://www.cnblogs.com/myesn/p/spring-boot-request-use-enums-params.html