在数据库中,我们通常需要定义一些描述状态的字段来展示业务的进展情况或对象的状态,例如user表中定义一个int类型的字段status,0表示账户禁用,1表示账户正常;transaction交易表中定义一个交易状态字段dealStatus,0表示交易取消,1表示交易发起,2表示交易成功等等。
为了在java代码中更好地管理这些状态字段,我们通常会在项目中定义枚举类来描述这个字段所有的状态值以及对应的意思。
public enum BaseStatus {
ENABLE(1, "正常"),
DISABLE(0, "禁用");
private Integer code;
private String name;
BaseStatus(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return this.code;
}
public String getName() {
return this.name;
}
}
在前后端的数据交互中,经常会涉及到状态字段的转换,例如前端需要查询正常使用的用户信息,查询条件为status="1",然后后端查询到需要的数据后,将用户集合中的状态字段的数字转换为汉字返回给前端。
为此,我们需要在对应的需求处调用getCode()或getName()方法,这会导致我们的代码冗余度高并且不利于维护。所以我们可以在项目中定义一个全局的枚举消息转换器,controller接口可以使用对应的枚举类型去接收参数,并返回前端想要的中文意思。
项目实践:
1、定义一个接口BaseEnum,提供getCode()和getName()方法。
public interface BaseEnum {
int getCode();
String getName();
}
2、定义具体的枚举类UserStatus,实现BaseEnum接口。其他需要的枚举类均以这种方式创建,定义Integer类型的属性code和String类型的属性name。
@EnumValue注解是mybatisplus框架提供的,标注在code上表示在java服务与数据库交互时,status字段的值与UserStatus枚举类的code属性进行映射。
@JsonValue注解标注在枚举类的name字段上,将对象序列化成json字符串时,status字段会取枚举类name字段的值封装到json串中。
public enum UserStatus implements BaseEnum {
ENABLE(1, "正常"),
DISABLE(0, "禁用");
@EnumValue
private Integer code;
@JsonValue
private String name;
UserStatus(Integer code, String name) {
this.code = code;
this.name = name;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getName() {
return this.name;
}
}
3、定义一个枚举消息转换类CodeEnumConverter,实现接口ConverterFactory<String, BaseEnum>,重写getConverter()方法,并将自定义转换类的bean交由spring容器管理。
/**
* <String, BaseEnum>
* String表示前端传递的参数是String类型的
* BaseEnum表示我需要将String类型的参数转换成BaseEnum类型的参数
*/
@Component
public class CodeEnumConverter 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) {
/*
Class.getEnumConstants()方法是Java反射API中的一个方法,
用于获取表示枚举类型的 Class 对象中所有枚举常量的数组
*/
for (T enumConstant : targetType.getEnumConstants()) {
if (enumConstant.getCode() == Integer.valueOf(source)) {
return enumConstant;
}
}
throw new IllegalArgumentException("非法的枚举值:" + source);
}
};
}
}
4、将枚举消息转换类CodeEnumConverter注册到springmvc中。
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private CodeEnumConverter enumConverter;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(this.enumConverter);
}
}
5、controller接口可以使用枚举类型的字段去接收前端的请求参数。
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@GetMapping("/getUser")
public List<User> getUser(@RequestParam(value = "status", required = false) UserStatus status) {
List<User> list = userService.lambdaQuery()
.eq(!ObjectUtils.isEmpty(status), User::getStatus, status).list();
return list;
}
}
6、发送请求,查询状态为1的用户,springmvc接收到请求后会对参数进行转换,然后调用后端方法,并返回前端
7、在响应结果中,可以看到status的值为"正常",这种请求时传递数值,响应时返回汉字的需求,在很多地方都会用到。同时,可以看到响应中的createTime和updateTime字段返回的时间信息不符合我们的阅读习惯,修改json字符串中时间字段的格式,可以做如下配置:
7.1、在配置文件中添加配置:
spring.jackson.time-zone=GMT+8
7.2、在响应的实体类时间字段上标注@JsonFormat注解,并指定时间格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
7.3、完成以上两个步骤后,重新访问,时间格式就会变成我们所需要的样子