![](/img/trans.png)
[英]Use Jackson Objectmapper configured by Spring boot in Hibernate
[英]How to configure Jackson ObjectMapper for Camel in Spring Boot
我正在尝试使用 Jackson 在骆驼路线上序列化和反序列化与 JSON 之间的 POJO。 其中一些有 Java 8 LocalDate 字段,我希望它们被序列化为 YYYY-MM-DD 字符串,而不是整数数组。
我们仅将 Java 配置用于我们的 Spring 引导应用程序,因此没有 XML 骆驼配置。
我已经成功地创建了一个 ObjectMapper 来做我想做的事,通过将它添加到我们的依赖项中,我们系统的其他部分正在使用它:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
这对我们的应用程序配置:
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return builder
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
传出 REST 路由示例:
@Component
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
restConfiguration().component("servlet").contextPath("/mycontext")
.port(8080).bindingMode(RestBindingMode.json);
rest("/myendpoint)
.get()
.route()
.to("bean:myService?method=myMethod()");
}
}
传入消息路由示例:
@Component
public class MyRouteBuilder extends RouteBuilder {
@Autowired
private MyBean myBean;
@Override
public void configure() {
from(uri)
.unmarshal().json(JsonLibrary.Jackson)
.bean(myBean);
}
}
但是,默认情况下,Camel 创建自己的 ObjectMapper 实例,因此不会使用Jackson2ObjectMapperBuilder
自动添加的 JSR310 序列化器/反序列化器或禁用的WRITE_DATES_AS_TIMESTAMPS
功能。 我已阅读Camel JSON文档,但它没有显示如何使用 Spring 配置添加自定义数据格式,或如何为所有类型应用全局自定义。
那么如何告诉 Camel 使用我的 ObjectMapper,仅使用 Spring 引导 Java 配置?
我通过单步执行 Camel 代码找到了解决方案。 因此,虽然它可以满足我的要求,但它可能不适用于 Camel 的未来版本,因为它似乎没有记录并且可能不受支持。
我所做的就是将以下 bean 添加到我的 Spring 配置中,以及问题中的ObjectMapper
bean:
@Bean(name = "json-jackson")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public JacksonDataFormat jacksonDataFormat(ObjectMapper objectMapper) {
return new JacksonDataFormat(objectMapper, HashMap.class);
}
需要注意的关键点:
JacksonDataFormat
没有采用没有解组类型的ObjectMapper
构造函数。 但是,在默认构造函数中,当未提供解组类型时使用HashMap.class
,所以我使用它。 通过某种魔法,这似乎习惯于解组所有 POJO 类型。 如果您还需要其他类的更具体的数据格式,您也需要在其中设置ObjectMapper
。SCOPE_PROTOTYPE
因为 REST DSL 期望获得DataFormat
的新实例。 参见CAMEL-7880 。在 Java 代码中创建JacksonDataFormat
并启用/禁用您想要的功能,然后在 Camel 路由中使用该实例。
.unmarshal(myInstanceGoesHere).
使用 Spring 和 Camel 2.18.1,我能够通过添加以下依赖项来实现相同的目标:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.6.1</version>
</dependency>
在CamelContextConfiguration
类中,自动JacksonDataFormat
以配置类路径模块的发现和序列化选项的配置:
@Configuration
public class CamelContextConfig implements CamelContextConfiguration {
@Autowired
public JacksonDataFormat jacksonDataFormat;
@Override
public void beforeApplicationStart(CamelContext camelContext) {
}
@Override
public void afterApplicationStart(CamelContext camelContext) {
jacksonDataFormat
.getObjectMapper()
.findAndRegisterModules()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
大家好消息,Spring Boot 现在支持对象映射器自动发现! 只需设置此属性:
camel.dataformat.json-jackson.auto-discover-object-mapper=true
如果设置为 true,那么 Jackson 将在注册表中查找 objectMapper
文档: https : //camel.apache.org/components/latest/dataformats/json-jackson-dataformat.html#_spring_boot_auto_configuration
日志:
INFO o.a.c.impl.engine.AbstractCamelContext : Apache Camel 3.3.0 (CamelContext: camel-1) is starting
INFO o.a.c.c.jackson.JacksonDataFormat : Found single ObjectMapper in Registry to use: com.fasterxml.jackson.databind.ObjectMapper@20a1b3ae
WARN o.a.c.c.jackson.JacksonDataFormat : The objectMapper was already found in the registry, no customizations will be applied
(警告只是表示, camel.dataformat.json-jackson.*
下的所有其他属性都被忽略)
到目前为止,只有@david-edwards 的建议对我有用。 我首先定义了一个id为“json-jackson”的数据格式bean
<bean id="json-jackson" class="com.mydomain.JacksonDataFormatExt" />
然后是格式类:
public class JacksonDataFormatExt extends JacksonDataFormat{
public JacksonDataFormatExt(){
super();
setPrettyPrint(true);
setEnableFeatures(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS.name());
SimpleModule s = new SimpleModule();
s.addSerializer(CustomEnum.class, new CustomEnumSerializer());
addModule(s);
}
}
和 CustomEnumSerializer 类:
public class CustomEnumSerializer extends JsonSerializer<CustomEnum> {
@Override
public void serialize(CustomEnumvalue, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
String stringValue = value.getNlsText();
if(stringValue != null && !stringValue.isEmpty() && !stringValue.equals("null")) {
jgen.writeString(stringValue);
} else {
jgen.writeNull();
}
}
}
我设法使用org.apache.camel:camel-jackson-starter:2.20.0
非常方便地为 Camel 配置了 ObjectMapper
它通过 Spring 应用程序属性公开了一些有用的 ObjectMapper 属性以进行配置。 例如,可以直接从 application.yaml 或 application.properties 文件设置 WRITE_DATES_AS_TIMESTAMPS。
查找 JacksonDataFormatConfiguration 类以获取更多详细信息。
我还需要使用一些 Mixin,所以我仍然需要配置 Camel 以使用 Spring 的 ObjectMapper。 我结束了这个:
配置豆:
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.mixIn(Person.class, PersonMixin.class);
}
}
}
应用程序.yaml:
camel:
dataformat:
json-jackson:
disable-features: WRITE_DATES_AS_TIMESTAMPS
object-mapper: jacksonObjectMapper
其中jacksonObjectMapper
是配置的 Jackson2ObjectMapperBuilder 构建的 ObjectMapper bean 的名称
如果其他人想知道如何使用版本中的修复程序。 2.17 .. 我使用这个 xml 配置让它工作:
<camel:camelContext id="defaultCamelContext">
.....
<camel:dataFormats>
<camel:json id="json" library="Jackson" objectMapper="myObjectMapper"/>
</camel:dataFormats>
</camel:camelContext>
..其中 myObjectMapper 是 ObjectMapper 类型的 spring bean 的名称
我通过在 pom 中包含 jackson 依赖来解决
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>${camel.version}</version>
</dependency>
现在,只需在路由配置中添加 JacksonDataFormat
public void configure() throws Exception {
JacksonDataFormat jsonDf = new JacksonDataFormat(Card.class);
jsonDf.setPrettyPrint(true);
from("direct:endpoint")
.marshal(jsonDf)
.convertBodyTo(String.class)
.....
}
如果 Camel 在那里给你带来麻烦,我会恢复直接使用 bean:
只需创建一个小型 Json 实用程序,它可以进行编组和解组并将预配置的 ObjectMapper 自动装配到其中。
利用 Camels 很棒的 Spring bean 集成来调用您的实用程序并转换路由中的消息,例如:
from(uri) .unmarshal().json(JsonLibrary.Jackson) .beanRef("jsonUtil", "unmarshal") .bean(myBean);
我无法让任何示例工作。 有点失望的是,阅读变通方法非常复杂。
在我看来,camel 应该通过使用应用程序附带的相同 Jackson bean 来轻松使用 Spring 默认对象映射器。
我放弃使用.json()
并将其换成处理器。
如下所示,这里使用了 Spring 提供的 objectMapper。
路线
from(CONSUME_TAG)
.process("jsonProcessor")
.to("direct:anotherRoute")
.end();
通用处理器注意这如何自动装配 spring boot objectMapper bean。
@Component
public class JsonProcessor implements Processor {
@Autowired
ObjectMapper objectMapper;
@Override
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(objectMapper.writeValueAsString(exchange.getIn().getBody()));
}
}
这对我有用(Camel 2.2.0)
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.5</version>
</dependency>
休息配置
restConfiguration().dataFormatProperty("moduleClassNames", "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule")
.dataFormatProperty("disableFeatures", "WRITE_DATES_AS_TIMESTAMPS")
Spring Boot 在启动期间使用所需jackson-datatype-jsr310
模块配置ObjectMapper
,并将其放入 Spring 上下文。
Camel 的新版本默认不使用ObjectMapper
形式 Spring Context 并在没有jackson-datatype-jsr310
的情况下创建自己的ObjectMapper
。
application.yaml
中。yamlcamel.dataformat.jackson.auto-discover-object-mapper: true
from("some").unmarshal().json(SomeClass.class)
并且不要使用
from("some").unmarshal(new JacksonDataFormat(SomeClass.class))
它不会从 Spring 上下文中获取ObjectMapper
。
要检查会发生什么调试AbstractJacksonDataFormat.doStart()
方法。 它在 Camel 启动期间被调用并从 Spring 上下文中获取ObjectMapper
或创建一个新的。 创建新的ObjectMapper
时,它不需要 Jackson jackson-datatype-jsr310
模块并发生错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.