映射器實例完全是線程安全的,不需要爲單次使用創建映射器,但可以更改映射器的配置。對於傑克遜,如何安全地共享一個ObjectMapper?有沒有不可變的ObjectMapper?
儘管ObjectMapper具有copy函數來複制基於存在映射器的自定義配置,但如果我共享映射器,並不能保證當有人想要自定義映射器時,它們將複製共享映射器。所以我想要一個不可變的映射器來共享,如果有人不小心改變了共享映射器,應該拋出一些異常。
有沒有這樣的事情?
映射器實例完全是線程安全的,不需要爲單次使用創建映射器,但可以更改映射器的配置。對於傑克遜,如何安全地共享一個ObjectMapper?有沒有不可變的ObjectMapper?
儘管ObjectMapper具有copy函數來複制基於存在映射器的自定義配置,但如果我共享映射器,並不能保證當有人想要自定義映射器時,它們將複製共享映射器。所以我想要一個不可變的映射器來共享,如果有人不小心改變了共享映射器,應該拋出一些異常。
有沒有這樣的事情?
寫不可變的包裝比我想象的有CGLIB
/**
* Create a immutable mapper, will hide some config change operation
*/
@SuppressWarnings("unchecked")
static <T extends ObjectMapper> T immutable(T mapper) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ObjectMapper.class);
enhancer.setCallback((InvocationHandler) (proxy, method, args) -> {
if (Modifier.isPublic(method.getModifiers())) {
// banned operation
String name = method.getName();
boolean match = name.startsWith("set") ||
name.startsWith("add") ||
name.startsWith("clear") ||
name.startsWith("disable") ||
name.startsWith("enable") ||
name.startsWith("register") ||
name.startsWith("config");
if (match) {
throw new UnsupportedOperationException(
"Can not modify the immutable mapper, copy the mapper first");
}
}
if (!method.isAccessible()) {
method.setAccessible(true);
}
return method.invoke(mapper, args);
});
return (T) enhancer.create();
}
由於配置得到映射是不可改變的容易,所以我不需要隱藏吸氣。
一種方法是不共享ObjectMapper
實例,而是正確地配置它,然後共享由ObjectMapper
創建的ObjectWriter
和ObjectReader
實例。
ObjectMapper om = new ObjectMapper();
// Configure to your needs
om.enable(...);
om.disable(...);
// Distribute these to the parts of the program where you fear configuration changes.
ObjectWriter writer = om.writer();
ObjectReader reader = om.reader();
這也似乎是由傑克遜的開發商青睞的辦法:https://stackoverflow.com/a/3909846/13075
我將創建ObjectMapper公正公開一些必要的功能 – Jerry06
的包裝,相反,我只是想隱藏一些功能爲了防止配置發生變化,這似乎是非常常見的用例,是否存在這種包裝?如果不是,我會爲自己創建一個。 – wener
一個選項可能是共享一個ObjectWriter實例,而不是ObjectMapper。儘管我相信這不是它的預期目的,但這個類似乍一看是不變的。 – Henrik