[alibaba/fastjson]fastjson 1.2.29 升级到1.2.36 导致FastJsonProvider 提前被注册引发个性定制失效

2025-11-25 843 views
6

/**

  • 注册共性扩展点 */ protected void registerProviders() { //基础扩展插件簇 register(MultiPartFeature.class); //use alibaba fastsjon register(FastJsonFeature.class); //register(JacksonObjectMapperProvider.class); //register(JacksonFeature.class); }

FastJsonFeature 代码如下:

public class FastJsonFeature implements Feature {

private final static String JSON_FEATURE = FastJsonFeature.class.getSimpleName();

@Override
public boolean configure(final FeatureContext context) {
    final Configuration config = context.getConfiguration();
    final String jsonFeature = CommonProperties.getValue(config.getProperties(), config.getRuntimeType(), InternalProperties.JSON_FEATURE, JSON_FEATURE,
        String.class);
    // Other JSON providers registered.
    if (!JSON_FEATURE.equalsIgnoreCase(jsonFeature)) {
        return false;
    }
    // Disable other JSON providers.
    context.property(PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE);
    // Register FastJson.
    if (!config.isRegistered(FastJsonProvider.class)) {
        FastJsonProvider fastJsonProvider = new FastJsonProvider();
        FastJsonConfig fastJsonConfig=new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure);
        fastJsonProvider.setFastJsonConfig(fastJsonConfig);
        context.register(fastJsonProvider, MessageBodyReader.class, MessageBodyWriter.class);
    }
    return true;
}

}

为什么不直接在registerProviders方法中注册 register(FastJsonProvider.class); 而是 register(FastJsonFeature.class);是因为我在想定制失效循环检测特性以及开始浏览器安全特性,

如: FastJsonProvider fastJsonProvider = new FastJsonProvider(); FastJsonConfig fastJsonConfig=new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure); fastJsonProvider.setFastJsonConfig(fastJsonConfig); context.register(fastJsonProvider, MessageBodyReader.class, MessageBodyWriter.class);

上述代码我升级到1.2.36后,这个if语句里代码进不去了,我初步判断原因是:

1.2.36中FastJsonProvider默认被jersey发现注册了,替换到了默认的jackson序列化

而1.2.29版本中,是需要显示注册 register(FastJsonProvider.class);的

我想要的效果需要自己代码注册FastJsonProvider,除非默认自动注册的FastJsonProvider默认自带 fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure); 这2个feature

回答

0

/**

  • Title: JerseyAutoDiscoverable
  • Description: JerseyAutoDiscoverable
  • @author Victor.Zxy
  • @see AutoDiscoverable
  • @since 1.2.36 */ @Priority(AutoDiscoverable.DEFAULT_PRIORITY + 1) public class JerseyAutoDiscoverable implements AutoDiscoverable {

    @Override public void configure(FeatureContext context) {

    final Configuration config = context.getConfiguration();
    
    // Register FastJson.
    if (!config.isRegistered(FastJsonProvider.class)) {
    
        context.register(FastJsonProvider.class);
    }

    } }

4

上面那个代码引起的原因

6

@tbjinyuan 目前Jersey已注册类(Provider/Feature/...)是无法进行删除的,FastJsonFeature 中的代码在Jersey中其实无法对FastJsonProvider重新注册,在“注册共性扩展点“时,就应该直接注册FastJsonProvider,e.g.

protected void registerProviders() {
...
//use alibaba fastsjon
FastJsonProvider fastJsonProvider = new FastJsonProvider();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure);
fastJsonProvider.setFastJsonConfig(fastJsonConfig);

register(fastJsonProvider);
...
}
4

@VictorZeng 你前面不要注册就好了,你在1.2.36新增JerseyAutoDiscoverable这个自动注册类,这样1.2.36版本强奸了用户必须用fastjsonprovider把默认的JacksonAutoDiscoverable给改掉了,而且类名也取的不好,JerseyAutoDiscoverable改成FastJsonProviderAutoDiscoverable

1

register(FastJsonFeature.class);

