当前位置:首页 > 技术分析 > 正文内容

SpringBoot项目:接口参数空白值如何替换为null值

ruisui884个月前 (02-04)技术分析27

来源:
https://mp.weixin.qq.com/s/slPpOtqm5tvwxA4e_so4gQ

问题发生

我们公司代码生成的时候,查询列表统一都是使用了setEntity() ,查询写法如下:

查询的方法是Get方法:

前端是通过url加参数传过来的,如果有一个参数值为空的时候,由于setEntity() 并不过滤空白,执行sql的时候 会把""作为参数去当做查询条件,查询就出现了问题:

于是我就想把空白转换为null来解决这个问题了。

初始解决

一开始自然而然想到在setEntity之前先判断, 如果BasReservoirArea这个实例有字段的值是空白就设置为null

用到的工具类如下

问题解决了。

优化

由于感觉上面的解决方案不够专业,不够优雅,所以先寻找更好的解决办法,在后端接收参数值的时候,如果接收的是空白,直接设置为null, 这样就不需要再次转换了。

解决问题首先要考虑两种情况,一种是前端通过Get请求,路径上带参数;另一种是Post请求,带着Request报文。

Post请求报文体

由于笔者熟悉Post中报文体的转换,知道是MappingJackson2HttpMessageConverter结合Jackson实现报文体转换为实例的,而且也研究过Jackson, 所以解决办法如下

创建一个针对于String.class的Jackson的反序列类:

@ControllerAdvice
public?class?GlobalControllerAdiviceController?{
????//WebDataBinder是用来绑定请求参数到指定的属性编辑器,可以继承WebBindingInitializer
????//来实现一个全部controller共享的dataBiner?Java代码
????@InitBinder
????public?void?dataBind(WebDataBinder?binder)?{
????????///注册
????????binder.registerCustomEditor(String.class,?new?StringTrimmerEditor(true));
????}
}

创建一个MappingJackson2HttpMessageConverter Bean:

@Bean
@Primary
public?MappingJackson2HttpMessageConverter?mappingJackson2HttpMessageConverter()?{
?MappingJackson2HttpMessageConverter?jsonConverter?=?new?MappingJackson2HttpMessageConverter();
?//设置解析JSON工具类
?ObjectMapper?objectMapper?=?new?ObjectMapper();
?objectMapper.getSerializerProvider().setNullValueSerializer(
??new?JsonSerializer()?{
???@Override
???public?void?serialize(Object?value,?JsonGenerator?jsonGenerator,?SerializerProvider????????serializerProvider)?throws?IOException?{
?????jsonGenerator.writeString("");
???}
??}
?);
?
?SimpleModule?simpleModule?=?new?SimpleModule();
?simpleModule.addDeserializer(String.class,?new?StringDescrializer());
????//注册自定义的StringDescrializer
????//registerModules函数可以注册多个Module
?objectMapper.registerModule(simpleModule);

????//忽略未知属性?防止解析报错
????objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,?false);

????jsonConverter.setObjectMapper(objectMapper);
????List?list?=?new?ArrayList<>();
????list.add(MediaType.APPLICATION_JSON_UTF8);
????jsonConverter.setSupportedMediaTypes(list);
????return?jsonConverter;
}

对于Post报文体来说,测试成功了。

Get路径带参数

上面的解决方法不适用于Get方法路径带参数的情况,所以需要另外想办法了。

由于我使用过@InitBinder注解,知道可以注入自定义的PropertyEditor, 在Editor里面可以自定义格式或者返回值,于是,自定义一个StringEditor来处理空白的问题:

想要全局controller共享这个Databinder:

对于Get路径带参数来说,测试也成功了

思考

解决完问题后,还是觉得不够优雅,觉得spring 应该会考虑到这种情况,终于在spring 的文档中查阅到StringTrimmerEditor(https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-beans) 可以实现「Get」方法时参数去除空格:

只不过这个editor确实没有注册,需要手工注册。

@ControllerAdvice
public?class?GlobalControllerAdiviceController?{
????//WebDataBinder是用来绑定请求参数到指定的属性编辑器,可以继承WebBindingInitializer
????//来实现一个全部controller共享的dataBiner?Java代码
????@InitBinder
????public?void?dataBind(WebDataBinder?binder)?{
????????///注册
????????binder.registerCustomEditor(String.class,?new?StringTrimmerEditor(true));
????}
}

