/**
* 注册共性扩展点
*/
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
/**
Title: JerseyAutoDiscoverable
Description: JerseyAutoDiscoverable
@Override
public void configure(FeatureContext context) {
final Configuration config = context.getConfiguration();
// Register FastJson.
if (!config.isRegistered(FastJsonProvider.class)) {
context.register(FastJsonProvider.class);
}
}
}
上面那个代码引起的原因
@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);
...
}
@VictorZeng 你前面不要注册就好了,你在1.2.36新增JerseyAutoDiscoverable这个自动注册类,这样1.2.36版本强奸了用户必须用fastjsonprovider把默认的JacksonAutoDiscoverable给改掉了,而且类名也取的不好,JerseyAutoDiscoverable改成FastJsonProviderAutoDiscoverable

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);
上面那个也是参考之前google提供的思路
@tbjinyuan 你这个FastJsonFeature中的大部分代码都是没有用的 Jersey register的类是没法删除的,也就是说你注册了多个JsonFeature或者JsonProvider的话,Jersey每次都会遍历一遍,然后根据MediaType找一个最合适的。
@tbjinyuan 所以只选择一种json工具类吧 选择fastjson就不要用Jackson了
@VictorZeng 这个让用户选择啊,你默认注册的fastjsonprovider不是我想要的啊
@tbjinyuan Jackson不是也默认了嘛
@VictorZeng 我的意思你默认没关系,我支持,但是你默认注册的fastjsonprovider不是我想要的类型,我需要在fastjsonprovider做扩展 比如xss安全特性
@VictorZeng 我重新new 一个 FastJsonProvider
FastJsonProvider fastJsonProvider = new FastJsonProvider();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure);
fastJsonProvider.setFastJsonConfig(fastJsonConfig);
register(fastJsonProvider); 可以覆盖掉你吗?
@tbjinyuan 当然了,况且 1.2.36 FastJsonConfig 已经默认了SerializerFeature.BrowserSecure
@VictorZeng 默认xss漏洞这个我知道,我跟温少沟通过,我测试一下,另外in建议你改名成FastJsonProviderAutoDiscoverable
@VictorZeng 我测试了下,压根不行,如果用了
FastJsonProvider fastJsonProvider = new FastJsonProvider();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.BrowserSecure);
fastJsonProvider.setFastJsonConfig(fastJsonConfig);
register(fastJsonProvider); 最后直接进不了 FastJsonProvider,而是JacksonJsonProvider
,这个你自己没验证过
@tbjinyuan 这个我验证过 没有问题啊 你提供一下测试用例
@VictorZeng 你找其他同学验证吧,我太忙了,我要提交一个版本把你那个类去掉,影响到我们业务了
@VictorZeng

上图就是你说的那种方式后的效果,等于我同时注册了fastjsonprovider和jersey自带的JacksonJsonProvider
,也就是说之前FastJsonFeature中的// Disable other JSON providers.
context.property(PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE); 这个代码是有意义的
@tbjinyuan 告诉个最直接的方式把 jersey-media-json-jackson 包排除掉
@VictorZeng 不搞个性化
@tbjinyuan 那就把FastJsonFeature加上吧 大兄弟
上面的图,用的是jackson,不是fastjson,
fastjson目前jsonp不会默认给个callback
@tbjinyuan 为你量身定做的 #1396
这种非独立,而是依赖某个特定环境的增强功能其实弄个独立的jar包就好了,需要就加上依赖,不需要就不加~
@vipcxj 我们也正在考虑这种模块化方式
如果可以开放一些spi就更好了,最近发现这种古老的标准拓展方式其实挺好用~
@kimmking jersey 内置callback使用了@JSONP注解后,JsonWithPaddingInterceptor 会解析
在切换支持fastjson之前,我是用jersey自带的jackson框架,如下代码:
/**
@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
@tbjinyuan 这个建议很好~
@VictorZeng 恩,大兄弟响应很快很棒,我晚上抽空验证下功能,对了 @kimmking @VictorZeng @vipcxj @zhuzhaoyuan @ronnin 大伙谁有代码走读过jersey源码,有沉淀记录吗 转我分享下,我后续有空也深入看下
感谢反馈,问题已经修复,请使用新版本 https://github.com/alibaba/fastjson/releases/tag/1.2.37
Most helpful comment
这种非独立,而是依赖某个特定环境的增强功能其实弄个独立的jar包就好了,需要就加上依赖,不需要就不加~