SpringBoot项目如何把接口参数中的空白值替换为null值(推荐)

  • 更新时间:2022-07-27 14:33:53
  • 编辑:冷锐进
给网友们整理SpringBoot相关的编程文章,网友司萧玉根据主题投稿了本篇教程内容,涉及到SpringBoot空白值替换为null值、SpringBoot接口参数空白值替换为null值、SpringBoot空白值替换为null值相关内容,已被102网友关注,内容中涉及的知识点可以在下方直接下载获取。
《基于SpringBoot实现:Java分布式中间件开发入门与实战》源码文件
《基于SpringBoot实现:Java分布式中间件开发入门与实战》源码文件
  • 大小:206 MB
  • 发布人:桂爰爰
  • 下载:SpringBoot

SpringBoot空白值替换为null值

问题发生

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

public List<BasReservoirArea> selectList(BasReservoirArea basReservoirArea) {
  QueryWrapper<BasReservoirArea> where = new QueryWrapper<>();
  where.setEntity(basReservoirArea);
  return baseMapper.selectList(where);
}

查询的方法是Get方法:

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

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

初始解决

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

//1.对象转map
Map<Object, Object> map = MapUtil.beanToMap(test);
//2.移除空值
MapUtil.removeNullValue(map);
//3.map转回对象
Test entity = JSON.parseObject(JSON.toJSONString(map), Test.class);

用到的工具类如下

/**
* 将对象属性转化为map结合
*/
public static <T> Map<Object, Object> beanToMap(T bean) {
 Map<Object, Object> map = new HashMap<>();
 if (bean != null) {
 BeanMap beanMap = BeanMap.create(bean);
 for (Object key : beanMap.keySet()) {
  map.put(key, beanMap.get(key));
 }
 }
 return map;
}
/**
* 移除map中的value空值
*
* @param map
* @return
*/
public static void removeNullValue(Map map) {
 Set set = map.keySet();
 for (Iterator iterator = set.iterator(); iterator.hasNext(); ) {
 Object obj = (Object) iterator.next();
 Object value = (Object) map.get(obj);
 remove(value, iterator);
 }
}

问题解决了。

优化

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

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

Post请求报文体

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

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

public class StringDescrializer extends JsonDeserializer<String> {
  @Override
  public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
    String value = jsonParser.getValueAsString();
    if (value == null || "".equals(value.trim())) {
      return null;
    }
    return value;
  }
}

创建一个MappingJackson2HttpMessageConverter Bean:

@Bean
@Primary
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
 MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
 //设置解析JSON工具类
 ObjectMapper objectMapper = new ObjectMapper();
 objectMapper.getSerializerProvider().setNullValueSerializer(
 new JsonSerializer<Object>() {
  @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<MediaType> list = new ArrayList<>();
  list.add(MediaType.APPLICATION_JSON_UTF8);
  jsonConverter.setSupportedMediaTypes(list);
  return jsonConverter;
}

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

Get路径带参数

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

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

public class StringEditor extends PropertyEditorSupport {
  //setAsText完成字符串到具体对象类型的转换,
  @Override
  public void setAsText(String text) throws IllegalArgumentException {
    if (text == null || "".equals(text.trim())) {
      text = null;
    }
    setValue(text);
  }

  //getAsText完成具体对象类型到字符串的转换。
  @Override
  public String getAsText() {
    if (getValue() != null) {
      return getValue().toString();
    }
    return null;
  }
}

想要全局controller共享这个Databinder:

@ControllerAdvice
public class GlobalControllerAdiviceController {
  //WebDataBinder是用来绑定请求参数到指定的属性编辑器,可以继承WebBindingInitializer
  //来实现一个全部controller共享的dataBiner 
  @InitBinder
  public void dataBind(WebDataBinder binder) {
    ///給指定类型注册类型转换器操作
    binder.registerCustomEditor(String.class, new StringEditor());
  }
}

对于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>(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和功能都不为人知。所以碰上问题就记录下来是个很好的习惯

到此这篇关于SpringBoot项目如何优雅的把接口参数中的空白值替换为null值的文章就介绍到这了,更多相关SpringBoot空白值替换为null值内容请搜索java学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持java学习网!

相关下载

  • SpringBoot项目如何将jar包打包成war包

    大小:108 KB
  • SpringBoot全教程

    大小:20.6 MB
  • Sharding-Jdbc在springboot中配置

    大小:2.5 MB

相关教程

  • 手把手教你SpringBoot快速集成Swagger的配置过程

    手把手教你SpringBoot快速集成Swagger的配置过程

    给网友朋友们带来一篇关于SpringBoot的教程,这篇文章主要介绍了手把手教你SpringBoot快速集成Swagger的配置过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    发布时间:2022-06-24SpringBoot集成Swagger

  • SpringBoot中自定义注解实现参数非空校验的示例

    给网友朋友们带来一篇关于SpringBoot的教程,这篇文章主要介绍了SpringBoot中自定义注解实现参数非空校验,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下

    发布时间:2022-06-10SpringBoot 参数非空校验

  • Springboot 跨域配置无效及接口访问报错的解决方法

    给大家整理了关于Springboot的教程,这篇文章主要介绍了Springboot 跨域配置无效及接口访问报错的解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    发布时间:2022-06-19Springboot 跨域配置

  • springboot的三种启动方式总结

    springboot的三种启动方式总结

    给网友们整理关于springboot的教程,这篇文章主要介绍了详解springboot的三种启动方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    发布时间:2022-07-01springboot的三种启动方式

  • SpringBoot缓存Ehcache的使用详解

    SpringBoot缓存Ehcache的使用详解

    为网友们分享了关于SpringBoot的教程,EhCache、Redis比较常用,使用Redis的时候需要先安装Redis服务器,本文给大家介绍SpringBoot缓存Ehcache的使用详解,感兴趣的朋友跟随小编一起看看吧

    发布时间:2022-06-14SpringBoot缓存Ehcache

  • SpringBoot生成二维码的实现

    SpringBoot生成二维码的实现

    给大家整理一篇关于SpringBoot的教程,这篇文章主要介绍了SpringBoot生成二维码的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    发布时间:2022-06-24SpringBoot生成二维码

  • SpringBoot集成Druid监控页面最小化配置操作

    SpringBoot集成Druid监控页面最小化配置操作

    为网友们分享了关于SpringBoot的教程,这篇文章主要介绍了SpringBoot集成Druid监控页面最小化配置操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    发布时间:2022-06-27SpringBoot Druid页面配置

  • Idea安装及涉及springboot详细配置的图文教程

    Idea安装及涉及springboot详细配置的图文教程

    给大家整理了关于idea的教程,这篇文章主要介绍了Idea安装及涉及springboot详细配置,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    发布时间:2022-06-13Idea安装springboot配置

用户留言