前端传String 后端使用enum
情况 前端 String 后端 enum
前端
后端
报错1
2
3
4
5
62024-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 [ .springframework.web.bind.annotation.RequestParam
com.orchids.springmybatisplus.model.enums.Sex] for value '1']
问题出现在这个方法1
2
3
4
5
6
7
8
9//根据性别查询学生 存在String --->转换为enums\
//@RequestParam(required = false) required=false 表示参数可以没有
public Result<List<Student>> StudentBySex({ Sex sex)
LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(Student::getSex,sex);
List<Student> list = studentService.list(lambdaQueryWrapper);
return Result.ok(list);
}
对应的枚举类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package 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, "女性");
private Integer code;
private String name;
Sex(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return this.code;
}
public String getName() {
return this.name;
}
}
解决方法 一
编写StringToSexConverter方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package 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;
public class StringToItemTypeConverter implements Converter<String, ItemType> {
/**
* 根据给定的代码字符串转换为对应的ItemType枚举。
*
* @param code 代表ItemType枚举的代码字符串,该代码应该是整数形式。
* @return 对应于给定代码的ItemType枚举值。
* @throws IllegalArgumentException 如果给定的代码无法匹配到任何枚举值时抛出。
*/
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package 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
*/
public class WebMvcConfiguration implements WebMvcConfigurer {
private StringToSexConverter stringToItemTypeConverter;
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(this.stringToItemTypeConverter);
}
}成功解决
解决方法二
当有很多种类型需要转换 例如`
- String
到
Integer`、 String
到Date
,String
到Boolean
- 就要写每一种转换方法 代码重用性不高
- 于是就有了第二种方法
- 使用
[ConverterFactory](https://docs.spring.io/spring-framework/reference/core/validation/convert.html#core-convert-ConverterFactory-SPI)
接口更为合适,这个接口可以将同一个转换逻辑应用到一个接口的所有实现类,因此我们可以定义一个BaseEnum
接口,然后另所有的枚举类都实现该接口,然后就可以自定义ConverterFactory
,集中编写各枚举类的转换逻辑了 - 具体实现如下
- 在编写一个BaseEnum接口
1
2
3
4public interface BaseEnum {
Integer getCode();
String getName();
}
让enums 包下的枚举都实现这个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package 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, "女性");
private Integer code;
private String name;
Sex(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return this.code;
}
public String getName() {
return this.name;
}
}编写 StringToBaseEnumConverterFactory 实现接口 ConverterFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class StringToBaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
return new Converter<String, T>() {
public T convert(String source) {
for (T enumConstant : targetType.getEnumConstants()) {
if (enumConstant.getCode().equals(Integer.valueOf(source))) {
return enumConstant;
}
}
throw new IllegalArgumentException("非法的枚举值:" + source);
}
};
}
}将其注册到WebMvcConfiguration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package 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
*/
public class WebMvcConfiguration implements WebMvcConfigurer {
private StringToBaseEnumConverterFactory stringToBaseEnumConverterFactory;
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(this.stringToBaseEnumConverterFactory);
}
}第二种方法有这一个类就行了
数据库用 int 后端用enum为什么不会出现错误?
- String
TypeHandler枚举类型转换
- Mybatis预置的
TypeHandler
可以处理常用的数据类型转换,例如String
、Integer
、Date
等等,其中也包含枚举类型,但是枚举类型的默认转换规则是枚举对象实例(ItemType.APARTMENT)和实例名称(”APARTMENT”)相互映射。若想实现code
属性到枚举对象实例的相互映射,需要自定义TypeHandler
。 - 不过MybatisPlus提供了一个通用的处理枚举类型的TypeHandler。其使用十分简单,只需在
Sex
枚举类的code
属性上增加一个注解@EnumValue
,Mybatis-Plus便可完成从Sex
对象到code
属性之间的相互映射,具体配置如下。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package 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, "女性");
private Integer code;
private String name;
Sex(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return this.code;
}
public String getName() {
return this.name;
}
}
- Mybatis预置的
HTTPMessageConverter枚举类型转换
HttpMessageConverter
依赖于Json序列化框架(默认使用Jackson)。其对枚举类型的默认处理规则也是枚举对象实例(ItemType.APARTMENT)和实例名称(”APARTMENT”)相互映射。不过其提供了一个注解@JsonValue
,同样只需在ItemType
枚举类的code
属性上增加一个注解@JsonValue
,Jackson便可完成从ItemType
对象到code
属性之间的互相映射。具体配置如下,详细信息可参考Jackson官方文档。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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, "女性");
private Integer code;
private String name;
Sex(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return this.code;
}
public String getName() {
return this.name;
}
}