public class FastJsonFeature implements Feature {

private final static String JSON_FEATURE = FastJsonFeature.class.getSimpleName();

@Override public boolean configure(final FeatureContext context) { final Configuration config = context.getConfiguration(); final String jsonFeature = CommonProperties.getValue(config.getProperties(), config.getRuntimeType(), InternalProperties.JSON_FEATURE, JSON_FEATURE, String.class); // Other JSON providers registered. if (!JSON_FEATURE.equalsIgnoreCase(jsonFeature)) { return false; } // Disable other JSON providers. context.property(PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE); // Register FastJsonfastJsonProvider. if (!config.isRegistered(FastJsonProvider.class)) { FastJsonProvider fastJsonProvider = new FastJsonProvider(); FastJsonConfig fastJsonConfig=new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure); fastJsonProvider.setFastJsonConfig(fastJsonConfig); context.register(fastJsonProvider, MessageBodyReader.class, MessageBodyWriter.class); } return true; } 我这样在运行时第一次注册 context.register(fastJsonProvider, MessageBodyReader.class, MessageBodyWriter.class);

6

上面那个也是参考之前google提供的思路

2

@tbjinyuan 你这个FastJsonFeature中的大部分代码都是没有用的 Jersey register的类是没法删除的,也就是说你注册了多个JsonFeature或者JsonProvider的话,Jersey每次都会遍历一遍,然后根据MediaType找一个最合适的。

3

@tbjinyuan 所以只选择一种json工具类吧 选择fastjson就不要用Jackson了

0

@VictorZeng 这个让用户选择啊,你默认注册的fastjsonprovider不是我想要的啊

0

@tbjinyuan Jackson不是也默认了嘛

3

@VictorZeng 我的意思你默认没关系,我支持,但是你默认注册的fastjsonprovider不是我想要的类型,我需要在fastjsonprovider做扩展 比如xss安全特性

6

@VictorZeng 我重新new 一个 FastJsonProvider FastJsonProvider fastJsonProvider = new FastJsonProvider(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure); fastJsonProvider.setFastJsonConfig(fastJsonConfig); register(fastJsonProvider); 可以覆盖掉你吗?

2

@tbjinyuan 当然了,况且 1.2.36 FastJsonConfig 已经默认了SerializerFeature.BrowserSecure

5

@VictorZeng 默认xss漏洞这个我知道,我跟温少沟通过,我测试一下,另外in建议你改名成FastJsonProviderAutoDiscoverable

5

@VictorZeng 我测试了下,压根不行,如果用了 FastJsonProvider fastJsonProvider = new FastJsonProvider(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure); fastJsonProvider.setFastJsonConfig(fastJsonConfig); register(fastJsonProvider); 最后直接进不了 FastJsonProvider,而是JacksonJsonProvider ,这个你自己没验证过

1

@tbjinyuan 这个我验证过 没有问题啊 你提供一下测试用例

4

@VictorZeng 你找其他同学验证吧,我太忙了,我要提交一个版本把你那个类去掉,影响到我们业务了

6

@VictorZeng

上图就是你说的那种方式后的效果,等于我同时注册了fastjsonprovider和jersey自带的JacksonJsonProvider ,也就是说之前FastJsonFeature中的// Disable other JSON providers. context.property(PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE); 这个代码是有意义的

6

@tbjinyuan 告诉个最直接的方式把 jersey-media-json-jackson 包排除掉

0

@VictorZeng 不搞个性化

5

@tbjinyuan 那就把FastJsonFeature加上吧 大兄弟

8

上面的图,用的是jackson,不是fastjson, fastjson目前jsonp不会默认给个callback

3

@tbjinyuan 为你量身定做的 #1396

4

这种非独立,而是依赖某个特定环境的增强功能其实弄个独立的jar包就好了,需要就加上依赖,不需要就不加~

7

@vipcxj 我们也正在考虑这种模块化方式

4

如果可以开放一些spi就更好了,最近发现这种古老的标准拓展方式其实挺好用~

1

@kimmking jersey 内置callback使用了@JSONP注解后,JsonWithPaddingInterceptor 会解析

7

在切换支持fastjson之前,我是用jersey自带的jackson框架,如下代码: /**

  • {@link AutoDiscoverable} registering {@link JacksonFeature} if the feature is not already registered.
  • @author Michal Gajdos */ @Priority(AutoDiscoverable.DEFAULT_PRIORITY) public class JacksonAutoDiscoverable implements AutoDiscoverable {

    @Override public void configure(final FeatureContext context) { if (!context.getConfiguration().isRegistered(JacksonFeature.class)) { context.register(JacksonFeature.class); } } } 但jackjson有个策略是默认输出哪些为null值的属性,我们这边需要不输出null,所以我用rs提供的SPI扩展,如下图 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); -------------分割线------------

类似的 @VictorZeng 如果强制绑定了1.2.36版本中fastjsonprovider作为序列化反序列化框架,那么也需要提供类似的扩展代码,让业务切入进去,参考上面的实现 @vipcxj @wenshao

6

@tbjinyuan 这个建议很好~

0

@VictorZeng 恩,大兄弟响应很快很棒,我晚上抽空验证下功能,对了 @kimmking @VictorZeng @vipcxj @zhuzhaoyuan @ronnin 大伙谁有代码走读过jersey源码,有沉淀记录吗 转我分享下,我后续有空也深入看下