最近忙着自己的博客程式,自然而然就转到了博客中老生长谈的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重写过程后像实际存在此目录相同会具有严密的格式但显得框架结构更方便更灵活,从而得到功能和用户体验上的重点提升
暂时到这里吧。有什么疑问欢迎回复加入讨论。如果有更好的重写方法非常高兴能通知下本人哦。