5. JsonFactory工厂而已,还蛮有料,这是我没想到的(中)

简介: 5. JsonFactory工厂而已,还蛮有料,这是我没想到的(中)

JsonFactory的Feature


除了JsonGenerator和JsonParser有Feature来控制行为外,JsonFactory也有自己的Feature特征,来控制自己的行为,可以理解为它对读/写均生效。

同样的也是一个内部枚举类:


public enum Feature {
  INTERN_FIELD_NAMES(true),
  CANONICALIZE_FIELD_NAMES(true),
  FAIL_ON_SYMBOL_HASH_OVERFLOW(true),
  USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING(true)
}


小贴士:枚举值均为bool类型,括号内为默认值


每个枚举值都控制着JsonFactory不同的行为。


INTERN_FIELD_NAMES(true)


这是Jackson所谓的key缓存:对JSON的字段名是否调用String#intern方法,放进字符串常量池里,以提高效率,默认是true。


小贴士:Jackson在调用String#intern之前使用InternCache(继承自ConcurrentHashMap)挡了一层,以防止高并发条件下intern效果不显著问题


intern()方法的作用这个老生常谈的话题了,解释为:当调用intern方法时,如果字符串池已经包含一个等于此String对象的字符串(内容相等),则返回池中的字符串。否则,将此 String放进池子里。下面写个例子增加感受感受:


@Test
public void test2() {
    String str1 = "a";
    String str2 = "b";
    String str3 = "ab";
    String str4 = str1 + str2;
    String str5 = new String("ab");
    System.out.println(str5.equals(str3)); // true
    System.out.println(str5 == str3); // false
    // str5.intern()去常量池里找到了ab,所以直接返回常量池里的地址值了,因此是true
    System.out.println(str5.intern() == str3); // true
    System.out.println(str5.intern() == str4); // false
}


想而知,开启这个小功能的意义还是蛮大的。因为同一个格式的JSON串被多次解析的可能性是非常之大的,想想你的Rest API接口,被调用多少次就会进行了多少次JSON解析(想想高并发场景)。这是一种用空间换时间的思想,所以小小功能,大大能量。


小贴士:如果你的应用对内存很敏感,你可以关闭此特征。但,真的有这种应用吗?有吗?


值得注意的是:此特征必须是CANONICALIZE_FIELD_NAMES也为true(开启)的情况下才有效,否则是无效的。


CANONICALIZE_FIELD_NAMES(true)

是否需要规范化属性名。所谓的规范化处理,就是去字符串池里尝试找一个字符串出来,默认值为true。规范化借助的是ByteQuadsCanonicalizer去处理,简而言之会根据Hash值来计算每个属性名存放的位置~


小贴士:ByteQuadsCanonicalizer拥有一套优秀的Hash算法来规范化属性存储,提高效率,抵御攻击(见下特征)


此特征开启了,INTERN_FIELD_NAMES特征的开启才有意义~


FAIL_ON_SYMBOL_HASH_OVERFLOW(true)


当ByteQuadsCanonicalizer处理hash碰撞达到一个阈值时,是否快速失败。


什么时候能达到阈值?官方的说明是:若触发了阈值,这基本可以确定是Dos(denial-of-service)攻击,制造了非常多的相同Hash值的key,这在正常情况下几乎是没有发生的可能性的。


所以,开启此特征值,可以防止攻击,在提高性能的同时也确保了安全。


USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING(true)

是否使用BufferRecycler、ThreadLocal、SoftReference来有效的重用底层的输入/输出缓冲区。这个特性在后端服务(JavaEE)环境下是很有意义的,提效明显。但是对于在Android环境下就不见得了~


总而言之言而总之,JsonFactory的这几个特征值都建议开启,也就是维持默认即可。


定制读/写实例


读写行为的控制是通过各自的Feature来控制的,JsonFactory作为一个功能并非单一的工厂类,需要既能够定制化读JsonParser,也能定制化写JsonGenerator。


为此,对应的API它都提供了三份(一份定制化自己的Feature):


public JsonFactory enable(JsonFactory.Feature f);
public JsonFactory enable(JsonParser.Feature f);
public JsonFactory enable(JsonGenerator.Feature f);
public JsonFactory disable(JsonFactory.Feature f);
public JsonFactory disable(JsonParser.Feature f);
public JsonFactory disable(JsonGenerator.Feature f);
// 合二为一的Configure方法
public JsonFactory configure(JsonFactory.Feature f, boolean state);
public JsonFactory configure(JsonParser.Feature f, boolean state);
public JsonFactory configure(JsonGenerator.Feature f, boolean state);

