这几天因为要做网站中的博客功能,需要对博客的地址进行处理,用到了urlrewrite,逸风在此也给大家简单介绍一下
urlrewrite顾名思义,就是对URL进行重写,用户得到的全部都是经过处理后的URL地址,这样做我觉得好处有三:
一:提高安全性,可以有效的避免一些参数名、ID等完全暴露在用户面前,如果用户随便乱输的话,不符合规则的话直接会返回个404或错误页面,这比直接返回500或一大堆服务器错误信息要好的多
二:美化URL,去除了那些比如*.do之类的后缀名、长长的参数串等,可以自己组织精简更能反映访问模块内容的URL
三:更有利于搜索引擎的收入,通过对URL的一些优化,可以使搜索引擎更好的识别与收录网站的信息
首先我们在web.xml中加入如下配置
<!-- url地址重写 -->
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/blog/*</url-pattern>
<!--
可以省略
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
-->
</filter-mapping>
这里我是要做用户博客的功能,用户博客的地址格式为:http://www.xxx.com/blog/+用户自定义的个性地址,而我实际要做的是通过用户的个性地址来查询用户博客的相关信息后转到用户的博客主页,实际要调用的地址为http://www.xxx.com/cblog.do?action=forwardIndex&hostUrl=用户自定义的地址,为了给用户好的体验所有我们需要用到urlrewrite来对地址栏的:http://www.xxx.com/blog/+用户自定义的个性地址 进行转换,已达到请求真实地址的目的。
下面我们需要在WEB-INF下建立一个xml文件来配置urlrewrite的规则,建立的xml的文件名建议为:urlrewrite.xml,全部小写,因为urlrewrite.xml实现时就全部是小写,如果定义的是别的名字的话,需要在web.xml中进行加载,不然不会自动加载
我定义的xml的文件的内容如下
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"
"http://tuckey.org/res/dtds/urlrewrite2.6.dtd">
<urlrewrite>
<rule>
<from>^/blog/(\w+)</from>
<to type="forward">/cblog.do?action=forwardIndex&hostUrl=$1</to>
</rule>
</urlrewrite>
启动项目,如果我在地址栏输入http://localhost:8080/test/blog/czykeith
那么我实际请求的地址是:http://localhost:880/test/cblog.do?action=forwardIndex&hosturl=czykeith
rule结点中form的规则默认使用的是正则表达式来匹配的,当用户访问服务器时的URL会与该配置相比较,如果符合规则就会按照下面to结点中的配置对其进行跳转,其默认是forward跳转,还可以是type=redirect ,当然这两者是有区别的
forward:默认. 请求匹配这个<rule />的所有<condition />,并且URL使用内部跳转到”to”指定的地址(注意, 这里forward 到的URL 必须和UrlRewriteFilter 位于同一个容器中)。状态码302。临时重定向。
redirect :用Response.Redirect实现,请求匹配所有<condition/>和这个<rule />的<from />, 通知客户端跳转到<to/>指定地址,状态码应该是302。
permanent-redirect: 永久重定向。状态码301。相当于做了以下事情
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);.
response.setHeader(“Location”, [<to />指定的值]);
passthrough: 和forward 相同,具体区别我也不清楚。
temporary-redirect:临时重定向。状态码302。 相当于做了以下事情
response.setStatus(HttpServletResponse. SC_MOVED_TEMPORARILY);
response.setHeader(“Location”, [<to />指定的值]);
使用urlrewrite时需要注意
1.如果要用&符号,需要用&代替
2.简单起见, 给<from />的配置前面和后面分别加上^, $, 这两个是正则表达式中的强制开始和结尾标志;
3. 如果使用<outbound-rule>要记得代码中的url都是编码过的;
4. contex 是非常重要的, 如果有一个应用的context 是”/myapp”,并且你的请求是”/myapp/somefolder/somepage.jsp”, 容器交给UrlRewriteFilter 的url会是”/somefolder/somepage.jsp”, 这可能难以理解,但是在你的<rule>和<condition>中不要包含context path, 它是容器负责处理的.
5. 正则表达式非常复杂灵活, 请阅读java.util.regex.Pattern中的java正则介绍。如果觉得正则难以理解,可以使用通配符方式。
6. 应用通配符,通配符匹配引擎可以替代正则表达式, 在<condition>和<rule>中设置match-type是wildcard用以开启支持通配符.(或者设置default-match-type)
例如:
/big/url/*匹配/big/url/abc.html但是不匹配/big/url/abc/dir/或/big/url/abc/
/big/url/**匹配/big/url/abc.html,/big/url/abc/dir/和/big/url/abc/
也可以和正则的替换一样, 每个*代表一个参数,在<set>和<to>中用$N的方式使用
7. <to />可以是null, 意义为: 如果匹配请求不再继续, 相当于没有调用chain.doFilter
补充:大家可能看到我上面的配置中有个$1 ,还不明白是什么意思,我说明一下,$1为<from>^/blog/(\w+)</from>中(\w+)所匹配的内容,如果有多个根据顺序$2...$6获取就可以了,需要注意的是在from中需要用()把要匹配的内容括起来才能获取,不然java会抛出异常
urlrewrite顾名思义,就是对URL进行重写,用户得到的全部都是经过处理后的URL地址,这样做我觉得好处有三:
一:提高安全性,可以有效的避免一些参数名、ID等完全暴露在用户面前,如果用户随便乱输的话,不符合规则的话直接会返回个404或错误页面,这比直接返回500或一大堆服务器错误信息要好的多
二:美化URL,去除了那些比如*.do之类的后缀名、长长的参数串等,可以自己组织精简更能反映访问模块内容的URL
三:更有利于搜索引擎的收入,通过对URL的一些优化,可以使搜索引擎更好的识别与收录网站的信息
首先我们在web.xml中加入如下配置
<!-- url地址重写 -->
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/blog/*</url-pattern>
<!--
可以省略
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
-->
</filter-mapping>
这里我是要做用户博客的功能,用户博客的地址格式为:http://www.xxx.com/blog/+用户自定义的个性地址,而我实际要做的是通过用户的个性地址来查询用户博客的相关信息后转到用户的博客主页,实际要调用的地址为http://www.xxx.com/cblog.do?action=forwardIndex&hostUrl=用户自定义的地址,为了给用户好的体验所有我们需要用到urlrewrite来对地址栏的:http://www.xxx.com/blog/+用户自定义的个性地址 进行转换,已达到请求真实地址的目的。
下面我们需要在WEB-INF下建立一个xml文件来配置urlrewrite的规则,建立的xml的文件名建议为:urlrewrite.xml,全部小写,因为urlrewrite.xml实现时就全部是小写,如果定义的是别的名字的话,需要在web.xml中进行加载,不然不会自动加载
我定义的xml的文件的内容如下
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"
"http://tuckey.org/res/dtds/urlrewrite2.6.dtd">
<urlrewrite>
<rule>
<from>^/blog/(\w+)</from>
<to type="forward">/cblog.do?action=forwardIndex&hostUrl=$1</to>
</rule>
</urlrewrite>
启动项目,如果我在地址栏输入http://localhost:8080/test/blog/czykeith
那么我实际请求的地址是:http://localhost:880/test/cblog.do?action=forwardIndex&hosturl=czykeith
rule结点中form的规则默认使用的是正则表达式来匹配的,当用户访问服务器时的URL会与该配置相比较,如果符合规则就会按照下面to结点中的配置对其进行跳转,其默认是forward跳转,还可以是type=redirect ,当然这两者是有区别的
forward:默认. 请求匹配这个<rule />的所有<condition />,并且URL使用内部跳转到”to”指定的地址(注意, 这里forward 到的URL 必须和UrlRewriteFilter 位于同一个容器中)。状态码302。临时重定向。
redirect :用Response.Redirect实现,请求匹配所有<condition/>和这个<rule />的<from />, 通知客户端跳转到<to/>指定地址,状态码应该是302。
permanent-redirect: 永久重定向。状态码301。相当于做了以下事情
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);.
response.setHeader(“Location”, [<to />指定的值]);
passthrough: 和forward 相同,具体区别我也不清楚。
temporary-redirect:临时重定向。状态码302。 相当于做了以下事情
response.setStatus(HttpServletResponse. SC_MOVED_TEMPORARILY);
response.setHeader(“Location”, [<to />指定的值]);
使用urlrewrite时需要注意
1.如果要用&符号,需要用&代替
2.简单起见, 给<from />的配置前面和后面分别加上^, $, 这两个是正则表达式中的强制开始和结尾标志;
3. 如果使用<outbound-rule>要记得代码中的url都是编码过的;
4. contex 是非常重要的, 如果有一个应用的context 是”/myapp”,并且你的请求是”/myapp/somefolder/somepage.jsp”, 容器交给UrlRewriteFilter 的url会是”/somefolder/somepage.jsp”, 这可能难以理解,但是在你的<rule>和<condition>中不要包含context path, 它是容器负责处理的.
5. 正则表达式非常复杂灵活, 请阅读java.util.regex.Pattern中的java正则介绍。如果觉得正则难以理解,可以使用通配符方式。
6. 应用通配符,通配符匹配引擎可以替代正则表达式, 在<condition>和<rule>中设置match-type是wildcard用以开启支持通配符.(或者设置default-match-type)
例如:
/big/url/*匹配/big/url/abc.html但是不匹配/big/url/abc/dir/或/big/url/abc/
/big/url/**匹配/big/url/abc.html,/big/url/abc/dir/和/big/url/abc/
也可以和正则的替换一样, 每个*代表一个参数,在<set>和<to>中用$N的方式使用
7. <to />可以是null, 意义为: 如果匹配请求不再继续, 相当于没有调用chain.doFilter
补充:大家可能看到我上面的配置中有个$1 ,还不明白是什么意思,我说明一下,$1为<from>^/blog/(\w+)</from>中(\w+)所匹配的内容,如果有多个根据顺序$2...$6获取就可以了,需要注意的是在from中需要用()把要匹配的内容括起来才能获取,不然java会抛出异常