在Spring框架中,枚举类型的转换可以通过自定义的转换器来实现,这样可以方便地在请求参数、表单数据、以及数据库查询中使用枚举类型。

下面是关于Spring枚举转换器的详细介绍和使用方法:

OrderType排序枚举为例

1. 定义枚举类

BaseEnum.java

package com.echo.model.enums;

public interface BaseEnum {

    Integer getCode();

    String getName();
}

OrderType.java

package com.echo.model.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;

public enum OrderType implements BaseEnum {

    ASC(1, "升序"),

    DESC(2, "降序");


    @EnumValue
    @JsonValue
    private Integer code;
    private String name;

    @Override
    public Integer getCode() {
        return this.code;
    }


    @Override
    public String getName() {
        return name;
    }

    OrderType(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

}

2. 枚举转换器

在Spring中,实现Converter<S, T>接口来创建自定义枚举转换器。例如,将请求参数中的字符串转换为枚举类型:

package com.echo.webapp.works.custom.converter;

import com.echo.model.enums.OrderType;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class StringToOrderTypeConverter implements Converter<String, OrderType> {

    @Override
    public OrderType convert(@NotNull String code) {
        try {
            for (OrderType value : OrderType.values()) {
                if (value.getCode().equals(Integer.valueOf(code))) {
                    return value;
                }
            }
            return OrderType.DESC;
        } catch (IllegalArgumentException e) {
            // 如果 code 无效,可以选择返回 null 或者默认值
            return OrderType.DESC; // 或者 return null;
        }
    }
}

这个转换器将String转换为OrderType枚举。Spring会自动注册该转换器,这样就可以在Controller的请求参数中直接使用枚举类型。

3. 注册转换器(Spring会自动注册转换器,这里可省)

通过实现WebMvcConfigurer接口,在全局范围内注册枚举转换器:

package com.echo.webapp.works.custom.config;

import com.echo.webapp.works.custom.converter.StringToOrderTypeConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Autowired
    private StringToOrderTypeConverter stringToOrderTypeConverter;

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(this.stringToOrderTypeConverter);
    }
}

4. 使用场景

a. 使用@RequestParam@PathVariable

枚举类型的请求参数可以直接映射到控制器的方法中,如:

@RequestMapping("/filter")
public String filterOrders(@RequestParam("orderType") OrderType orderType) {
    // 使用枚举进行操作
    return "Filtered by order type: " + orderType.name();
}

或者通过@PathVariable:

@RequestMapping("/filter/{orderType}")
public String filterOrders(@PathVariable("orderType") OrderType orderType) {
    return "Filtered by order type: " + orderType.name();
}

b. 枚举在实体类中的映射

package com.echo.webapp.works.vo;

import com.echo.model.enums.OrderType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Data
@Schema(description = "作品查询实体")
public class WorkQueryVo {

    @Schema(description = "作者id")
    private Long authorId;

    @Schema(description = "排序键")
    private String orderBy;

    @Schema(description = "排序方式")
    private OrderType orderType;

}

c. 在数据库中使用

<select id="pageWorkItemByQuery" resultType="com.echo.webapp.works.vo.WorkItemVo">
    SELECT *
    FROM work_info
    <where>
        is_deleted = 0
        <if test="queryVo.authorId != null">
            AND author_id = #{queryVo.authorId}
        </if>
    </where>
    ORDER BY
    <choose>
        <when test="queryVo.orderBy != null and queryVo.orderBy == 'view'">
            view_count
        </when>
        <otherwise>
            id
        </otherwise>
    </choose>
    <choose>
        <when test="queryVo.orderType != null and queryVo.orderType.name() == 'ASC'">
            ASC
        </when>
        <otherwise>
            DESC
        </otherwise>
    </choose>
</select>