使用示例:


@Test
public void test3() throws IOException {
    String jsonStr = "{\"age\":18, \"age\": 28 }";
    JsonFactory factory = new JsonFactory();
    factory.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
    try (JsonParser jsonParser = factory.createParser(jsonStr)) {
        // 使用factory定制将不生效
        // factory.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            String fieldname = jsonParser.getCurrentName();
            if ("age".equals(fieldname)) {
                jsonParser.nextToken();
                System.out.println(jsonParser.getIntValue());
            }
        }
    }
}


相关文章
|
7月前
|
安全 Java 程序员
【C++航海王:追寻罗杰的编程之路】继承你学会了么?
【C++航海王:追寻罗杰的编程之路】继承你学会了么?
34 0
|
设计模式 架构师 Java
牛皮了!世界级架构师,图解面向对象编程,小学生都能看得懂
面向对象编程(Object-oriented Programming,缩写:OOP)是软件工程中一种具有对象概念的编程范式(Programming Paradigm),同时也是一种程序开发的抽象方针,与之对应的编程范式还有:函数式编程(Functional Programming)、过程式编程(Procedural Programming)、响应式编程(Reactive Programming)等。
|
Cloud Native Go Python
面试前夜:最后准备的小贴士
面试前夜:最后准备的小贴士
72 0
|
设计模式 分布式计算 Java
你敢信?清华毕业大佬用了一个坦克大战项目就讲完了23种设计模式
坦克大战 一、需求分析 坦克大战中有我方坦克和敌方坦克,我方坦克有一个,敌方坦克有多个。坦克可以移动,也可以发射子弹。我方坦克可以通过上下左右键来控制方向,敌方坦克自动改变方向。在游戏窗体中有障碍物,包括砖墙、钢墙、水墙和草地。坦克可以穿过草地,在遇到其他障碍物时,我方坦克停止移动,并通过操纵改变方向再移动,敌方坦克遇到其他障碍物时可以自动的改变方向。我方坦克有三次生命值,当与敌方坦克或敌方子弹相撞时,生命值减- -, 当生命值是零时,敌方胜利,游戏结束。敌方坦克的生命值为-一,当敌方坦克与我方坦克或者我方子弹相遇就消失,同时我方子弹也消失,并产生爆炸。当我方坦克把敌方坦克消灭完后,我方胜利
86 0
|
消息中间件 算法 Java
面试造飞机? 网易在职顶级大佬“java面试真题 2023” (助上岸)
现在的互联网环境可以说是比较难受的了,学习it的越来越多行业越来越卷,导致更加多的程序员去争取更少的岗位。其实很多人的技术还是不错的但一面试可能还是会被刷下去。
107 0
|
JSON 安全 Java
5. JsonFactory工厂而已,还蛮有料,这是我没想到的
一件事情本身的复杂度并不会凭空消失,而是从一个地方转移到另外一个地方
1141 0
5. JsonFactory工厂而已,还蛮有料,这是我没想到的
|
设计模式 算法 架构师
YYDS!由浅入深学习阿里JDK源码,已在阿里内部疯拿3个金奖
大家好,又是我你们不知道喜不喜爱的架构师之道,今天呢,我想和大家聊一聊JDK源码的问题: * **为什么要看JDK源码** * **JDK源码的阅读顺序** * **JDK源码的最佳学习方法**
154 0
YYDS!由浅入深学习阿里JDK源码,已在阿里内部疯拿3个金奖
技术总监亲自上阵,手撸了一门编程语言,同事直呼哇塞
都说程序员的三大浪漫是:操作系统、编译原理、图形学;但图形学确实是特定的专业领域,我们几乎接触不到,所以对我来说换成网络更合适一些,最后再加上一个数据库。 这四项技术如果都能掌握的话,可以在 IT 行业横着走了,加上这几年互联网行业越来越不景气,越底层的技术就越不可能被替代;所以为了给自己的 30+ 危机留点出路,从今年上半年开始我就逐渐开始从头学习编译原理。 功夫不负有心人,经过近一个月的挑灯夜战,每晚都在老婆的催促下才休息,克服了中途好几次想放弃的冲动,终于现在完成了 GScript 一个预览版。 预览版的意思是语法结构与整体设计基本完成,后续更新也不太会改动这部分内容、但还缺少一些易用功
|
安全 Java 程序员
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
|
设计模式 JSON 安全
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)

热门文章

最新文章

下一篇
开通oss服务