激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - springMVC在restful風(fēng)格的性能優(yōu)化方案

springMVC在restful風(fēng)格的性能優(yōu)化方案

2021-11-30 10:57shjhhc Java教程

這篇文章主要介紹了springMVC在restful風(fēng)格的性能優(yōu)化方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

springMVC在restful風(fēng)格的性能優(yōu)化

目前,restful的接口風(fēng)格很流行,使用springMVC來搭配restful也是相得益彰。如下,使用@PathVariable注解便可以獲取URL上的值。

?
1
2
3
4
@RequestMapping(value = "restful/{name}", method = RequestMethod.GET)
    public String restful(@PathVariable String name){
        return name;
    }

不過如果你認(rèn)真的研究過springMVC就會發(fā)現(xiàn),restful風(fēng)格的接口的性能會大大低于正常形式的springMVC接口。比如下面這種方式。

?
1
2
3
4
@RequestMapping(value = "norestful", method = RequestMethod.GET)
    public String norestful(@RequestParam String name){
        return name;
    }

測試

為了看到效果,我先進(jìn)行了測試,工具是Apache-Jmeter

測試參數(shù),并發(fā)量50,總量10000次。

1、非restful接口

springMVC在restful風(fēng)格的性能優(yōu)化方案

2、restful接口

springMVC在restful風(fēng)格的性能優(yōu)化方案

對比很明顯,非restful接口的性能是restful接口的1.5倍左右,而且restful接口隨著@Requestmapping接口數(shù)量的增多會越來越慢,而非restful接口不會。

不止如此,非restful接口的最大響應(yīng)時間是67ms,而restful接口的最大響應(yīng)時間達(dá)到了381ms,這在極端情況下很可能會造成請求超時。

匹配原理

先講一下springMVC的路徑匹配邏輯吧。springMVC的請求主要在DispatcherServlet中處理,而請求分發(fā)規(guī)則則在doDispatch()方法中完成。

最后處理邏輯在AbstractHandlerMethodMapping類的lookupHandlerMethod方法中進(jìn)行。

?
1
2
3
4
5
6
7
8
9
10
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<Match>();
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        if (matches.isEmpty()) {
            // No choice but to go through all mappings...
            addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }

這段代碼中匹配邏輯有三:

1、List directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);

這個方法是非常直觀的根據(jù)URL來獲取,springMVC會在初始化的時候建立URL和相應(yīng)RequestMappingInfo的映射。如果不是restful接口,這里就可以直接獲取到了。

2、如果1中已經(jīng)獲取到,則調(diào)用方法addMatchingMappings(directPathMatches, matches, request)進(jìn)行匹配校驗。

3、如果1中未獲取到匹配方法信息,則調(diào)用方法addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);進(jìn)行全局(all mappings)掃描匹配(this.mappingRegistry.getMappings().keySet())。且會把所有的RequestMappingInfo都遍歷完才會停止,也就是說項目中的@RequestMapping方法越多,這個匹配的效率就越低,性能越差。

在遍歷過程中,SpringMVC首先會根據(jù)@RequestMapping中的headers, params, produces, consumes, methods與實際的HttpServletRequest中的信息對比,剔除掉一些明顯不合格的RequestMapping。

如果以上信息都能夠匹配上,那么SpringMVC會對RequestMapping中的path進(jìn)行正則匹配,剔除不合格的。

接下來會對所有留下來的候選@RequestMapping進(jìn)行評分并排序。最后選擇分?jǐn)?shù)最高的那個作為結(jié)果。

評分的優(yōu)先級為:

path pattern > params > headers > consumes > produces > methods

綜上所述,當(dāng)使用非restful接口時就會直接獲取對應(yīng)的HandlerMethod來處理請求,但使用restful接口時,就會每次遍歷所有的方法來查找,性能差由此形成。

優(yōu)化方案

原理:

1、在每個@RequestMapping中添加接口對應(yīng)服務(wù)名的信息。

2、實現(xiàn)自己定義的HandlerMethod查詢邏輯,在HandlerMethod注冊時記錄與之對應(yīng)的服務(wù)名,在查詢時通過HTTP請求頭中的服務(wù)名查表獲得HandlerMethod。

實現(xiàn):

每次請求都執(zhí)行這段復(fù)雜的匹配邏輯是不可取的。我們要做的就是找辦法繞開它。spring是一個符合開閉原則的框架。對擴(kuò)展開放,對修改關(guān)閉。它提供了很多擴(kuò)展性給我們。

springmvc中,AbstractHandlerMethodMapping.MappingRegistry里提供了@Requestmapping中name屬性和HandlerMethod的映射如下

?
1
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();

我們剛好可以使用它。

另外,我們看到實現(xiàn)匹配邏輯的方法HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);其本身是個protected方法,

?
1
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception

由此便可以在子類中擴(kuò)展它。

代碼:

我使用基于java config的注解配置.

1、繼承WebMvcConfigurationSupport類,復(fù)寫createRequestMappingHandlerMapping方法返回自定義的RequestMappingHandlerMapping類。

?
1
2
3
4
@Override
   protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
       return new RestfulRequestMappingHandlerMapping();
   }