注意,StringTrimmerEditor构造方法中有一个参数,如果传入true,则会将空白转换为null. 这样前面写的StringEditor就不用了,spring 已经帮我们写好了。

对于「Post」报文体来说,实际上我只需要改变的是「Jackson ObjectMapper」,不需要自定义整个MappingJackson2HttpMessageConverter ,只需要自定义Jackson ObjectMapper.百度了一下,果然有同学已经有了解决方案:

@Bean
public?Jackson2ObjectMapperBuilderCustomizer?jackson2ObjectMapperBuilderCustomizer()?{
????return?new?Jackson2ObjectMapperBuilderCustomizer()?{
????????@Override
????????public?void?customize(Jackson2ObjectMapperBuilder?jacksonObjectMapperBuilder)?{
????????????jacksonObjectMapperBuilder
????????????????????.deserializerByType(String.class,?new?StdScalarDeserializer(String.class)?{
????????????????????????@Override
????????????????????????public?String?deserialize(JsonParser?jsonParser,?DeserializationContext?ctx)
????????????????????????????????throws?IOException?{
????????????????????????????//?重点在这儿:如果为空白则返回null
????????????????????????????String?value?=?jsonParser.getValueAsString();
????????????????????????????if?(value?==?null?||?"".equals(value.trim()))?{
????????????????????????????????return?null;
????????????????????????????}
????????????????????????????return?value;
????????????????????????}
????????????????????});
????????}
????};
}

把上面的自定义StringDescrializer和MappingJackson2HttpMessageConverter去掉, 只保留上面的就行。

后记

好多问题,其实spring 都已经提供了解决方案,但是spring体系目前太庞大了,所以好多API和功能都不为人知。所以碰上问题就记录下来是个很好的习惯

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/1667.html

标签: objectmapper
分享给朋友:

“SpringBoot项目:接口参数空白值如何替换为null值” 的相关文章

总结了Vue3的七种组件通信方式,别再说不会组件通信了

写在前面本篇文章是全部采用的<script setup>这种组合式API写法,相对于选项式来说,组合式API这种写法更加自由,具体可以参考Vue文档对两种方式的描述。本篇文章将介绍如下七种组件通信方式:propsemitv-modelrefsprovide/injecteventBusv...

10个实例小练习,快速入门熟练 Vue3 核心新特性(一)

作者:xuying 全栈修炼转发链接:https://mp.weixin.qq.com/s/_n2seDbbiO5hXQfuUGbUCQ前言Vue3.0 发 beta 版都有一段时间了,正式版也不远了,所以真的要学习一下 Vue3.0 的语法了。本篇文章总共分两部分,望小伙伴们认真阅读。下一篇:10...

用IDEA开发如何用Git快速拉取指定分支代码?

1,准备空的文件夹,git init2,关联远程仓库,git remote add origin gitlab地址3,拉取远程分支代码,git pull origin 远程分支名再用IDEA打开项目即可...

编码 10000 个小时后,开发者悟了:“不要急于发布!”

【CSDN 编者按】在软件开发的道路上,时间是最好的老师。根据“一万小时定律”,要成为某个领域的专家,通常需要大约一万小时的刻意练习。本文作者身为一名程序员,也经历了一万小时的编程,最终悟出了一个道理:慢即是快,重视架构设计和代码质量,确保每一行代码都经得起时间的考验。作者 | Sotiris Ko...

Solid State Logic 发布低保真数字失真插件 Digicrush

Solid State Logic 宣布推出低保真数字失真插件 Digicrush ,他们最新的创意工具具有经典数字失真的粗糙、低保真特性,完美模拟早期数字音频的衰减和伪影。Digicrush 充满怀旧气息,深受经典数字采样器和效果器的影响,具有内置抖动、可调比特深度和采样率降低功能,是为音轨添加复...

你感动了吗?佳能超规格镜头 RF 24-105mm F2.8深度测评

如果要你选一支用作多题材创作的挂机镜头,那我相信很多人会选择24-105mm这个焦段的镜头。作为一支可以实现从广角到长焦的变焦镜头,24-105mm有着丰富的焦段选择。只是基于镜头体积以及光学结构上的限制,此前的24-105mm镜头只能恒定在F4的光圈。而佳能打破了这一限制,将实用焦段和恒定光圈完美...