java常量数据用枚举封装(二)优雅对接前端 您所在的位置:网站首页 数据字典转换成数字 java常量数据用枚举封装(二)优雅对接前端

java常量数据用枚举封装(二)优雅对接前端

2023-06-02 19:59| 来源: 网络整理| 查看: 265

二、-自定义数据转换 前言注意事项本文为了测试,已修改枚举类的内容 问题处理首先处理get请求数据自定义converter注册converter到SpringMVC中测试 post请求,body数据封装问题描述自定义JsonDeserializer注册JsonDeserializer测试: 如何仅返回枚举常量值给前端问题描述自定义JsonDeserializer注册JsonSerializer测试 总结通用化的问题,就留到后面的文章讲解吧

前言

上篇文章已初步解决了和前端对接的,如接收,返回枚举类数据的问题,但那是依靠MVC的自动封装进行的,使用的是枚举类的ordinal,不可控,或者说需要依赖人工校验枚举类的属性值。本人觉得此方式不可取,因为总会有疏忽的地方,或者枚举值起始值较大时,如10,100,1000时,就无法使用此方式了。 于是便有了本文,使用convert对前端传递来的数据进行转换。

注意事项

接收时,SpringMVC的Convertor仅对get请求中的数据有效,如果接收的是body参数,枚举类在对象中做属性的,则需要JsonDeserializer。 返回时,SpringMVC返回json数据时需要json化对象,使用

@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)

让枚举类参与json化,值使用的仍是ordinal,想要返回真正的枚举常量,需要使用JsonSerializer

本文为了测试,已修改枚举类的内容 import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Getter; import lombok.RequiredArgsConstructor; /** * @author jeff * @since 2023/4/30 17:46 */ @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @RequiredArgsConstructor public enum UserStatus { ENABLE(3,"启用"), DISABLE(4,"禁用"); @Getter private final int value; @Getter private final String desc; } 问题处理 首先处理get请求数据 自定义converter import com.will.cn.constants.enums.UserStatus; import org.springframework.core.convert.converter.Converter; /** * @author jeff */ public class UserStatusConverter implements Converter { @Override public UserStatus convert(String source) { System.out.println("正在执行UserStatus的convert方法:"+source); int i = Integer.parseInt(source); UserStatus[] values = UserStatus.values(); for (UserStatus value : values) { if (i==(value.getValue())) { System.out.println("已匹配到数据并返回"); return value; } } throw new RuntimeException("无效枚举值"); } }

convert方法中,如果出现异常,则会向前端返回400参数异常 如果这里想要给前端友好化提示的话,可以考虑自己封装异常自己抛 使用全局异常处理器进行异常返回。 这里用了最原始的,遍历所有枚举实例进行比对匹配,读者们可以自行优化算法。

注册converter到SpringMVC中 import com.will.cn.handler.UserStatusConverter; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author jeff */ @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new UserStatusConverter()); } } 测试

在这里插入图片描述 get请求的参数接收问题,到这里就基本解决了,但如果每建一个枚举类,就要写一个converter,对我这种懒人来说肯定是不行,这个问题的处理,就留到后面的枚举封装优化的文章中吧

post请求,body数据封装 问题描述

现在大部分应用SpringMVC,前后端对接的数据都是json格式了。 数据来到系统时,SpringMVC会对body的数据进行json反序列化。 对于枚举类型的数据,使用的是ordinal匹配,可能会出现的问题,前文已经提到了,这里就不再赘述。

SpringMVC内置的json处理工具为jackson,在反序列化json时,会判断当前数据是否有指定JsonDeserializer,有则使用,无则使用默认的,默认JsonDeserializer使用ordial进行反序列化

我们这里要自定义JsonDeserializer,用自己的方式解析前端传来的枚举类参数。

自定义JsonDeserializer import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.will.cn.constants.enums.UserStatus; import java.io.IOException; public class UserStatusEnumDeserializer extends JsonDeserializer { @Override public UserStatus deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { final String source = jsonParser.getText(); System.out.println("正在执行UserStatus的deserialize方法:"+source); int i = Integer.parseInt(source); UserStatus[] values = UserStatus.values(); for (UserStatus value : values) { if (i==(value.getValue())) { System.out.println("已匹配到正确的UserStatus数据并返回:"+value); return value; } } throw new RuntimeException("无效枚举值"); } }

同convet一样的匹配逻辑,各位可以自行优化。

注册JsonDeserializer @JsonDeserialize(using = UserStatusEnumDeserializer.class)

只要在枚举类上加上此注解,设置using参数为刚刚编写的Deserializer类即可

测试:

在这里插入图片描述 可以看到数据已正常封装。

如何仅返回枚举常量值给前端 问题描述

直接使用

@JsonFormat(shape = JsonFormat.Shape.OBJECT)

就可以完整的返回json格式的枚举数据,但会包括枚举中所有的get方法返回的值,而且会有key值,但已经能满足正常的对接工作 但如果前端无法适应这种参数类型,或者觉得数据太臃肿,或者说现在只是对后端改造,不涉及前端内容,那么就要考虑仅返回真正的常量值给前端了

上面已经提到了SpringMVC对接收的body参数,会使用JsonDeserializer反序列化,那自然而然的,SpringMVC肯定也会用到JsonSerializer序列化返回的数据。

SpringMVC会走同样的流程,对数据进行序列化,判断有无指定,无则使用默认序列化方法 前文中的JsonFormat注解,则是对默认JsonSerializer的参数的配置。

自定义JsonDeserializer import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.will.cn.constants.enums.UserStatus; import java.io.IOException; /** * @author jeff * @since 2023/5/1 11:46 */ public class UserStatusEnumSerializer extends JsonSerializer { @Override public void serialize(UserStatus status, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeNumber(status.getValue()); } }

直接往jsonGenerator写入枚举类的值即可。

注册JsonSerializer @JsonSerialize(using = UserStatusEnumSerializer.class)

只要在枚举类上加上此注解,设置using参数为刚刚编写的Sserializer类即可

测试

在这里插入图片描述

总结

到这里,对枚举类数据的接收就初步完善了 剩下的问题就是对匹配算法的优化 还有就是对Converter、Serializer和Deserializer的通用化,因为不可能为每一个枚举常量创建一套规则。

通用化的问题,就留到后面的文章讲解吧


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有