解决spring后端传前端数值为空的问题
问题:在开发当中,由于我的数据传输从DTO在某些场景下,其中的部分字段并不需求进行值的传递,但在其他功能当中需要;(比如开发题目模块时,查询题目采用同一接口,根据题目id不同,后台判断其为多选还是单选进行回传给dto给前端)。
导致出现了如下情况的诸多null值,而这些是没有作用但又不可删除的,因为在其他业务场景下需要这些字段。
先上源代码便于理解。
package com.jingdianjichi.subject.application.dto; import com.jingdianjichi.subject.commom.entity.PageInfo; import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; /** * 题目信息表(SubjectInfo)实体类 * * @author makejava * @since 2024-07-11 22:44:31 */ @Data public class SubjectInfoDTO extends PageInfo implements Serializable { private Long id; /** * 题目名称 */ private String subjectName; /** * 题目难度 */ private Integer subjectDifficult; /** * 出题人名 */ private String settleName; /** * 题目类型 1单选 2多选 3判断 4简答 */ private Integer subjectType; /** * 题目分数 */ private Integer subjectScore; /** * 题目解析 */ private String subjectParse; /** * 题目答案 */ private String subjectAnswer; /** * 分类id */ private List<Integer> categoryIds; /** * 标签id */ private List<Integer> labelIds; /** * 答案选项 */ private List<SubjectAnswerDTO> optionList; /** * 标签name */ private List<String> labelName; private Long categoryId; private Long labelId; private String keyWord; /** * 创建人昵称 */ private String createUser; /** * 创建人头像 */ private String createUserAvatar; /** * 题目数量 */ private Integer subjectCount; /** * 是否被当前用户点赞 */ private Boolean liked; /** * 当前题目点赞的数量 */ private Integer likedCount; /** * 下一题 */ private Long nextSubjectId; /** * 上一题 */ private Long lastSubjectId; }
我们可以看到DTO类封装了许多字段,但是在我查询单选题目情况下,多选,简答等字段便不再需要对其进行展示。
在这种场景下, 我们选取采用通过继承WebMvcConfigurationSupport
类来自定义Spring MVC的配置,将所有JSON数据将通过自定义的如MappingJackson2HttpMessageConverter类
进行序列化和反序列。
首先,我们先了解什么是WebMvcConfigurationSupport?
对WebMvcConfigurationSupport类的理解
官方介绍:
This is the main class providing the configuration behind the MVC Java config.It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an application {@link Configuration @Configuration} class. An alternative more advanced option is to extend directly from this class and override methods as necessary, remembering to add {@link Configuration @Configuration} to the subclass and {@link Bean @Bean} to overridden {@link Bean @Bean} methods.For more details see the javadoc of {@link EnableWebMvc @EnableWebMvc}.
翻译的中文介绍如下:
这是一个在Java MVC配置之后提供配置的主类。它的导入方式是将 @EnableWebMvc注解添加到应用程序@Configuration类。另一个更高级的方式是根据需要覆盖的方法直接extends这个类,但要记住将 @Configuration添加到子类中,将@Bean添加到覆盖的@Bean方法中。有关更多细节,请参见@EnableWebMvc的javadoc。
主要特点
-
默认配置:
WebMvcConfigurationSupport
类包含了Spring MVC的一些默认配置,例如自动注册视图解析器、消息转换器(如JSON转换)、数据格式化器等。
-
可扩展性:
- 继承
WebMvcConfigurationSupport
的类可以覆盖其中的方法,从而定制Spring MVC的行为。例如,你可以覆盖configureMessageConverters
方法来添加自定义的消息转换器,或者覆盖addResourceHandlers
方法来配置静态资源处理。
- 继承
-
拦截器注册:
- 你也可以通过覆盖
addInterceptors
方法来注册拦截器,这些拦截器可以用于处理请求前后的逻辑,比如认证、日志记录等。
- 你也可以通过覆盖
-
视图控制器:
- 可以通过覆盖
addViewControllers
方法来添加视图控制器,它们可以快速映射URL到特定的视图,而无需显式控制器方法。
- 可以通过覆盖
使用示例
在Spring Boot应用中,你可能会看到如下配置:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurationSupport { @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyCustomInterceptor()); } @Override protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new MyCustomMessageConverter()); super.configureMessageConverters(converters); } }
在这个示例中,WebConfig
类继承了WebMvcConfigurationSupport
,并且覆盖了addInterceptors
和configureMessageConverters
方法,分别用于注册自定义的拦截器和消息转换器。
需要注意的是,如果你在Spring Boot应用中使用@EnableWebMvc
注解,那么Spring Boot的自动配置会被禁用,你将完全负责MVC的配置。如果不使用@EnableWebMvc
,则可以与Spring Boot的默认配置共存,只覆盖或添加你关心的部分配置。
再次回到我们本次的目的,解决json空值问题。
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
package com.jingdianjichi.subject.application.config; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.util.List; /** * mvc的全局处理 * * @author: ChickenWing * @date: 2023/10/7 */ @Configuration public class GlobalConfig extends WebMvcConfigurationSupport { @Override protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); converters.add(mappingJackson2HttpMessageConverter()); } // @Override // protected void addInterceptors(InterceptorRegistry registry) { // registry.addInterceptor(new LoginInterceptor()) // .addPathPatterns("/**"); // } /** * 自定义mappingJackson2HttpMessageConverter * 目前实现:空值忽略,空字段可返回 */ private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return new MappingJackson2HttpMessageConverter(objectMapper); } }
-
configureMessageConverters
:- 这个方法用于配置HTTP消息转换器,即Spring MVC用来读取和写入HTTP请求和响应体中的数据的组件。在你的代码中,这个方法首先调用父类的同名方法来应用默认的配置,然后添加了一个自定义的
MappingJackson2HttpMessageConverter
实例到转换器列表中。这意味着所有的JSON数据将通过你自定义的MappingJackson2HttpMessageConverter
进行序列化和反序列化。
- 这个方法用于配置HTTP消息转换器,即Spring MVC用来读取和写入HTTP请求和响应体中的数据的组件。在你的代码中,这个方法首先调用父类的同名方法来应用默认的配置,然后添加了一个自定义的
-
mappingJackson2HttpMessageConverter
:- 这个方法创建并配置了一个
MappingJackson2HttpMessageConverter
实例。在这个方法中,你创建了一个新的ObjectMapper
实例,并设置了两个重要的配置:configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
: 这个配置告诉Jackson,即使遇到空的JavaBean(没有任何非默认值的字段)也不抛出异常,而是将其序列化为空的JSON对象。setSerializationInclusion(JsonInclude.Include.NON_NULL);
: 这个配置原本是告诉Jackson,在序列化对象时,只包含非null
的字段,忽略所有null
值。不过,你没有激活这个配置,因此默认情况下所有字段都会被序列化,包括null
值。
- 这个方法创建并配置了一个
这时,null值传输问题便可以得到妥善解决!