Java 如何在Spring Boot中为Camel配置Jackson ObjectMapper
我正在尝试使用Jackson在驼峰路由上序列化和反序列化POJO与JSON之间的通信。其中一些具有Java8LocalDate字段,我希望将它们序列化为YYYY-MM-DD字符串,而不是整数数组 我们的Spring Boot应用程序只使用Java配置,所以没有XML配置 我已经成功创建了一个ObjectMapper,它可以满足我的需要,通过将其添加到依赖项中,我们系统的其他部分正在使用它:Java 如何在Spring Boot中为Camel配置Jackson ObjectMapper,java,spring-boot,jackson,apache-camel,Java,Spring Boot,Jackson,Apache Camel,我正在尝试使用Jackson在驼峰路由上序列化和反序列化POJO与JSON之间的通信。其中一些具有Java8LocalDate字段,我希望将它们序列化为YYYY-MM-DD字符串,而不是整数数组 我们的Spring Boot应用程序只使用Java配置,所以没有XML配置 我已经成功创建了一个ObjectMapper,它可以满足我的需要,通过将其添加到依赖项中,我们系统的其他部分正在使用它: <dependency> <groupId>com.fasterxml.j
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<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>
出站休息路线示例:
@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实例,因此不会使用自动添加的JSR310序列化程序/反序列化程序,也不会使用禁用的时间戳功能。我已经阅读了文档,但它没有显示如何使用Spring配置添加自定义数据格式,或者如何对所有类型应用全局自定义
那么,我如何告诉Camel使用我的ObjectMapper,只使用Spring Boot Java配置呢?在Java代码中创建
JacksonDataFormat
,并启用/禁用所需的功能,然后在Camel路由中使用该实例
.unmarshal(myInstanceGoesHere).
如果Camel给您带来麻烦,我将恢复直接使用bean:
from(uri)
.unmarshal().json(JsonLibrary.Jackson)
.beanRef("jsonUtil", "unmarshal")
.bean(myBean);
通过单步执行Camel代码,我找到了一个解决方案。因此,虽然它可以实现我想要的功能,但它可能无法与Camel的未来版本配合使用,因为它似乎没有文档记录,并且可能不受支持 除了问题中的
ObjectMapper
bean之外,我所做的就是将以下bean添加到我的Spring配置中:
@Bean(name = "json-jackson")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public JacksonDataFormat jacksonDataFormat(ObjectMapper objectMapper) {
return new JacksonDataFormat(objectMapper, HashMap.class);
}
需要注意的要点:
的构造函数没有接受不带解组器类型的JacksonDataFormat
。但是,在默认构造函数中,如果没有提供解组类型,则使用ObjectMapper
,因此我使用它。通过某种神奇的方式,这似乎已经习惯于解组所有POJO类型。如果您还需要其他类的更具体的数据格式,则还需要在这些类中设置HashMap.class
ObjectMapper
- Camel似乎在bean注册表中搜索一个名为“json jackson”的bean,因此将springbean设置为使用该名称会诱使Camel不创建新名称,而是使用我的名称
- bean范围必须设置为
,因为REST DSL希望获得scope\u PROTOTYPE
的新实例。看DataFormat
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<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>
到目前为止,只有戴维·爱德华兹的建议对我有效。我首先定义了一个id为“json jackson”的数据格式bean
然后是format类:
公共类JacksonDataFormat扩展了JacksonDataFormat{
公共JacksonDataFormatExt(){
超级();
setPrettyPrint(真);
setEnableFeatures(SerializationFeature.WRITE_DATES_为_TIMESTAMPS.name());
SimpleModule s=新的SimpleModule();
s、 addSerializer(CustomEnum.class,新的CustomEnumSerializer());
添加模块;
}
}
和CustomEnumSerializer类:
公共类CustomEnumSerializer扩展JsonSerializer{
@凌驾
public void serialize(CustomEnumvalue、JsonGenerator jgen、SerializerProvider提供程序)引发IOException、JsonProcessingException{
字符串stringValue=value.getNlsText();
if(stringValue!=null&&!stringValue.isEmpty()&&!stringValue.equals(“null”)){
jgen.writeString(stringValue);
}否则{
jgen.writeNull();
}
}
}
我使用org.apache.Camel:Camel-jackson-starter:2.20.0
它通过Spring应用程序属性为配置公开了一些有用的ObjectMapper属性。例如,可以直接从application.yaml或application.properties文件将日期写入时间戳
有关更多详细信息,请查看JacksonDataFormatConfiguration类
我还需要使用一些mixin,所以我仍然需要将Camel配置为使用Spring的ObjectMapper。我的结局是:
配置bean:
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.mixIn(Person.class, PersonMixin.class);
}
}
}
application.yaml:
camel:
dataformat:
json-jackson:
disable-features: WRITE_DATES_AS_TIMESTAMPS
object-mapper: jacksonObjectMapper
其中,
jacksonObjectMapper
是由已配置的Jackson2ObjectMapperBuilder构建的ObjectMapper bean的名称我无法让任何示例工作。有点失望的是,从阅读变通办法来看,这相当复杂
在我看来,camel应该通过使用应用程序附带的同一个jacksonbean来简化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()));
}
}
如果有人想知道如何使用安装在版本中的修复程序。2.17.. 我使用以下xml配置使其正常工作:
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return builder
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
<camel:camelContext id="defaultCamelContext">
.....
<camel:dataFormats>
<camel:json id="json" library="Jackson" objectMapper="myObjectMapper"/>
</camel:dataFormats>
</camel:camelContext>
.....
…其中myObjectMapper是ObjectMapper类型的spring bean的名称I通过在pom中包含jackson依赖项来解决
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>${camel.version}</version>
</dependency>
大家好消息,现在Spring Boot支持对象映射器自动发现!只需设置此属性:
camel.dataformat.json-jackson.auto-discover-object-mapper=true
如果设置为true,则Jackson将在注册表中查找objectMapper
文件:
日志:
(警告仅表示,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