Liferay中的UrlRewriteFilter的研究

简介:

引入:

关于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目录下:

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行。

100448493.png

首先,第726行会去利用processRequest(HttpServletRequest,HttpServletResponse)来获取重写url.我们看它的实现,首先它会在第68行把它trim()下去掉首尾空白字符:

100938898.png

trim()完之后,这个url还是/tunnel-web:

101105952.png


然后,在84行将其用utf-8形式将其decode,因为我们都知道最早我们输入的url都被URLEncode过了。

101255709.png

decode完之后,这个originalUrl仍然是/tunnel-web:

101358524.png


然后第95到98行会从请求url中吧contextPath部分移除。

101517580.png

因为如下图所示,我们的contextPath为"",所以98行执行完之后originalUrl依然是/tunnel-web:

101735908.png


从102-107行会吧queryString加载originalUrl的后面:

101933750.png

因为我们没有查询字符串,所以不加任何东西。


然后第123行会获取所有的url重写规则并且保存在变量rules中,它会从urlrewrite.xml中获取所有规则配置信息:

102215278.png

因为最上面,我们在urlrewrite.xml中配置了6条规则,所以从调试信息看,这里rules数组变量有6个元素。

102410301.png


然后从131-141行就会依次遍历这些规则集然后调用规则来重写请求url了,需要注意的是,它是顺序的执行匹配然后重写的,也就是下一个规则会用上一个规则的输出作为输入:

102633672.png

而重写的过程在第135行 execute方法中:


重点:execute()方法的细节:

我们来看下我们的例子,因为我们定义了以下规则:

102732364.png

所以,当请求url /tunnel-web时候,当执行到上述第134行时候,它先从urlrewrite.xml中获得了当前规则(匹配上述定义):

103116166.png


然后第135行会调用rule.execute()方法来具体的执行重写:

103906745.png

它先在第74行通过executeBase()方法获取一个RuleExecutionOutput对象,具体不展开了,就是创建一个Matcher对象,如果匹配,就把<from>中的()中的匹配正则表达式的重写内容按照顺序1,2,3等替换为<to>中的重写参数$1,$2,$3等。最终通过调试信息我们可以看出,它计算出了最终的匹配目标:104033533.png

这里看出,它的replaceUrl 包含了要匹配到的目标,而ruleMatchedtrue表明通过检验,这个url重写规则匹配当前的url.


execute()方法最终会调用rewriteRequest()方法来具体的进行重写:

103731767.png

从这里可以看出,因为我们的to type字符串设置为"permanent-redirect",所以我们根据以下规则:

104543826.png

我们的toType被设为2.


所以会执行rewriteRequest的第99-103行,最终会吧rewrittenRequestpermanentRedirect设置为true.

104849610.png


然后到回到UrlRewriter的processRequest()方法中,因为我们已经从execute()方法中返回RewrittenUrl,它的target/api:

105655336.png

所以第139行会取出这个target,并且作为最后finalToUrl.

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>中的用括号括出来的正则表达式匹配的请求内容转为<to>中重写参数指定的模式。其次,它会去读取<to>中的type属性,并且根据type属性的取值来决定对于重写后的url 进行如何后处理。

(5)type属性有6种,分别是redirect,permanent-redirect,temporary-redirect,pre-include,post-include,forward,我们可以根据不同需要为其进行定制。





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1297612,如需转载请自行联系原作者
目录
相关文章
|
安全 Go
第十一章 CSP 架构 - Web Application Settings
第十一章 CSP 架构 - Web Application Settings
第十一章 CSP 架构 - Web Application Settings
|
开发框架 安全 .NET
【牛刀小试】——详解VS2010WEB项目发布
【牛刀小试】——详解VS2010WEB项目发布
153 0
【牛刀小试】——详解VS2010WEB项目发布
|
JavaScript 前端开发 Java
|
JavaScript Java Android开发
|
应用服务中间件 容器 数据格式