亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JSON.toJSONString使用異常分析

 更新時間:2023年09月11日 15:36:29   作者:土豆肉絲蓋澆飯  
這篇文章主要為大家介紹了JSON.toJSONString使用異常分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

先說說坑

JSON.toString在序列化對象時,默認通過的是get*()方法來查找屬性,而不是具體某個屬性,同時回忽略transient注解的屬性。

測試案例如下

public class FastJsonTest {
    public static void main(String[] args) {
        Person person = new Person();
        person.setBirth(new Date());
        System.out.println(JSON.toJSONString(person));
    }
    public static class Person{
        private Integer age =123;
        private transient Date birth;
        public Date getBirth() {
            return birth;
        }
        public void setBirth(Date birth) {
            this.birth = birth;
        }
        public String getName(){
            return "scj";
        }
    }
}

輸出

{"name":"scj"}

問題發(fā)生

最近在迭代一個老項目,升級中間件框架版本(不升級不給打包部署)后,在項目啟動的時候居然拋出以下異常

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.masaike.yama.platform.domain.model.product.ProductServiceEntity.properties, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201)
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:145)
    at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:261)
    at com.masaike.yama.platform.infrastructure.converter.ProductServiceConverterImpl.productServicePropertyVOListToProductServicePropertyDTOList(ProductServiceConverterImpl.java:139)
    at com.masaike.yama.platform.infrastructure.converter.ProductServiceConverterImpl.map(ProductServiceConverterImpl.java:50)
    at com.masaike.yama.platform.infrastructure.converter.ProductServiceConverterImpl.entityListToDTOList(ProductServiceConverterImpl.java:32)
    at com.masaike.yama.platform.query.ProductServiceQueryServiceImpl.getAllProductService(ProductServiceQueryServiceImpl.java:43)
    at com.alibaba.fastjson.serializer.ASMSerializer_12_ProductServiceQueryServiceImpl.write(Unknown Source)
    at com.alibaba.fastjson.serializer.JSONSerializer.writeWithFieldName(JSONSerializer.java:333)
    at com.alibaba.fastjson.serializer.ASMSerializer_1_InterfaceInfo.write(Unknown Source)
    at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:285)
    at com.alibaba.fastjson.JSON.toJSONString(JSON.java:745)
    at com.alibaba.fastjson.JSON.toJSONString(JSON.java:683)
    at com.alibaba.fastjson.JSON.toJSONString(JSON.java:648)
    at com.alibaba.dubbo.config.masaikehttp.ExportedInterfaceManager.addInterface(ExportedInterfaceManager.java:104)//關鍵點
    at com.alibaba.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:321)
    at com.alibaba.dubbo.config.ServiceConfig.export(ServiceConfig.java:218)
    at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:123)
    at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:49)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:886)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230)
    at com.masaike.yama.bootstrap.BootStrapApplication.main(BootStrapApplication.java:36)

這個一個使用JPA時常見問題:延遲加載的時候session不存在

關于延遲加載no-session問題,可以看如何解決JPA延遲加載no Session報錯

從日志定位到拋出異常的方法為

@Override
@Transactional(rollbackFor = Exception.class)
public List<XXDTO> getAllXX() {
    List<XXEntity> result = xXQueryRepository.findAll();
    //下面的converter會觸發(fā)延遲加載
    return XXConverter.INSTANCE.entityListToDTOList(result);
}

這邊存在兩個迷惑性行為

  • 啟動的時候怎么調用了getAllXX方法
  • getAllXX我加了@Transactional,理論上是有session的

問題排查

精簡上面的異常棧

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.masaike.yama.platform.domain.model.product.ProductServiceEntity.properties, could not initialize proxy - no Session
    at com.masaike.yama.platform.infrastructure.converter.ProductServiceConverterImpl.productServicePropertyVOListToProductServicePropertyDTOList(ProductServiceConverterImpl.java:139)
    at com.masaike.yama.platform.infrastructure.converter.ProductServiceConverterImpl.map(ProductServiceConverterImpl.java:50)
    at com.masaike.yama.platform.infrastructure.converter.ProductServiceConverterImpl.entityListToDTOList(ProductServiceConverterImpl.java:32)
    at com.masaike.yama.platform.query.ProductServiceQueryServiceImpl.getAllProductService(ProductServiceQueryServiceImpl.java:43)
    at com.alibaba.fastjson.JSON.toJSONString(JSON.java:648)
    at com.alibaba.dubbo.config.masaikehttp.ExportedInterfaceManager.addInterface(ExportedInterfaceManager.java:104)//關鍵點
    at com.alibaba.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:321)
    at com.alibaba.dubbo.config.ServiceConfig.export(ServiceConfig.java:218)

可以復盤出問題發(fā)生的現(xiàn)場

dubbo服務進行export的時候調用了ExportedInterfaceManager.addInterface方法,而在addInterface方法中調用的JSON.toJSONString方法觸發(fā)了ProductServiceQueryServiceImpl.getAllProductService方法

