[英]Jackson ObjectMapper in Jersey has error with multi thread
我有一个使用球衣2,杰克逊(jersey-media-json-jackson)和ObjectMapper的应用程序。
当线程同时访问同一服务时,序列化将失败,并且某些对象将以空序列化,例如{}。
例:
{"order":1,"itens":[{"id":91},{"id":85},{"id":32},{"id":19},{"id":58},{"id":98},{"id":75},{"id":78},{"id":84},{"id":79}]}
{"order":1,"itens":[{"id":77},{"id":9},{"id":83},{},{},{},{},{},{},{}]} -> bug
{"order":1,"itens":[{"id":71},{"id":94},{"id":58},{},{},{},{},{},{},{}]} -> bug
{"order":1,"itens":[{"id":4},{"id":4},{"id":73},{"id":48},{"id":57},{"id":47},{"id":60},{"id":22},{"id":44},{"id":48}]}
我的代码:
@provider
@Produces (MediaType.APPLICATION_JSON)
public class ObjectMapperResolverJ2 implements ContextResolver <ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperResolverJ2 () {
mapper = new ObjectMapper ();
mapper.setSerializationInclusion (JsonInclude.Include.NON_NULL);
mapper.enable (DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
mapper.enable (DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
mapper.enable (DeserializationFeature.USE_BIG_INTEGER_FOR_INTS);
mapper.disable (SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.disable (SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
mapper.disable (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.configure (SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setVisibility (PropertyAccessor.FIELD, Visibility.ANY);
mapper.setVisibility (PropertyAccessor.SETTER, Visibility.ANY);
mapper.setVisibility (PropertyAccessor.GETTER, Visibility.ANY);
mapper.setVisibility (PropertyAccessor.ALL, Visibility.ANY);
mapper.getVisibilityChecker (). withFieldVisibility (Visibility.ANY);
mapper.getVisibilityChecker (). withSetterVisibility (Visibility.ANY);
mapper.getVisibilityChecker () .GetterVisibility (Visibility.ANY);
mapper.getVisibilityChecker () .with (Visibility.ANY);
}
@Override
public ObjectMapper getContext (Class <?> type) {
return mapper;
}
}
MyApplication.java
public class MyApplication extends ResourceConfig {
public MyApplication () {
register (JacksonFeature.class);
register (ObjectMapperResolverJ2.class);
}
}
服务
@GET
@Path ("/{Order}")
@Produces (MediaType.APPLICATION_JSON)
public OrderDTO getOrder (@PathParam("Order") Integer code) {
// I change return to simplify
OrderDTO order = new OrderDTO();
order.setOrder(1);
List<ItemDTO> itens = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ItemDTO item = new ItemDTO();
item.setId((int) (100 * Math.random()));
itens.add(item);
}
order.setItens(itens);
return order;
}
球衣版本:2.21杰克逊版本2.5.1 Tomcat 7.0.59
我在Jersey版本:2.0,Jackson版本1.9.11和Tomcat 7.0.59上进行了测试,并且可以正常工作。
我解决了更改ObjectMapper注册方式的问题,之前
register(ObjectMapperResolverJ2.class);
后:
JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
provider.setMapper(getObjectMapper());
register(provider);
MyApplication.java
public class MyApplication extends ResourceConfig {
public MyApplication () {
register (JacksonFeature.class);
//register(ObjectMapperResolverJ2.class);
JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
provider.setMapper(getObjectMapper());
register(provider);
}
private ObjectMapper getObjectMapper(){
ObjectMapper mapper = new ObjectMapper ();
mapper.setSerializationInclusion (JsonInclude.Include.NON_NULL);
mapper.enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
mapper.enable(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS);
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
mapper.setVisibility(PropertyAccessor.SETTER, Visibility.ANY);
mapper.setVisibility(PropertyAccessor.GETTER, Visibility.ANY);
mapper.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY);
mapper.getVisibilityChecker().withSetterVisibility(Visibility.ANY);
mapper.getVisibilityChecker().GetterVisibility(Visibility.ANY);
mapper.getVisibilityChecker().with (Visibility.ANY);
return mapper;
}
}
“解决”的最简单方法是使用ThreadLocal,因此每个线程将使用自己的副本
private static final ThreadLocal<ObjectMapper> objectMapperThreadLocal = new ThreadLocal<>();
public static ObjectMapper getObjectMapper() {
ObjectMapper objectMapper = objectMapperThreadLocal.get();
if (objectMapper == null) {
objectMapper = new ObjectMapper();
objectMapperThreadLocal.set(objectMapper);
}
return objectMapper;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.