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());
            }
        }
    }
}


相关文章
|
6月前
|
前端开发 JavaScript 搜索推荐
专业与传统相融,程序员特有祝福:通过前端代码送上新春祝福
新春佳节即将来临,忙了一年,作为程序员,当然要用属于程序员独有的方式来给大家送上新春祝福。在这个喜庆的时刻,让我们以技术的视角来送上一份特别的新春祝福,作为程序员,我们可以用代码和技术,为了大家带来一份独特而有趣的祝福,为了给节日增添一份属于技术人特有的魅力,以前端开发的视角来送上一份特别的新春祝福。作为前端开发者,通过编写前端代码可以创造出丰富多样的视觉效果,可以利用HTML、CSS和JavaScript等编写代码来呈现出直观的新春祝福效果,为大家呈现出生动直观的新春祝福。那么本文以前端程序员的视角,结合前端专业知识送上新春祝福,希望在新的一年里,大家的生活充满幸福和技术的收获。
86 1
专业与传统相融,程序员特有祝福:通过前端代码送上新春祝福
|
JSON 安全 Java
5. JsonFactory工厂而已,还蛮有料,这是我没想到的
一件事情本身的复杂度并不会凭空消失,而是从一个地方转移到另外一个地方
1119 0
5. JsonFactory工厂而已,还蛮有料,这是我没想到的
|
消息中间件 设计模式 JavaScript
这样写代码,同事乐开花!上
这样写代码,同事乐开花!上
|
敏捷开发 测试技术 数据安全/隐私保护
这样写代码,同事乐开花!下
这样写代码,同事乐开花!下
|
消息中间件 JavaScript 小程序
这样写代码,同事乐开花
这样写代码,同事乐开花
|
数据可视化 JavaScript Devops
菜鸟教练的第一次登场
菜鸟教练的第一次登场
118 0
菜鸟教练的第一次登场
|
架构师 测试技术 程序员
全攻略!!!告诉学弟学妹怎么入行游戏行业
有粉丝问我想要做游戏,怎么才能进入游戏行业呐?忆当年,已过十余载,当年大学毕业的时候有学姐进入珠海西山居做测试,当时觉得很高端,好想进去,可惜没有如意,当时觉得很遗憾,不过两年后我还是进入了游戏行业,只是为了弥补遗憾,为了不让和我有同样想法的同学有遗憾,今天聊一下具体入行攻略。
251 0
全攻略!!!告诉学弟学妹怎么入行游戏行业
|
安全 Java 程序员
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(下)
|
设计模式 JSON 安全
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)
5. JsonFactory工厂而已,还蛮有料,这是我没想到的(上)
|
设计模式 Java
最全工厂设计模式案例详解,不服来辩!(二)
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,今天我们一起来彻底解析一下它。
最全工厂设计模式案例详解,不服来辩!(二)