最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2021年08月23日 10:25:58   作者:shjhhc  
這篇文章主要介紹了springMVC在restful風格的性能優(yōu)化方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

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

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

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

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

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

測試

為了看到效果,我先進行了測試,工具是Apache-Jmeter

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

1、非restful接口

這里寫圖片描述

2、restful接口

這里寫圖片描述

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

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

匹配原理

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

最后處理邏輯在AbstractHandlerMethodMapping類的lookupHandlerMethod方法中進行。

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)進行匹配校驗。

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

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

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

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

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

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

綜上所述,當使用非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í)行這段復雜的匹配邏輯是不可取的。我們要做的就是找辦法繞開它。spring是一個符合開閉原則的框架。對擴展開放,對修改關(guān)閉。它提供了很多擴展性給我們。

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

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

我們剛好可以使用它。

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

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

由此便可以在子類中擴展它。

代碼:

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

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

 @Override
    protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
        return new RestfulRequestMappingHandlerMapping();
    }

2、繼承RequestMappingHandlerMapping類

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

@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,進行匹配查找
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的反向映射。

//映射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)化邏輯編寫完成??创a量很少,但想通過自己寫出來,需要對springMVC有相當了解,深入理解springMVC的可擴展點。

最終測試

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

這里寫圖片描述

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

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

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

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

原因:

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

解決方案:

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

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

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

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

相關(guān)文章

  • MyBatis一對一映射初識教程

    MyBatis一對一映射初識教程

    MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優(yōu)秀持久層框架。在我們生活中一對一的例子很多見,下面通過本文給大家?guī)砹薽ybatis一對一映射初識教程,感興趣的朋友一起看下吧
    2016-08-08
  • Java中MapStruct使用方法解析

    Java中MapStruct使用方法解析

    這篇文章主要介紹了Java中MapStruct使用方法解析,接受請求參數(shù)都會使用一個vo類,這個vo類里封裝了所有需要接受的參數(shù),然后對參數(shù)進行業(yè)務(wù)邏輯處理,處理完后會持久化處理,?使用MapStruct可以快速幫你解決轉(zhuǎn)換工作,需要的朋友可以參考下
    2023-10-10
  • kotlin之協(xié)程的理解與使用詳解

    kotlin之協(xié)程的理解與使用詳解

    這篇文章主要介紹了kotlin之協(xié)程的理解與使用詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • IDEA 搭建maven 安裝、下載、配置的圖文教程詳解

    IDEA 搭建maven 安裝、下載、配置的圖文教程詳解

    這篇文章主要介紹了IDEA 搭建maven 安裝、下載、配置,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Intellj Idea中的maven工程Java文件顏色不對,未被識別的解決

    Intellj Idea中的maven工程Java文件顏色不對,未被識別的解決

    這篇文章主要介紹了Intellj Idea中的maven工程Java文件顏色不對,未被識別的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Java中方法優(yōu)先調(diào)用可選參數(shù)還是固定參數(shù)

    Java中方法優(yōu)先調(diào)用可選參數(shù)還是固定參數(shù)

    這篇文章主要介紹了Java中方法優(yōu)先調(diào)用可選參數(shù)還是固定參數(shù),可選參數(shù)是?JDK?5?中新增的特性,也叫變長參數(shù)或可變參數(shù),固定參數(shù)的概念恰好與可選參數(shù)相反,固定參數(shù)也就是普通的參,下文更多詳細內(nèi)容需要的小伙伴可以參考一下
    2022-05-05
  • Java中5種異步實現(xiàn)的方式詳解

    Java中5種異步實現(xiàn)的方式詳解

    同步操作如果遇到一個耗時的方法,需要阻塞等待,那么我們有沒有辦法解決呢?讓它異步執(zhí)行,下面我會詳解異步及實現(xiàn),需要的可以參考一下
    2022-09-09
  • Spring?IOC?常用注解與使用實例詳解

    Spring?IOC?常用注解與使用實例詳解

    這篇文章主要介紹了Spring?IOC?常用注解與使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • mybatis?plus常用注解的具體使用

    mybatis?plus常用注解的具體使用

    本文主要介紹了mybatis?plus常用注解的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • 分享關(guān)于JAVA 中使用Preferences讀寫注冊表時要注意的地方

    分享關(guān)于JAVA 中使用Preferences讀寫注冊表時要注意的地方

    這篇文章介紹了關(guān)于JAVA 中使用Preferences讀寫注冊表時要注意的地方,有需要的朋友可以參考一下
    2013-08-08

最新評論

石首市| 封开县| 菏泽市| 巧家县| 安康市| 长葛市| 进贤县| 乐都县| 高唐县| 迭部县| 柳江县| 佛坪县| 满洲里市| 天台县| 广南县| 涞源县| 襄城县| 晋宁县| 玛沁县| 太保市| 静安区| 盘锦市| 阳春市| 柞水县| 鲁甸县| 汝南县| 延边| 肇源县| 柘荣县| 根河市| 教育| 文安县| 西贡区| 寿阳县| 大英县| 长葛市| 新竹县| 成武县| 民丰县| 洛南县| 拜泉县|