前端传String字符串 后端使用enun枚举类出现错误

image.png
情况 前端 String 后端 enum

前端
image.png
后端
image.png
报错

2024-05-31T21:47:40.618+08:00  WARN 21360 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: 
Failed to convert value of type 'java.lang.String' to required type 'com.orchids.springmybatisplus.model.enums.Sex'; 
Failed to convert from type 
[java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam 
com.orchids.springmybatisplus.model.enums.Sex] for value '1']

问题出现在这个方法

    //根据性别查询学生 存在String --->转换为enums\
    @Operation(summary = "根据性别(类型)查询学生信息")
    @GetMapping("sex") //@RequestParam(required = false) required=false 表示参数可以没有
    public Result<List<Student>> StudentBySex(@RequestParam(required = false) Sex sex){
        LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Student::getSex,sex);
        List<Student> list = studentService.list(lambdaQueryWrapper);
        return Result.ok(list);
    }

对应的枚举类

package com.orchids.springmybatisplus.model.enums;

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

/**
 * @Author qwh
 * @Date 2024/5/31 19:13
 */
public enum Sex implements BaseEnum{
    MAN(0,"男性"),
    WOMAN(1, "女性");
    @EnumValue
    @JsonValue
    private Integer code;
    private String name;

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

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

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

解决方法 一
  1. 编写StringToSexConverter方法
package com.orchids.lovehouse.web.admin.custom.converter;

import com.orchids.lovehouse.model.enums.ItemType;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class StringToItemTypeConverter implements Converter<String, ItemType> {
    /**
     * 根据给定的代码字符串转换为对应的ItemType枚举。
     *
     * @param code 代表ItemType枚举的代码字符串,该代码应该是整数形式。
     * @return 对应于给定代码的ItemType枚举值。
     * @throws IllegalArgumentException 如果给定的代码无法匹配到任何枚举值时抛出。
     */
    @Override
    public ItemType convert(String code) {

        // 遍历所有ItemType枚举值,查找与给定代码匹配的枚举
        for (ItemType value : ItemType.values()) {
            if (value.getCode().equals(Integer.valueOf(code))) {
                return value;
            }
        }
        // 如果没有找到匹配的枚举,抛出异常
        throw new IllegalArgumentException("code非法");
    }
}

将其注册到WebMvcConfiguration

package com.orchids.springmybatisplus.web.custom.config;

import com.orchids.springmybatisplus.web.custom.converter.StringToSexConverter;
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;

/**
 * @Author qwh
 * @Date 2024/5/31 22:06
 */
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Autowired
    private StringToSexConverter stringToItemTypeConverter;

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

成功解决

解决方法二
  1. 当有很多种类型需要转换 例如`
    1. StringInteger`、
    2. StringDate
    3. StringBoolean
    • 就要写每一种转换方法 代码重用性不高
    • 于是就有了第二种方法
    • 使用[ConverterFactory](https://docs.spring.io/spring-framework/reference/core/validation/convert.html#core-convert-ConverterFactory-SPI)接口更为合适,这个接口可以将同一个转换逻辑应用到一个接口的所有实现类,因此我们可以定义一个BaseEnum接口,然后另所有的枚举类都实现该接口,然后就可以自定义ConverterFactory,集中编写各枚举类的转换逻辑了
    • 具体实现如下
    • 在编写一个BaseEnum接口
public interface BaseEnum {
    Integer getCode();
    String getName();
}
  • 让enums 包下的枚举都实现这个接口
package com.orchids.springmybatisplus.model.enums;

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

/**
 * @Author qwh
 * @Date 2024/5/31 19:13
 */
public enum Sex implements BaseEnum{
    MAN(0,"男性"),
    WOMAN(1, "女性");
    @EnumValue
    @JsonValue
    private Integer code;
    private String name;

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

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

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

  • 编写 StringToBaseEnumConverterFactory 实现接口 ConverterFactory
@Component
public class StringToBaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
    @Override
    public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
        return new Converter<String, T>() {
            @Override
            public T convert(String source) {

                for (T enumConstant : targetType.getEnumConstants()) {
                    if (enumConstant.getCode().equals(Integer.valueOf(source))) {
                        return enumConstant;
                    }
                }
                throw new IllegalArgumentException("非法的枚举值:" + source);
            }
        };
    }
}
  • 将其注册到WebMvcConfiguration
package com.orchids.springmybatisplus.web.custom.config;

import com.orchids.springmybatisplus.web.custom.converter.StringToBaseEnumConverterFactory;
import com.orchids.springmybatisplus.web.custom.converter.StringToSexConverter;
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;

/**
 * @Author qwh
 * @Date 2024/5/31 22:06
 */
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
    @Autowired
    private StringToBaseEnumConverterFactory stringToBaseEnumConverterFactory;

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(this.stringToBaseEnumConverterFactory);
    }
}

第二种方法有这一个类就行了

数据库用 int 后端用enum为什么不会出现错误?
  • TypeHandler枚举类型转换
    1. Mybatis预置的TypeHandler可以处理常用的数据类型转换,例如StringIntegerDate等等,其中也包含枚举类型,但是枚举类型的默认转换规则是枚举对象实例(ItemType.APARTMENT)和实例名称(“APARTMENT”)相互映射。若想实现code属性到枚举对象实例的相互映射,需要自定义TypeHandler
    2. 不过MybatisPlus提供了一个通用的处理枚举类型的TypeHandler。其使用十分简单,只需在Sex枚举类的code属性上增加一个注解@EnumValue,Mybatis-Plus便可完成从Sex对象到code属性之间的相互映射,具体配置如下。
package com.orchids.springmybatisplus.model.enums;

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

/**
 * @Author qwh
 * @Date 2024/5/31 19:13
 */
public enum Sex implements BaseEnum{
    MAN(0,"男性"),
    WOMAN(1, "女性");
    @EnumValue
    @JsonValue
    private Integer code;
    private String name;

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

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

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

  • HTTPMessageConverter枚举类型转换
    1. HttpMessageConverter依赖于Json序列化框架(默认使用Jackson)。其对枚举类型的默认处理规则也是枚举对象实例(ItemType.APARTMENT)和实例名称(“APARTMENT”)相互映射。不过其提供了一个注解@JsonValue,同样只需在ItemType枚举类的code属性上增加一个注解@JsonValue,Jackson便可完成从ItemType对象到code属性之间的互相映射。具体配置如下,详细信息可参考Jackson官方文档
    
package com.orchids.springmybatisplus.model.enums;

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

/**
 * @Author qwh
 * @Date 2024/5/31 19:13
 */
public enum Sex implements BaseEnum{
    MAN(0,"男性"),
    WOMAN(1, "女性");
    @EnumValue
    @JsonValue
    private Integer code;
    private String name;

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值