2、繼承RequestMappingHandlerMapping類

2.1重寫lookupHandlerMethod方法,完成自己的查找邏輯。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    //自己的查找邏輯,如果找不到,再執(zhí)行原有的邏輯,以免出現(xiàn)錯誤情況
        HandlerMethod handlerMethod = lookupHandlerMethodHere(lookupPath, request);
        if (handlerMethod == null)
            handlerMethod = super.lookupHandlerMethod(lookupPath, request);
        return handlerMethod;
    }
//自己的查找邏輯,根據(jù)從請求頭中獲取服務(wù)名servicename,進(jìn)行匹配查找
private HandlerMethod lookupHandlerMethodHere(String lookupPath, HttpServletRequest request) {
        String servicename = request.getHeader("servicename");
        if (!StringUtils.isEmpty(servicename)) {
            List<HandlerMethod> methodList = this.getHandlerMethodsForMappingName(servicename);
            if (methodList.size() > 0){
                HandlerMethod handlerMethod = methodList.get(0);
                RequestMappingInfo requestMappingInfo = mappingLookup.get(handlerMethod);
                handleMatch(requestMappingInfo, lookupPath, request);
                return handlerMethod;
            }
        }
        return null;
    }

2.2因為RESTful接口存在@PathVariable,我們還需要調(diào)用handleMatch方法來將HTTP請求的path解析成參數(shù)。然而這個方法需要的參數(shù)是RequestMappingInfo,并不是HandlerMethod,SpringMVC也沒有提供任何映射。

做法:重寫registerHandlerMethod方法,再初始化的時候構(gòu)建一個從HandlerMethod—>RequestMappingInfo的反向映射。

?
1
2
3
4
5
6
7
8
//映射map
private final Map<HandlerMethod, RequestMappingInfo> mappingLookup = new LinkedHashMap<HandlerMethod, RequestMappingInfo>();
@Override
    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
        HandlerMethod handlerMethod = createHandlerMethod(handler, method);
        mappingLookup.put(handlerMethod, mapping);
        super.registerHandlerMethod(handler, method, mapping);
    }

由此,springMVC優(yōu)化邏輯編寫完成。看代碼量很少,但想通過自己寫出來,需要對springMVC有相當(dāng)了解,深入理解springMVC的可擴(kuò)展點。

最終測試

看下優(yōu)化過后的restful接口

springMVC在restful風(fēng)格的性能優(yōu)化方案

吞吐量和非restful接口差不多,各項應(yīng)能都接近,達(dá)到預(yù)期效果。

spring restful使用中遇到的一個性能問題

在使用spring restful開發(fā)過程中遇到個棘手的問題,解決后來做個備注。希望其他遇到相同問題的朋友可以參考下。

客戶端訪問rest api速度過慢,每次請求超過1秒鐘

原因:

返回類型是強(qiáng)類型,SPRING將其序列化為json對象消耗時間過長。

解決方案:

返回類型改為String,改動很小,只需要將原來的強(qiáng)類型對象通過fastjson的JSON.toJSONString方法進(jìn)行轉(zhuǎn)換即可;

?
1
@RequestMapping加參數(shù)produces = { "application/json;charset=UTF-8" }

通過以上修改,原先1秒鐘左右的請求變?yōu)?0-50毫秒。雖然解決,但是否是spring本身問題還是配置問題,抑或代碼寫法問題,還未深究,暫時先趕項目進(jìn)度,項目完成后再回頭查找具體原因。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/shjhhc/article/details/53261168

延伸 · 閱讀

精彩推薦
  • Java教程xml與Java對象的轉(zhuǎn)換詳解

    xml與Java對象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發(fā)項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經(jīng)有好久沒有升過級了。升級完畢重啟之后,突然發(fā)現(xiàn)好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java實現(xiàn)搶紅包功能

    Java實現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發(fā)現(xiàn)了對于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
主站蜘蛛池模板: 成人在线视频精品 | 天使萌一区二区三区免费观看 | 日本娇小videos高潮 | 国产精品一区二区三区在线看 | 刘亦菲一区二区三区免费看 | 毛片免费视频网站 | 免费毛片播放 | 国产一区日韩精品 | 国内精品免费一区二区2001 | 亚洲一二区精品 | 免费午夜视频 | 欧美日韩一区二区综合 | 一级片久久免费 | 免费一级毛片在线播放不收费 | 毛片免费观看完整版 | 亚洲爱爱图 | 天天草天天爱 | 91香焦视频 | 国产一级小视频 | 日本a在线观看 | 久久国产精品二国产精品中国洋人 | www.射| 欧美性生交xxxxx免费观看 | 少妇一级淫片免费放正片 | 国产一区二区三区网站 | 黄色视频a级毛片 | 免费a级黄色毛片 | av不卡毛片 | 在线99热| 在线播放污 | 久草在线最新免费 | 成人在线视频黄色 | 午夜男人免费视频 | 精品一区二区三区在线观看视频 | 天天看成人免费毛片视频 | 日本aaa一级片 | 92看片淫黄大片一级 | 亚洲国产高清一区 | 日本精品久久久久 | 一区二区三区日韩电影 | 国产精品jk白丝蜜臀av软件 |