自定义Jackson的ObjectMapper如何实现@ResponseBody的自定义渲染

 更新时间:2024年07月08日 09:53:21   作者:qq_32331073  
这篇文章主要介绍了自定义Jackson的ObjectMapper如何实现@ResponseBody的自定义渲染,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="bean1" class="test.Bean1" />
    <bean id="bean2" class="test.Bean2" />

</beans>

通常,我们可以采用下面的Java Config方式代替上面的Xml,实现 fine-grained(细粒度) 配置。

Java Config

package test;

@Configuration
public class WebConfig {
  @Bean
  public Bean1 bean1(){
       //……
  }
  @Bean
  public Bean2 bean2(){
       //……
  }
}

XXXConfigurer

但是,有时候我们希望:

一组功能相关的Bean之间能够建立更直接更明确的关系。

那么我们可以选择实现 XXXConfigurer 这类 回调接口,然后使用 @Configuration注解该实现类,并Override它们的抽象方法。

例如:

功能回调接口
缓存org.springframework.cache.annotation.CachingConfigurer
定时任务org.springframework.scheduling.annotation.SchedulingConfigurer
异步(并发)任务org.springframework.scheduling.annotation.AsyncConfigurer
Spring MVC高级配置org.springframework.web.servlet.config.annotation.WebMvcConfigurer

注意:

XXXConfigurer 接口的实现类无疑需要复写其全部抽象方法(Java8之前,Spring旧版本),但是如果不希望覆盖默认增加额外配置:

  • 方法有返回值,则 return null。
  • 方法无返回值,则不写任何实现代码。
  • 当然你也可以直接继承其抽象适配器 XXXConfigurerAdapter ,根据配置需要复写方法。
  • 当然Java8以后,接口方法有了默认实现default,在新版的Spring中,你可以直接实现 XXXConfigurer 接口,并根据配置复写方法。

示例:WebMvcConfigurer

我们以 WebMvcConfigurer 为例:自定义Jackson的ObjectMapper,实现@ResponseBody的自定义渲染?

  • 解决方法是配置Spring MVC的 HttpMessageConverter 消息转换器

先来看xml方式

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
		
		<mvc:annotation-driven >
			<mvc:message-converters>
        		<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            		<property name="objectMapper" ref="objectMapper"/>
        		</bean>
       	    </mvc:message-converters>
		</mvc:annotation-driven>

     	<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
           p:serializationInclusion="NON_NULL"/>

WebMvcConfigurer的抽象适配器

我们还可以通过继承 WebMvcConfigurer 的抽象适配器

org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter

来实现Spring MVC在Java Config 形式下的高级配置:

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

	    @Override
	    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
	        ObjectMapper mapper = new ObjectMapper();
	        mapper.setDefaultPropertyInclusion(Include.NON_NULL);
	        converters.add(new MappingJackson2HttpMessageConverter(mapper));
	    }
}

@EnableWebMvc

到这里,我们已经实现了Spring MVC在Java Config 形式下的高级配置,但是需要注意,这里我们使用了 @EnableWebMvc

@EnableWebMvc源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

第4行,导入了配置类

org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration

DelegatingWebMvcConfiguration源码

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    
    @Autowired(required = false)
 	public void setConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.configurers.addWebMvcConfigurers(configurers);
		}
	}
}

可以看到,DelegatingWebMvcConfiguration的作用就是注入WebMvcConfigurer的实现类, 而 DelegatingWebMvcConfiguration 又需要@EnableWebMvc来导入。

所以如果你没有使用Spring Boot,而是传统的

Spring项目,又想要使用WebMvcConfigurer来实现细粒度配置,你需要@EnableWebMvc

官方文档上给出了另一种解决方式:

If WebMvcConfigurer does not expose some advanced setting that needs to be configured,
consider removing the @EnableWebMvc annotation and extending directly from
WebMvcConfigurationSupport or DelegatingWebMvcConfiguration,

如果WebMvcConfigurer没能解决你的需求,那么你可以考虑移除 @EnableWebMvc并且直接继承WebMvcConfigurationSupport or DelegatingWebMvcConfiguration

注意:

