![](/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.