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


相关文章
|
机器学习/深度学习 JSON 监控
智能定价模型:借助API实时更新商品价格信息
在电子商务的迅猛发展中,价格战成为商家间常见的竞争方式。然而,一成不变的价格策略无法满足市场的即时需求和消费者的多变偏好。因此,智能定价(也称为动态定价)成为了电商平台提升市场竞争力的关键工具。智能定价模型通过实时监控市场数据和消费者行为,自动调整商品价格以最大化收益或实现其他商业目标。本文将深入探讨如何利用API技术实现智能定价,并提供一个Python代码示例来指导读者进行实时价格更新。
|
存储 监控 Kubernetes
k8s诊断之记一次pod oom的异常shmem输出
客户反馈java设置xms,xmx参数固定8G内存,而pod的limit则为16G, 三番五次出现了pod oom的情况,且oom的时候他的业务进程输出也是8g, 同时promethus的监控对应pod的working_set_memory也是8个多g, 剩下的几个g的内存到底去哪里了呢?
4345 1
k8s诊断之记一次pod oom的异常shmem输出
|
算法 决策智能
初谈背包问题——01背包
初谈背包问题——01背包
|
程序员
简历竟然敢写精通并发编程,那你说说AQS为什么要用双向链表?
一位工作4年的程序员 , 简历上写了精通并发编程 , 并且还阅读过AQS( AbstractQueuedSynchronizer)的源码,然后面试官只问了这样一个问题:“AQS 为什么要采用双向链表结构”?,然后就垮了! 其实AQS 大家都不陌生,它是 J.U.C 包里面一个非常重要的线程同步器。今天,我给大家聊聊我的理解。
369 1
|
Oracle jenkins 持续交付
新的centos7.9安装jenkins(二)
新的centos7.9安装jenkins(二)
147 1
|
存储 Arthas 监控
JVM工作原理与实战(三十):堆内存状况的对比分析
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了堆内存状况的对比分析、产生内存溢出的原因等内容。
257 0
|
JSON Java 数据格式
jackson 转换报内存缢出:java.lang.OutOfMemoryError: GC overhead limit exceeded at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:141)
转换报内存缢出。 原因是查询数据时,在转json的数据太大,内存不足 解决方法:1、加内存(没有从根本上解决问题)。2、优化代码,例如减少查询,分页查询。
366 0
|
消息中间件 安全 搜索推荐
【小家java】Java线程池之---ForkJoinPool线程池的使用以及原理(下)
【小家java】Java线程池之---ForkJoinPool线程池的使用以及原理(下)
【小家java】Java线程池之---ForkJoinPool线程池的使用以及原理(下)
|
Java
查看JDK动态代理生成的类的内容
首先我们先定义一个接口: public interface PersonInter { String test(String str); }接着就是我们想的要生成的JDK代理类源码的代码: public class JdkProxy...
1606 0