最近忙着自己的博客程序,自然而然就转到了博客中老生长谈的url重写问题。一个原因是在多用户博客系统中的一个面子问题,本来想拿我的csdn博客http://blog.csdn.net/joshualang来说事,想想还是用我的空间(http://www.tyoo.net)吧,因为这是我的博客完功之后的去所了。
像http://www.tyoo.net/blog/joshualang 如若不进行必要的url重写,就会出http://www.tyoo.net/blog/default.aspx?bloger=joshualang样子的博客地址;大家要知道blog可谓是大部分网民视为筑在网络上的另一个家,现实生活中会考虑家的地址远近,交通好坏,同样网络中的家也要有个好记的门牌号的。这个门牌号还不算太长(还不是很体面哦),后边在加上一堆的参数只怕让人慢慢见而生畏,要看文章就要面对这么一大堆http://blog.tyoo.net/articles/default.aspx?bloger=joshualang&articleid=20070118234530是不是有什么感觉了?再看看现在好多博客程序都要得到的一种效果吧http://blog.tyoo.net/joshua/articles/2007/01/18/大家一看就知道这种效果的好处了,这也就引到了本文的重点所在了!
是的,要通过这样一个很规整的字符串来达到我们的一个目标。
一个可行的url应该遵循以下标准来选择 :
• 简短。
• 易于键入。
• 可以看出站点的结构。
• “可删节”,允许用户通过删除 url 的组成部分来浏览站点。
致于这点就不用我来多说了,其实都是要突出简单,实用。
注意:说到这里就有必要看看msdn网站上scott mitchell的一遍文档http://www.microsoft.com/china/msdn/library/webservices/asp.net/urlrewriting.mspx?pf=true#top
已经有专家在这里将url重写的原理讲得足够明确了,不懂还可以下载上边文档的源代码 来研究一下。
为了图效率(人的时间是宝贵的,程序员的时间更是),就直接采用urlrewriter.net的组件,实际上以前没接触过url重写经历,大致得源程序看了几遍就开始上路了。开始当然不求什么技术含量了,只要能重写成功就已经感觉很ok了,然后才是在不断的重写过程中找出其中问题还有新思路,新发现。。。所以就有了这遍文章。
现在开始吧。这次针对的其实主要就是刚提到的日期模式的url重写.
http://blog.tyoo.net/articles/2007/01/18/233030/joshualang.aspx 这就是要在这里实现的最终效果。
基础: urlrewriter.net组件(当然也可以自已写), 了解正则表达式
参数:articleid //文章编号 [ 类型:string 长度:14(like:yyyymmddhhmmss)//有意义且不会重复 ]
bloger //博主用户名[ 类型:string 字母开头 ]
在url重写过程中遇到的一个问题就是在访问不存在的目录或文件时出现404错误。在msdn上的这遍文档提供的建议就是在程序目录下建立必要的文件夹目录及空的页面,说麻烦的确是麻烦,数千的目录需要建立。
既然不能随便就访问不存在的目录文件,那我们不访问这样的目录不就行了。就要访问我们已经存在的文件(我的全部url指向都是根目录blog下的一个default.aspx页面然后动态加载控件组生成不同的视图功能页面)当然这次要指向的还是这个页面~/default.aspx;
下面的任务就是传递参数,当然是url传值了。这就是重写它的原因了。
主角又要出场了:正则表达式。
在这里用正则表达式真的是太帅了~ http://blog.tyoo.net/joshualang/articles/2007/01/18/default.aspx目录你可能会生成如下这样的url重写规则:
<rewriterrule>
<lookfor>~/(w{6,16})/articles/(d{4})/(d{2})/(d{2})/default.aspx</lookfor>
<sendto>~/default.aspx?bloger=$1&year=$2&month=$3&day=$4</sendto>
</rewriterrule>
这样写出的规则在进行删节时肯定是会因为访问的页面不存在而产生404错误。因为它会顺着你的目录标记一直往下找,要是再建目录工程可就大了,再看看下边的代码:
<rewriterrule>
<lookfor>~/(w{6,16})/articles/(d{4})/(d{2})/(d{2})/(d{6})/default.aspx</lookfor>
<sendto>~/default.aspx?bloger=$1&year=$2&month=$3&day=$4&time=$5</sendto>
</rewriterrule>
这下多出了时间部分该没人会选择建目录了。那就充分利用已经存在的文件来完成这个任务吧。
其实一说可能有很多人都能想到用文件名来代替目录结构。想想看,是不是这样。当然这还得对正则表达式有一定的了解。
好,来看看实现吧。
<rewriterrule>
<lookfor>~/(w{5,16})/articles/(d{4})//(d{2})//(d{2})//(d{6}).aspx</lookfor>
<sendto>~/default.aspx?articleid=$2$3$4$5&bloger=$1</sendto>
</rewriterrule>
大家很容易看出我这里用到了“/”对“/”进行了转义,而且用在了文件名里边现在的结构就是
http://blog.tyoo.net/joshualang/2007/01/18.aspx
很显然我的articleid就是一个以年月日时分秒为基础的字符串,因为这样插入数据不用考虑重复还有意义,而在这里用时间也为查询时方便。$2$3$4$5得到的14位组合就是我的articleid.通过发表日期,文章编号都可以很容易查出记录。而最后一点好处就在进行删节时表现的特为明显。
现在来让我们删节时间部分:
<rewriterrule>
<lookfor>~/(w{5,16})/articles/(d{4})//(d{2})//(d{2}).aspx</lookfor>
<sendto>~/default.aspx?articleid=$2$3$4&bloger=$1</sendto>
</rewriterrule>
依次我们可以将url删节为这样的模式:http://blog.tyoo.net/joshualang/articles/2007.aspx甚至http://blog.tyoo.net/joshualang/articles/default.aspx
是不是很简单。但你要注意一个问题了:什么事不是能够就会实现的了,须要考虑的还有很多比如:
http://blog.tyoo.net/joshualang/articles/2007.aspx和http://blog.tyoo.net/joshualang/articles/2007/.aspx有什么区别,做到上边的规则后后者能否正常运行?不能
同样:http://blog.tyoo.net/joshualang/articles/2007/01/08/.aspx也是不行的。还需要定义其它应对规则来实现恰如其份的重写效果。
好了,大致上效果已经出来了;这里是完整的规则代码:
<!--author: joshua li ([email protected] ) qq:245965348-->
<!-- rules for blog content displayer -->
<rewriterrule>
<lookfor>~/([a-za-z]w{5,16})/default.aspx</lookfor>
<sendto>~/default.aspx?bloger=$1</sendto>
</rewriterrule>
<!-- rules for article lister -->
<rewriterrule>
<lookfor>~/articles/(d{4})//(d{2})//(d{2})//(d{1,6})//([a-za-z]w{5,16}).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1$2$3$4&bloger=$5</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})//(d{2})//(d{2})//(d{1,6})((//)?).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1$2$3$4</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})//(d{2})//(d{2})//([a-za-z]w{5,16}).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1$2$3&bloger=$4</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})//(d{2})//(d{2})((//)?).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1$2$3</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})//(d{2})//([a-za-z]w{5,16}).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1$2&bloger=$3</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})//(d{2})((//)?).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1$2</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})//([a-za-z]w{5,16}).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1&bloger=$2</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/(d{4})((//)?).aspx</lookfor>
<sendto>~/default.aspx?articleid=$1</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/([a-za-z]w{5,16}).aspx</lookfor>
<sendto>~/default.aspx?bloger=$1</sendto>
</rewriterrule>
<rewriterrule>
<lookfor>~/articles/default.aspx</lookfor>
<sendto>~/default.aspx?articleid=-1</sendto>
</rewriterrule>
说明:在这里为了访止用户误删节掉重要的.aspx扩展名,我将用户名作为了文件的虚拟标识名称。
最后得到的url: http://blog.tyoo.net/articles/2007/01/18/015000/joshualang.aspx
同时将放在最后的最长为6位的时间设置为可删节变长,就算丢了某些数字也能最方便的找到与该发表时间最接近的列表。
在去除用户名后也不会影响到使用,还是通过前边详细的时间格式很快会得到与您需要的文章最批配的列表。如果用户名完好则能通过删节找到特定时间段对应作者的文章列表。
还要注意的是:用户名的格式([a-za-z]{6-16})和规则验证的顺序。
总结:
通过规则的url重写过程后像实际存在此目录一样会具有严密的格式但显得框架结构更方便更灵活,从而得到功能和用户体验上的重点提升
暂时到这里吧。有什么疑问欢迎回复加入讨论。如果有更好的重写方法很高兴能通知下本人哦。
新闻热点
疑难解答