繁体   English   中英

泽西岛的Jackson Jackson出现多线程错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM