自定义Jackson的ObjectMapper如何实现@ResponseBody的自定义渲染
XML
1 2 3 4 5 6 7 8 9 10 11 | <? 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
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | < 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 形式下的高级配置:
1 2 3 4 5 6 7 8 9 10 11 | @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源码
1 2 3 4 5 6 | @Retention (RetentionPolicy.RUNTIME) @Target (ElementType.TYPE) @Documented @Import (DelegatingWebMvcConfiguration. class ) public @interface EnableWebMvc { } |
第4行,导入了配置类
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
DelegatingWebMvcConfiguration源码
1 2 3 4 5 6 7 8 9 10 | @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
接口的注入。
1 2 3 4 5 | < 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项目中的配置方式,与示例同理。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
相关文章
在VSCode里使用Jupyter Notebook调试Java代码的详细过程
Jupyter Notebook是以网页的形式打开,可以在网页页面中直接编写代码和运行代码,代码的运行结果也会直接在代码块下显示的程序,这篇文章主要介绍了在VSCode里使用Jupyter Notebook,调试Java代码,需要的朋友可以参考下2022-07-07
最新评论