• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

      基于SpringBoot結(jié)果集序列化過濾插件的研究與實現(xiàn)

      2020-10-20 03:23:49王春波葛雷文雪巍
      商情 2020年41期
      關(guān)鍵詞:堆棧序列化

      王春波 葛雷 文雪巍

      【摘要】SpringBoot是由Pivotal團(tuán)隊在2013年開始研發(fā)、2014年4月發(fā)布第一個版本的全新開源的輕量級框架。它基于Spring4.0設(shè)計,不僅繼承了Spring框架原有的優(yōu)秀特性,而且還通過簡化配置來進(jìn)一步簡化了Spring應(yīng)用的整個搭建和開發(fā)過程。該框架使用內(nèi)置的注解與Jackson插件可方便的將結(jié)果集序化成適合于移動互聯(lián)網(wǎng)廠商作為業(yè)務(wù)接口的JSON格式字符串。由于框架的高度集成使得結(jié)果集序列化成JSON字符串時過于規(guī)則化,不能適用于較為復(fù)雜的業(yè)務(wù)場景,且對于復(fù)雜的結(jié)果集還會出現(xiàn)堆棧溢出錯誤,筆者分析了SpringBoot消息序列化過程,結(jié)合業(yè)務(wù)場景,給出了如何靈活定義結(jié)果集序列化規(guī)則,如何避免堆棧溢出錯誤的設(shè)計與實現(xiàn)方法,從而為使用SpringBoot框架作為開發(fā)技術(shù)棧的項目組提供了借鑒與參考。

      【關(guān)鍵詞】SpringBoot? Jackson? 堆棧? JSON? 序列化

      一、引言

      Spring Boot是由Pivotal團(tuán)隊提供的全新框架,其設(shè)計目的是用來簡化新Spring應(yīng)用的初始搭建以及開發(fā)過程。該框架使用了特定的方式來進(jìn)行配置,從而使開發(fā)人員不再需要定義樣板化的配置。通過這種方式,Spring Boot致力于在蓬勃發(fā)展的快速應(yīng)用開發(fā)領(lǐng)域成為領(lǐng)導(dǎo)者。

      SpringBoot框架中有兩個非常重要的策略:開箱即用和約定優(yōu)于配置。開箱即用,是指在開發(fā)過程中,通過在MAVEN項目的pom文件中添加相關(guān)依賴包,然后使用對應(yīng)注解來代替繁瑣的XML配置文件以管理對象的生命周期。這個特點使得開發(fā)人員擺脫了復(fù)雜的配置工作以及依賴的管理工作,更加專注于業(yè)務(wù)邏輯。約定優(yōu)于配置,是一種由SpringBoot本身來配置目標(biāo)結(jié)構(gòu),由開發(fā)者在結(jié)構(gòu)中添加信息的軟件設(shè)計范式。這一策略減少了開發(fā)人員需要做出決定的數(shù)量,同時減少了大量的XML配置,并且可以將代碼編譯、測試和打包等工作自動化,但也降低了部分靈活性,增加了缺陷定位的復(fù)雜性。

      對于復(fù)雜的項目需求,SpringBoot缺少靈活性的結(jié)果集轉(zhuǎn)換方式,不但不能降低開發(fā)人員勞動強(qiáng)度和復(fù)雜度,相反極大的增加了開發(fā)人員的工作量以及出現(xiàn)去缺陷的可能。因此,需要找到一個確實有效方法允許開發(fā)人員靈活配置結(jié)果集序列化規(guī)則,但同時又不能破壞或改變SpringBoot框架原有的優(yōu)勢。

      二、SpringBoot結(jié)果集序列化的現(xiàn)狀與問題

      SpringBoot默認(rèn)使用Jackson插件進(jìn)行結(jié)果集序列化。SpringBoot允許開發(fā)者使用其他插件例如Fastjson替換默認(rèn)的Jackson進(jìn)行結(jié)果集序列化,但無論使用哪種插件都面臨著序列化規(guī)則僵化、不靈活的弊端。試想當(dāng)相同的視圖對象應(yīng)用于不同的請求接口時,就會出現(xiàn)需要的請求字段不一樣場景,例如以下部門定義實體:

      public class SysDepart {

      private String departAddr; //部門地址

      private String departPhone; //部門電話

      private Integer departLevel; //部門級別

      private String departName; //部門名稱

      private String departExplain; //部門說明

      private String departType; //部門類型

      private SysSchool school; //歸屬學(xué)校

      private SysDepart parentDepart ; //父級部

      private List staff; //歸屬該部門的員工列表

      }

      針對獲取部門基本信息的接口,僅需要返回departAddr、departLevel、departName、departExplain、departType這個五個屬性字段即可;針對獲取部門員工列表的接口,僅需返回List staff 這個屬性字段即可;

      對于這類問題通常有以下4中解決辦法:

      (1)返回全部屬性字段:即由接口發(fā)起方進(jìn)行二次判斷,這種解決辦法不僅增加了開發(fā)人員的工作量,也給系統(tǒng)帶來了額外開銷。特別的,如果視圖對象存在雙向關(guān)聯(lián)關(guān)系,即SysDepart擁有屬性字段SysSchool school,同時SysSchool擁有屬性字段List depart;兩個實體構(gòu)成雙向一對多關(guān)系時,用Jackson或Fastjson等插件進(jìn)行結(jié)果序列化時均會出現(xiàn)堆棧溢出錯誤。

      (2)結(jié)果集二次處理:適當(dāng)增加注解,對結(jié)果集進(jìn)行二次處理。該方法雖能夠避免開發(fā)人員進(jìn)行多余的判斷,但卻不能避免首次結(jié)果集序列化JSON時發(fā)起的不需要的關(guān)聯(lián)查詢,以及避免序列化兩個構(gòu)成雙向一對多關(guān)系實體時出現(xiàn)的堆棧溢出錯誤。

      (3)Jackson提供@JsonFilter 注解實現(xiàn)結(jié)果集的動態(tài)過濾,但該注解使用麻煩,需要一個對象寫多個子類以區(qū)分不同的結(jié)果集,對于更復(fù)雜關(guān)聯(lián)查詢則顯得捉襟見肘。

      (4)無論是Jackson還是FastJson都提供了簡單過濾器,但這類過濾器僅能進(jìn)行全局配置,無法做到個性化輸出。

      綜上所述,無論是SpringBoot官方還是插件提供商均未曾為該類問題提供方便有效的解決辦法。筆者充分分析SpringBoot結(jié)果集序列化過程,通過擴(kuò)展接口、自定義解析規(guī)則、增加必要注解,利用AOP編程思想編碼實現(xiàn)了解決該類問題的插件,插件命名為Power-filter。Power-filter可以根據(jù)不同的業(yè)務(wù)場景配置返回不同的結(jié)果集,不僅能夠有效避免雙向關(guān)聯(lián)實體bean因循環(huán)查詢導(dǎo)致的堆棧溢出問題,也能減少非必要查詢,降低開發(fā)人員的編碼復(fù)雜度的同時也提高系統(tǒng)的查詢效率。

      三、Power-filter的設(shè)計與實現(xiàn)

      (一)SpringBoot 消息序列化原理

      SpringBoot使用消息轉(zhuǎn)換器對結(jié)果集進(jìn)行序列化,原理圖如圖1:

      從圖2可知,客戶端發(fā)送消息時,消息轉(zhuǎn)換器的作用是將對象序列化為某一格式報文,然后將報文發(fā)送另一端;接收消息時,消息轉(zhuǎn)換器作用是將某一格式報文轉(zhuǎn)換為對象。

      SpringBoot框架內(nèi)置了很多HTTP消息轉(zhuǎn)換器,不同消息類型轉(zhuǎn)換器處理不同Content-type類型數(shù)據(jù)。如MappingJackson2HttpMessageConverter處理請求類型為application/json類型數(shù)據(jù), StringHttpMessageConverter 處理類型為為 text/

      html類型數(shù)據(jù)等。在框架內(nèi)部會根據(jù)不同請求類型值選擇不同類型轉(zhuǎn)換器進(jìn)行消息轉(zhuǎn)換。目前,結(jié)果集的序列化過程就是通過默認(rèn)名為MappingJackson2HttpMessageConverter的轉(zhuǎn)換器來實現(xiàn)的。

      SpringBoot框架提供了HTTP消息轉(zhuǎn)換器的處理接口,允許開發(fā)者自定義消息序列化規(guī)則,因此可通過實現(xiàn)消息轉(zhuǎn)換器處理接口,用于替換原有處理application/json類型數(shù)據(jù)的轉(zhuǎn)換器來達(dá)到動態(tài)過濾屬性字段的需求。

      (二)Power-filter設(shè)計思路

      Power-filter的設(shè)計目的是為了在原有的框架上擴(kuò)展功能,適應(yīng)多變的接口需求。通過深入分析 SpringBoot 消息序列化原理,結(jié)合需求,筆者得出如圖2的設(shè)計思路。

      圖2中標(biāo)識①②③的區(qū)域是Power-filter插件實現(xiàn)的關(guān)鍵點:①允許開發(fā)者根據(jù)不同業(yè)務(wù)接口需求靈活設(shè)置序列化規(guī)則。②請求發(fā)起時,框架能夠獲取到針對該請求設(shè)置的過濾規(guī)則,并緩存它。③SpringBoot調(diào)用自定義的消息轉(zhuǎn)換器,獲取相應(yīng)規(guī)則,解析并應(yīng)用規(guī)則進(jìn)行消息序列化。

      (三)Power-filter實現(xiàn)方法

      針對圖2的設(shè)計思路中提到的三個關(guān)鍵點,實現(xiàn)方式如下:

      (1)對于①,筆者使用注解的方式進(jìn)行實現(xiàn)。Java 注解又稱 Java 標(biāo)注,它允許Java 語言中的類、方法、變量、參數(shù)和包等都可以被標(biāo)注。Power-filter新定義的注解如下:

      注解1:PowerJsonFilter

      @Retention(RUNTIME)

      @Target(value = {ElementType.METHOD})

      @Repeatable(value=PowerJsonFilters.class)

      public @interface PowerJsonFilter {

      Class<?> clazz();

      String[] include() default {};// include為對象需要包含的字段

      }

      注解2:PowerJsonFilters

      @Retention(RUNTIME)

      @Target({METHOD })

      public @interface PowerJsonFilters {

      PowerJsonFilter[] value();

      }

      從代碼中可以看出,兩個注解只能使用在方法上,注解2是注解1的數(shù)組形態(tài),可支持多規(guī)則設(shè)置。注解1接收兩個參數(shù):

      clazz:用于指示哪些實體bean需要消息序列化。如 clazz = SysDepart.class

      include:為字符串?dāng)?shù)組類型,用于指示需要消息序列化的實體bean中哪些屬性可以被序列化,它的格式如下:include = {"字段1","字段2","字段m","字段x:{字段x-1, 字段x-2:{ 字段x-2-1,[字段y:{…}]}}","字段n"}。舉例說明該格式的含義,對于注解:@PowerJsonFilters({@PowerJsonFilter(clazz = SysDepart.class,include= {"departId","departName" ,"parentDepart:{departName,school:

      {schoolName}}"}))。它的含義是:對于SysDepart實體bean,需要對其屬性"departId","departName","parentDepart"進(jìn)行序列化,特別的對于parentDepart屬性,其所屬類型不是簡單字符串、整形等常用數(shù)據(jù)類型,而是用戶自定義的實體,parentDepart:{departName,school:{schoolName}}意味著僅需要序列化parentDepart所屬實體的"departName","school"屬性。對于school屬性也做同樣的解析。該規(guī)則支持多重嵌套,只要開發(fā)人員設(shè)置合理,即可避免實體bean的雙向關(guān)聯(lián)查詢導(dǎo)致的堆棧溢出錯誤。

      (2)對于②,使用AOP編程思想,定義新的切入點,實現(xiàn)流程圖如圖3:

      (3)對于③,需要遵守SpringBoot框架的消息轉(zhuǎn)換器的接口規(guī)范進(jìn)行實現(xiàn),實現(xiàn)流程如圖4:

      四、Power-filter應(yīng)用與對比測試

      (一)Power-filter安裝與應(yīng)用

      Power-filter的設(shè)計初衷是解決SpringBoot對結(jié)果集進(jìn)行序列化時遇到諸多不便問題,因此Power-filter僅是SpringBoot的有益補(bǔ)充,它的安裝使用依賴于SpringBoot框架。Power-filter的安裝使用步驟為:

      (1)在SpringBoot啟動方法上增加注解掃描范圍,例如:@SpringBootApplication(scanBasePackages = {"xxx.xxx.xxx","com.hanb.filterJson"})

      (2)刪除原有消息轉(zhuǎn)換器,增加自定義的消息轉(zhuǎn)換器,代碼如下:

      public void configureMessageConverters(List> converters) {

      for (int i = converters.size() - 1; i >= 0; i--) {

      //找到并刪除默認(rèn)的消息轉(zhuǎn)換器

      }

      //聲明自定義消息轉(zhuǎn)換器并加入消息轉(zhuǎn)換器轉(zhuǎn)換鏈

      PowerHttpMessageConverter myConverter=new PowerHttpMessageConverter();

      converters.add(myConverter);

      }

      (3)在需要定義序列化規(guī)則的方法上增加注解,代碼示例如下:

      @RestController

      public class XxAction {

      @PowerJsonFilters({@PowerJsonFilter(clazz = SysDepart.class,include =? {"departId","school","parentDepart:{departName,school:{schoolName}}"}),

      @PowerJsonFilter(clazz = School.class,include = {"schoolAddr"})})

      public Object queryDepart(參數(shù)列表)? throws Exception{

      //業(yè)務(wù)邏輯代碼

      }? }

      通過(1)、(2)的安裝,(3)的應(yīng)用,程序運行后即可得出規(guī)則設(shè)定的結(jié)果,如下示例:

      [{"departId":1,"school":{"schoolAddr":"學(xué)院路"}},{"departId":2,"parentDepart":{"departName":"1級部門","school":{"schoolName":"財經(jīng)"}},"school":{"schoolName":"財經(jīng)"}}]

      (二)SpringBoot使用Power-filter插件序列化效率前后對比

      Power-filter能夠通過設(shè)置過濾規(guī)則靈活對結(jié)果集進(jìn)行過濾,為了對比應(yīng)用插件前后的效率,筆者在同一軟硬件環(huán)境下分別做了單表查詢結(jié)果集序列化,多表關(guān)聯(lián)查詢結(jié)果集序列化對比測試。

      (1)單表查詢100條記錄序列化對比如圖5:

      (2)多表關(guān)聯(lián)查詢100條記錄序列化對比如圖6。

      通過對比測試可發(fā)現(xiàn),對于單表查詢,兩者對查詢結(jié)果的序列化耗時相差并不大,對于多表關(guān)聯(lián)查詢,框架由于應(yīng)用了過濾規(guī)則避免了無用屬性的關(guān)聯(lián)查詢與序列化,其效率大大提高。

      五、總結(jié)

      Power-filter是依賴于SpringBoot框架的插件,該插件使用AOP編程思想進(jìn)行編寫,主要做了以下3點工作:

      (1)新增注解,用于對查詢結(jié)果集序列化規(guī)則進(jìn)行配置。

      (2)新增過濾規(guī)則,使用堆數(shù)據(jù)結(jié)構(gòu)完成對實體bean的多層嵌套比對。

      (3)實現(xiàn)自定義的消息轉(zhuǎn)換器,替換SpringBoot原生插件,完成結(jié)果集的序列化。

      通過對比測試發(fā)現(xiàn),使用了Power-filter插件的SpringBoot有以下4點優(yōu)勢:

      (1)配置規(guī)則簡單易懂,學(xué)習(xí)成本極低。

      (2)對結(jié)果集序列化按規(guī)則進(jìn)行配置,使得業(yè)務(wù)接口更加靈活,降低開發(fā)者的大量重復(fù)性工作。

      (3)通過規(guī)則配置,可有效避免無用屬性字段的關(guān)聯(lián)查詢,節(jié)約了系統(tǒng)開銷。

      (4)通過規(guī)則配置,可有效避免雙向關(guān)聯(lián)實體bean引起的循環(huán)查詢,從而導(dǎo)致的堆棧溢出錯誤。

      Power-filter作為SpringBoot的非原生插件,雖然有著自身的優(yōu)點,但也存在著不足:

      (1)需要做額外配置,插件方可生效。

      (2)過濾規(guī)則暫不支持通配符配置,規(guī)則書寫略顯麻煩。

      (3)規(guī)則配置方式單一,目前僅支持包含設(shè)置,不支持排除設(shè)置。

      對于不足中的(2)和(3),筆者將繼續(xù)完善該插件,爭取早日彌補(bǔ)其不足。

      總之,Power-filter作為SpringBoot的有益補(bǔ)充,雖然有些許不足,但仍能夠為使用SpringBoot框架作為開發(fā)技術(shù)棧的項目組提供借鑒與參考,為其快速完成接口開發(fā)提供有效的解決方案。

      參考文獻(xiàn):

      [1]小馬哥. Spring Boot編程思想(核心篇)[M].北京:電子工業(yè)出版社,2019:155-187.

      [2][美] Bruce Eckel.Think In Java)[M].北京:機(jī)械工業(yè)出版社,2007:162-199.

      [3]王曉東,計算機(jī)算法設(shè)計與分析(第5版))[M],北京:電子工業(yè)出版社,2018:202-351.

      作者簡介: 王春波(1978-),男,漢族,黑龍江海倫市人,碩士,信息系統(tǒng)項目高級管理師,研究方向:軟件工程、大數(shù)據(jù)理論、神經(jīng)網(wǎng)路算法;葛雷(1973-),男,漢族,黑龍江哈爾濱人,碩士,教授,研究方向:軟件工程、教育理論;文雪巍(1979-),女,漢族,黑龍江哈爾濱人,碩士,教授,主研究方向:軟件工程、人工智能。

      猜你喜歡
      堆棧序列化
      如何建構(gòu)序列化閱讀教學(xué)
      甘肅教育(2020年14期)2020-09-11 07:58:36
      嵌入式軟件堆棧溢出的動態(tài)檢測方案設(shè)計*
      基于堆棧自編碼降維的武器裝備體系效能預(yù)測
      Java 反序列化漏洞研究
      作文訓(xùn)練微格化、序列化初探
      語文知識(2015年12期)2015-02-28 22:02:15
      Java序列化技術(shù)的探討
      一種用于分析MCS-51目標(biāo)碼堆棧深度的方法
      堆棧技術(shù)及其在程序設(shè)計中的靈活運用
      兴隆县| 青川县| 汉源县| 苏尼特右旗| 潮州市| 陆良县| 阿克陶县| 长岛县| 道孚县| 定兴县| 习水县| 秦皇岛市| 仁寿县| 江城| 东光县| 壤塘县| 莎车县| 莒南县| 四子王旗| 威宁| 新巴尔虎左旗| 轮台县| 什邡市| 泰宁县| 乐东| 壤塘县| 奈曼旗| 新竹县| 福海县| 辽宁省| 鞍山市| 准格尔旗| 庐江县| 波密县| 德钦县| 昭通市| 壤塘县| 威宁| 安阳市| 沈丘县| 咸丰县|