Liferay中的UrlRewriteFilter的研究

來源:互聯網
上載者:User

引入:

關於UrlRewriteFilter大家也許都不陌生,尤其那些做過SEO(搜尋引擎最佳化)的同學們都知道,它會吧一個url重寫為另外一URL,為什麼要這麼做呢?因為搜尋引擎看待動態URL非常不舒服所謂動態URL就是?關聯queryParameter,&關聯參數對這種url,比如http://1.2.3.4:3333/badurltest?a=1&b=2&c=3這種url.而我們重寫後會把它改為靜態url,比如http://1.2.3.4:3333/badurltest_1_2_3.html,這種情況下搜尋引擎看的比較舒服。


那麼我們看下Liferay中如何做到url重寫的,當然了,肯定還是按照慣例一樣,它會用filter來完成這個工作。



調試分析:

熟悉urlrewrite的人都知道,它一般會採用一個urlrewrite.xml來完成重寫的規則配置,我們liferay也不例外。它在$LIFERAY_TOMCAT_HOME/webapps/ROOT/WEB-INF目錄下:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115424125-0.png" title="2013-09-16_095244.png" alt="095431711.png" />

我們選取一個最簡單的,比如http://172.29.175.236:8080/tunnel-web ,看它是否能重寫為http://172.29.175.236:8080/api


很顯然,這個URLRewriteFilter是被InvokerFilterChain調用的。我們進入doFilter()方法:因為我們的拿到的sourcecode中的URLRewriteFilter.java無法和jar包中的UrlRewriterFilter.class相匹配,所以我們只能用jd-gui反編譯來對照著看。


跳去不重要的行,我們目光停在了第726到728行。

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/111542M49-1.png" title="2.png" alt="100448493.png" />

首先,第726行會去利用processRequest(HttpServletRequest,HttpServletResponse)來擷取重寫url.我們看它的實現,首先它會在第68行把它trim()下去掉首尾空白字元:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/111542O60-2.png" title="3.png" alt="100938898.png" />

trim()完之後,這個url還是/tunnel-web:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115423A0-3.png" title="4.png" alt="101105952.png" />


然後,在84行將其用utf-8形式將其decode,因為我們都知道最早我們輸入的url都被URLEncode過了。

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115422416-4.png" title="5.png" alt="101255709.png" />

decode完之後,這個originalUrl仍然是/tunnel-web:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115424W5-5.png" title="6.png" alt="101358524.png" />


然後第95到98行會從請求url中吧contextPath部分移除。

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/111542D48-6.png" title="7.png" alt="101517580.png" />

因為如所示,我們的contextPath為"",所以98行執行完之後originalUrl依然是/tunnel-web:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/111542E35-7.png" title="8.png" alt="101735908.png" />


從102-107行會吧queryString載入originalUrl的後面:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115425296-8.png" title="9.png" alt="101933750.png" />

因為我們沒有查詢字串,所以不加任何東西。


然後第123行會擷取所有的url重寫規則並且儲存在變數rules中,它會從urlrewrite.xml中擷取所有規則配置資訊:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115421Q3-9.png" title="10.png" alt="102215278.png" />

因為最上面,我們在urlrewrite.xml中配置了6條規則,所以從調試資訊看,這裡rules陣列變數有6個元素。

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115422622-10.png" title="11.png" alt="102410301.png" />


然後從131-141行就會依次遍曆這些規則集然後調用規則來重寫請求url了,需要注意的是,它是順序的執行匹配然後重寫的,也就是下一個規則會用上一個規則的輸出作為輸入:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115421543-11.png" title="12.png" alt="102633672.png" />

而重寫的過程在第135行 execute方法中:


重點:execute()方法的細節:

我們來看下我們的例子,因為我們定義了以下規則:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115421L9-12.png" title="13.png" alt="102732364.png" />

所以,當請求url /tunnel-web時候,當執行到上述第134行時候,它先從urlrewrite.xml中獲得了當前規則匹配上述定義):

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115422625-13.png" title="14.png" alt="103116166.png" />


然後第135行會調用rule.execute()方法來具體的執行重寫:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115425196-14.png" title="16.png" alt="103906745.png" />

它先在第74行通過executeBase()方法擷取一個RuleExecutionOutput對象,具體不展開了,就是建立一個Matcher對象,如果匹配,就把<from>中的()中的匹配Regex的重寫內容按照順序1,2,3等替換為<to>中的重寫參數$1,$2,$3等。最終通過調試資訊我們可以看出,它計算出了最終的匹配目標:650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115421247-15.png" title="17.png" alt="104033533.png" />

這裡看出,它的replaceUrl 包含了要匹配到的目標,而ruleMatchedtrue表明通過檢驗,這個url重寫規則匹配當前的url.


execute()方法最終會調用rewriteRequest()方法來具體的進行重寫:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/111542E29-16.png" title="15.png" alt="103731767.png" />

從這裡可以看出,因為我們的to type字串設定為"permanent-redirect",所以我們根據以下規則:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/111542CJ-17.png" title="18.png" alt="104543826.png" />

我們的toType被設為2.


所以會執行rewriteRequest的第99-103行,最終會吧rewrittenRequestpermanentRedirect設定為true.

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/11154252c-18.png" title="19.png" alt="104849610.png" />


然後到回到UrlRewriter的processRequest()方法中,因為我們已經從execute()方法中返回RewrittenUrl,它的target/api:

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115426333-19.png" title="20.png" alt="105655336.png" />

所以第139行會取出這個target,並且作為最後finalToUrl.

650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1115423613-20.png" title="21.png" alt="105735395.png" />



總結:

雖然這片調試沒有什麼技術難度,不過我們還是可以總結出一些有價值的結論:

(1)Liferay的Url重寫是通過UrlRewriteFilter來完成的,並且這個UrlRewriteFilter會被InvokerFilterChain所調用。

(2)重寫規則會定義在$LIFERAY_TOMCAT_HOME/webapps/ROOT/WEB-INF/urlrewrite.xml檔案中。

(3)執行重寫的過程如下:首先它會去吧請求url trim()下,再將其utf-8解碼成原始url,然後會去除contextPath部分並且後面加上查詢字串部分,得到重寫前的輸入url。然後,它會吧urlrewrite.xml中的所有重寫規則都讀取並且存放在Rule數組中,遍曆數組對於重寫前url一條一條應用程式規則,並且這是遞迴的,就是一條規則的輸出就是下一條規則的輸入。直到吧所有的規則全部應用完,才得到最終重寫後的輸出url.

(4)在應用重寫規則時候,它又分為2部分,首先它會在基類(RuleBase)中應用一般規則替換,就是把所有<from>中的用括弧括出來的Regex匹配的請求內容轉為<to>中重寫參數指定的模式。其次,它會去讀取<to>中的type屬性,並且根據type屬性的取值來決定對於重寫後的url 進行如何後處理。

(5)type屬性有6種,分別是redirect,permanent-redirect,temporary-redirect,pre-include,post-include,forward,我們可以根據不同需要為其進行定製。

本文出自 “平行線的凝聚” 部落格,請務必保留此出處http://supercharles888.blog.51cto.com/609344/1297612

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.