Spring boot已经通过Spring MVC的自动配置类WebMvcAutoConfiguration导入了DelegatingWebMvcConfiguration,所以不再需要@EnableWebMvc

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

相对的,如果你使用了@EnableWebMvc,那么Spring MVC的自动配置将被忽略。

@EnableXXX与<xxx:annotation-driven>的冲突

对于传统Spring项目,Java Config的使用势必导致Xml 与Java Config 同时存在于项目中。

这时候就需要我们去考虑Xml与annotation-based之间是否会产生冲突。

比如下面这些基本功能相同的标签注解

这里强调基本功能,因为Java Config的配置更细粒度,自然容易获得其他扩展导致某些功能不一致。

例如:@EnableWebMvc导入了DelegatingWebMvcConfiguration,从而实现了WebMvcConfigurer接口的注入。

<cache:annotation-driven /> <!--@EnableCaching--> 
<task:annotation-driven scheduler=""/> <!--@EnableScheduling--> 
<task:annotation-driven executor=""/> <!--@EnableAsync--> 
<mvc:annotation-driven /> <!--@EnableWebMvc--> 
<!-- …… 等等,诸如此类 -->

这里还是以<mvc:annotation-driven /> @EnableWebMvc为例,如果二者同时存在:

  • 传统Spring项目以web.xml加载dispatcher-servlet.xml,毫无疑问配置在xml中的<mvc:annotation-driven />将会优先生效。
  • 所以,此时 @EnableWebMvc不生效,WebMvcConfigurer的实现类将不会被注入,Java Config的配置方式不会生效。
  • 所以,这种情况需要二选一。

至于,其他**XXXConfigurer** 在传统Spring项目中的配置方式,与示例同理。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java模拟实现HTTP服务器项目实战

    Java模拟实现HTTP服务器项目实战

    本文主要介绍了Java模拟实现HTTP服务器项目实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • springboot使用@value读取配置的方法

    springboot使用@value读取配置的方法

    今天我们来讲一下如何通过python来实现自动登陆京东,以及签到领取金币。本文图文实例相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧
    2019-10-10
  • java邮件发送的实现

    java邮件发送的实现

    本篇是用于java来实现邮件的发送的实例代码,基于smtp服务,有需要的可以参考一下。
    2016-10-10
  • 在VSCode里使用Jupyter Notebook调试Java代码的详细过程

    在VSCode里使用Jupyter Notebook调试Java代码的详细过程

    Jupyter Notebook是以网页的形式打开,可以在网页页面中直接编写代码和运行代码,代码的运行结果也会直接在代码块下显示的程序,这篇文章主要介绍了在VSCode里使用Jupyter Notebook,调试Java代码,需要的朋友可以参考下
    2022-07-07
  • IntelliJ IDEA 中必有得插件和配置

    IntelliJ IDEA 中必有得插件和配置

    这篇文章主要介绍了IntelliJ IDEA 中必有得插件和配置,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Java编程时间日期API实例解析

    Java编程时间日期API实例解析

    本文主要介绍了Java编程时间日期API实例解析的相关内容,分享了一则实例,具有一定借鉴价值,需要的朋友可以参考下。
    2018-01-01
  • 详解Java volatile 内存屏障底层原理语义

    详解Java volatile 内存屏障底层原理语义

    为了保证内存可见性,java 编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。为了实现 volatile 内存语义,JMM 会分别限制这两种类型的重排序类型
    2021-09-09
  • Java中的Semaphore信号量深入解析

    Java中的Semaphore信号量深入解析

    这篇文章主要介绍了Java中的Semaphore信号量深入解析,Semaphore是Java里面另外一个基本的并发工具包类,主要的的作用是用来保护共享资源的访问的,也就是仅仅允许一定数量的线程访问共享资源,需要的朋友可以参考下
    2023-11-11
  • 聊聊mybatis sql的括号问题

    聊聊mybatis sql的括号问题

    这篇文章主要介绍了mybatis sql的括号问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java不可不知的泛型使用示例代码

    Java不可不知的泛型使用示例代码

    这篇文章主要介绍了Java不可不知的泛型使用,本文通过实例代码给大家介绍了java的泛型的基本使用,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08

最新评论