在看了ExportedInterfaceManager.addInterface源碼之后,問題的起因浮出水面

ExportedInterfaceManager這個類是用來針對接口暴露http服務時收集元數(shù)據(jù)使用

public synchronized void addInterface(Class<?> interfaceCls, Object obj) {
    //如果是代理類獲取代理類對象
    obj = getObjectTarget(obj);//獲取原始對象
    //...
    InterfaceInfo interfaceInfo = new InterfaceInfo();
    interfaceInfo.setInterfaceName(interfaceName);
    interfaceInfo.setRef(obj);//致命之處
    //...
    logger.info(String.format("start to addInterface into interfaceMap,interfaceName[%s],interfaceInfo[%s]",interfaceName, JSON.toJSONString(interfaceInfo)));//致命之處
    // add interface info to map
    interfaceMap.put(interfaceName, interfaceInfo);
}

對于第一個問題,InterfaceInfo的ref指向ProductServiceQueryServiceImpl,在打印日志的時候,JSON.toJSONString觸發(fā)了ProductServiceQueryServiceImpl中的get方法

而對于第二個問題,obj = getObjectTarget(obj);這段代碼會獲取代理的原始對象,導致事務失效。

問題危害

拋開獲取原始對象這個邏輯不說,這個bug的致命之處在于,他會調用所暴露dubbo接口中所有get*()格式的方法

問題解決

解決方式很簡單,有以下兩種

  • 不要序列化ref(加fastjson注解或字段加transient)
  • 去掉打印日志邏輯

在反饋這個問題后,中間件團隊的改動如下

以上就是JSON.toJSONString使用異常分析的詳細內容,更多關于JSON.toJSONString異常的資料請關注腳本之家其它相關文章!

相關文章

  • java解析xml之jdom解析xml示例分享

    java解析xml之jdom解析xml示例分享

    JDOM是專門為Java打造的API,JDOM采用了Java中的Collection架構來封裝集合,是Java愛好者更加熟悉的模式,下面看使用示例
    2014-01-01
  • SpringBoot項目如何添加2FA雙因素身份認證

    SpringBoot項目如何添加2FA雙因素身份認證

    雙因素身份驗證2FA是一種安全系統(tǒng),要求用戶提供兩種不同的身份驗證方式才能訪問某個系統(tǒng)或服務,國內普遍做短信驗證碼這種的用的比較少,不過在國外的網站中使用雙因素身份驗證的還是很多的,這篇文章主要介紹了SpringBoot項目如何添加2FA雙因素身份認證,需要的朋友參考下
    2024-04-04
  • 詳解SpringBoot封裝使用JDBC

    詳解SpringBoot封裝使用JDBC

    這篇文章主要介紹了SpringBoot封裝JDBC使用教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Java 中的 BufferedReader 介紹_動力節(jié)點Java學院整理

    Java 中的 BufferedReader 介紹_動力節(jié)點Java學院整理

    BufferedReader 是緩沖字符輸入流。它繼承于Reader。接下來通過本文給大家介紹BufferedReader的相關知識,需要的朋友參考下吧
    2017-05-05
  • Java設計模式之橋模式(Bridge模式)介紹

    Java設計模式之橋模式(Bridge模式)介紹

    這篇文章主要介紹了Java設計模式之橋模式(Bridge模式)介紹,本文講解了為什么使用橋模式、如何實現(xiàn)橋模式、Bridge模式在EJB中的應用等內容,需要的朋友可以參考下
    2015-03-03
  • Java同步代碼塊和同步方法原理與應用案例詳解

    Java同步代碼塊和同步方法原理與應用案例詳解

    這篇文章主要介紹了Java同步代碼塊和同步方法原理與應用,結合具體案例形式分析了使用java同步代碼塊和同步方法實現(xiàn)買票功能的相關原理與操作技巧,需要的朋友可以參考下
    2019-10-10
  • 一文深入解析JDBC超時機制

    一文深入解析JDBC超時機制

    恰當?shù)腏DBC超時設置能夠有效地減少服務失效的時間,下面這篇文章主要給大家介紹了關于JDBC超時機制的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-10-10
  • 探討Java中的深淺拷貝問題

    探討Java中的深淺拷貝問題

    這個概念估計懂C++的人不會陌生,但是很多朋友并不了解,概括起來將淺拷貝就是指兩個對象公用一個值,一個的改變了另一個也會隨之改變,深拷貝則是兩個對象值相等,但是相互獨立互不影響。下面我們將關于java的淺拷貝和深拷貝做一個詳細講解
    2021-06-06
  • java maven項目如何讀取配置文件信息

    java maven項目如何讀取配置文件信息

    這篇文章主要介紹了java maven項目如何讀取配置文件信息,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Servlet開發(fā)JavaWeb工程示例詳解

    Servlet開發(fā)JavaWeb工程示例詳解

    這篇文章主要介紹了Servlet開發(fā)JavaWeb工程示例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07

最新評論