第一次使用,代码可能不够完善,先放这,让大家给把把脉,其中混着一些静态页生成
重写HttpModel模块
using System;
using System.Web;
using System.Text.RegularExpressions;
using System.Collections;
namespace Web
{
/// <summary>
/// HttpModelReWriter 的摘要说明。
/// </summary>
public class HttpModelReWriter : IHttpModule
{
public HttpModelReWriter()
{
}
public void Init(HttpApplication app)
{
//事件订阅
app.BeginRequest += (new EventHandler(this.BeginRequest));
}
protected void BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
ReWriter(app.Request.Path,app);
}
protected void ReWriter(string requestedPath,HttpApplication app)
{
//动态页面不重写
if(requestedPath.IndexOf(".aspx") < 0)
{
ReWriterRules rules = ReWriterRules.GetInstance();
foreach(DictionaryEntry dic in rules)
{
RuleItem rule = (RuleItem)dic.Value;
string lookFor = "^" + RewriterHandler.ResolveUrl(app.Context.Request.ApplicationPath,rule.LookFor) + "$";
Regex reg = new Regex(lookFor, RegexOptions.IgnoreCase);
if (reg.IsMatch(requestedPath))
{
string sendToUrl = RewriterHandler.ResolveUrl(app.Context.Request.ApplicationPath, reg.Replace(requestedPath, rule.SendTo));
RewriterHandler.RewriteUrl(app.Context,sendToUrl,rule);
break;
}
}
}
else
{
//有参数update=1,则强制更新,该方法效率不好,在此作为一种补充手段,页面更新主要靠WIN服务来完成
if( null != app.Request.QueryString["update"] && "1" == app.Request.QueryString["update"].ToString() )
{
string htmlFile = URLBuild.GetStaticURL(app.Request.RawUrl.Replace("&update=1",""));
int iResult = 0;
try
{
iResult = RewriterHandler.CreateHtmlFile(app.Server.MapPath(htmlFile),app.Request.RawUrl.Replace("&update=1",""),app.Request.Url.Host);
}
catch(Exception ex)
{
app.Context.Response.Clear();
app.Context.Response.Write(ex.Message);
app.Context.Response.End();
return;
}
app.Context.Response.Clear();
app.Context.Response.Write(iResult);
app.Context.Response.End();
}
}
}
public void Dispose()
{
}
}
}
读配置模块(网上见很多人用序列化来读)
using System;
using System.Xml;
using System.Configuration;
namespace Web
{
/// <summary>
/// RewriterConfigHandle 的摘要说明。
/// </summary>
public class RewriterConfigHandle : IConfigurationSectionHandler
{
public RewriterConfigHandle()
{
}
public object Create(object parent, object input, XmlNode node)
{
if ( "#comment" == node.Name )
return null;
//处理RewriterConfig
foreach ( XmlNode xn in node.ChildNodes )
{
Read(xn);
}
return 1;
}
private void Read(XmlNode node)
{
if ( "#comment" == node.Name )
return;
RuleItem ri = new RuleItem();
//处理RewriterRule
foreach ( XmlAttribute xa in node.Attributes )
{
switch ( xa.Name.ToUpper() )
{
case "ID":
{
ri.ID = xa.Value;
break;
}
case "LOOKFOR":
{
ri.LookFor = xa.Value;
break;
}
case "SENDTO":
{
ri.SendTo = xa.Value;
break;
}
case "POLICY":
{
if ( xa.Value.Trim() != "" )
ri.Policy = Convert.ToInt32(xa.Value);
break;
}
default:
{
break;
}
}
}
ReWriterRules rules = ReWriterRules.GetInstance();
rules.Add(ri.ID,ri);
}
}
}
URL重写部分
using System;
using System.Web;
using System.Web.UI;
using System.Text.RegularExpressions;
using System.IO;
using System.Net;
namespace Web
{
/// <summary>
/// RewriterUtils 的摘要说明。
/// </summary>
public class RewriterHandler
{
private RewriterHandler()
{
}
/// <summary>
/// 替换~
/// </summary>
/// <param name="rootPath"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static string ResolveUrl(string rootPath,string filePath)
{
if ( Regex.IsMatch(filePath,"^~",RegexOptions.IgnoreCase) )
{
return filePath.Replace("~",rootPath).Replace("//","/");
}
else
{
return filePath.Replace("//","/");
}
}
/// <summary>
/// URL重写加静态页生成
/// </summary>
/// <param name="context"></param>
/// <param name="sendToUrl"></param>
/// <param name="rule"></param>
public static void RewriteUrl(HttpContext context,string sendToUrl,RuleItem rule)
{
string htmlRequestStr = context.Request.Path;
if(htmlRequestStr.IndexOf(".htm") == - 1)
{
htmlRequestStr = Regex.IsMatch(htmlRequestStr,@"^"+context.Request.ApplicationPath + "(/?)$",RegexOptions.IgnoreCase) ? URLBuild.GetStaticURL(sendToUrl) : htmlRequestStr.TrimEnd('/') + ".htm";
}
else
{
htmlRequestStr = htmlRequestStr.Replace(".html",".htm");
}
string htmlFile = context.Server.MapPath(htmlRequestStr);
int iResult = 0;
try
{
//无静态页,或已过期
if( !File.Exists(htmlFile) )
{
iResult = CreateHtmlFile(htmlFile,sendToUrl,context.Request.Url.Host);
}
else if ( rule.Policy > 0 )
{
FileInfo fi = new FileInfo(htmlFile);
if(DateTime.Now > fi.CreationTime.AddMinutes(rule.Policy))
{
fi.Delete();
iResult = CreateHtmlFile(htmlFile,sendToUrl,context.Request.Url.Host);
}
}
}
catch(Exception ex)
// if ( -1 == iResult )
{
// context.Response.Write("服务器繁忙,请稍后再试");
context.Response.Write(ex.Message);
context.Response.End();
return;
}
//在此可能要加实际路径参数???
context.RewritePath(htmlRequestStr);
}
/// <summary>
/// 创建静态页,通过重发一次请求来完成,效率不高
/// 可以重写HttpHandle,读Response流来完成
/// </summary>
/// <param name="htmlFile"></param>
/// <param name="sendToUrl"></param>
/// <param name="host"></param>
/// <returns></returns>
public static int CreateHtmlFile(string htmlFile,string sendToUrl,string host)
{
System.Text.Encoding encode = System.Text.Encoding.GetEncoding("UTF-8");
try
{
// HttpWebRequest hwrq = (HttpWebRequest)HttpWebRequest.Create("http://" + host + sendToUrl);
//中心网站服务器为内部跳转,承载的机器无法访问外网,取HOST会有问题
HttpWebRequest hwrq = (HttpWebRequest)HttpWebRequest.Create("http://localhost" + sendToUrl);
HttpWebResponse hwrp = (HttpWebResponse)hwrq.GetResponse();
if( null != hwrp )
{
StreamReader readStream = new StreamReader( hwrp.GetResponseStream(), encode );
string htmlFilePath = htmlFile.Substring(0,htmlFile.LastIndexOf(@"/"));
//验证目录
if(!Directory.Exists(htmlFilePath))
Directory.CreateDirectory(htmlFilePath);
FileStream fs = new FileStream(htmlFile,FileMode.Create,FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs,encode);
sw.Write(readStream.ReadToEnd());
sw.Flush();
fs.Flush();
sw.Close();
fs.Close();
readStream.Close();
hwrp.GetResponseStream().Close();
}
return 1;
}
catch(Exception ex)
{
throw ex;
//return -1;
}
}
}
}
URL重写规则实体集合类
using System;
using System.Collections;
namespace Web
{
/// <summary>
/// ReWriterRules 的摘要说明。
/// </summary>
public class ReWriterRules : IEnumerable
{
private static ReWriterRules helf = new ReWriterRules();
private Hashtable htRules = null;
private ReWriterRules()
{
htRules = new Hashtable();
}
public static ReWriterRules GetInstance()
{
if ( null == helf )
{
helf = new ReWriterRules();
}
return helf;
}
#region 属性
/// <summary>
/// 连接参数索引器
/// </summary>
public RuleItem this[object index]
{
get
{
if ( null == htRules || 0 == htRules.Count )
ReadConfig();
object o = htRules[index];
RuleItem r = (RuleItem)o;
return r;
}
set
{
htRules[index] = value;
}
}
/// <summary>
/// 获取参数总数
/// </summary>
public int Count
{
get
{
if ( null == htRules || 0 == htRules.Count )
ReadConfig();
return this.htRules.Count;
}
}
#endregion
#region 公共方法
/// <summary>
/// 添加新参数
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add ( object key,object value )
{
if ( !ContainsParam(key) )
this.htRules.Add(key,value);
}
/// <summary>
/// 删除参数
/// </summary>
/// <param name="key"></param>
public void Remove ( object key )
{
if ( ContainsParam(key) )
this.htRules.Remove(key);
}
/// <summary>
/// 测试是否存在特定的参数
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool ContainsParam(object key)
{
return this.htRules.ContainsKey(key);
}
public IEnumerator GetEnumerator()
{
if (Count > 0)
return htRules.GetEnumerator();
else
return null;
}
#endregion
private void ReadConfig()
{
try
{
System.Configuration.ConfigurationSettings.GetConfig("RewriterConfigurations");
}
catch(Exception ex)
{
throw ex;
}
}
}
}
URL重写规则配置类
using System;
namespace Web
{
/// <summary>
/// RuleItem 的摘要说明。
/// </summary>
public class RuleItem
{
private string id = "";
private string lookFor = "";
private string sendTo = "";
private int policy = 0;
public RuleItem()
{
}
public RuleItem(string id,string look,string send,int policy)
{
this.id = id;
lookFor = look;
sendTo = send;
this.policy = policy;
}
#region 属性
public string ID
{
get
{
return id;
}
set
{
id = value;
}
}
public string LookFor
{
get
{
return lookFor;
}
set
{
lookFor = value;
}
}
public string SendTo
{
get
{
return sendTo;
}
set
{
sendTo = value;
}
}
public int Policy
{
get
{
return policy;
}
set
{
policy = value > 0 ? value : 0;
}
}
#endregion
}
}
生成静态URL类
using System;
using System.Text.RegularExpressions;
namespace Web
{
/// <summary>
/// 根据重写规则,反生成静态页地址,以便绑定到页面
/// </summary>
public class URLBuild
{
public URLBuild()
{
}
public static string GetStaticURL(string strURL)
{
//如果本身就是静态URL,直接返回
if (Regex.IsMatch(strURL,@"[/w+].htm[l?]$",RegexOptions.IgnoreCase) )
return strURL;
string strPath = strURL.Substring(0,strURL.IndexOf("?"));
strPath = strPath.Substring(0,strPath.LastIndexOf("/"));
strPath += "/Journal";
string[] arrParam = strURL.Replace(strPath + "?","").Split('&');
if ( arrParam == null || arrParam.Length == 0 )
return strPath + ".htm";
for ( int i = 0; i < arrParam.Length; i ++ )
{
string[] arr = arrParam[i].Split('=');
if ( arr.Length == 2 && arr[1] != "" )
strPath += "/" + arr[1];
}
return strPath + ".htm";
}
}
}
配置文件样式
<configSections>
<!-- URL重写配置节设置 -->
<section name="RewriterConfigurations" type="Web.RewriterConfigHandle, CNKIURLReWriter"></section>
</configSections>
<!-- 现重写存在的小问题,图片资源路径问题 -->
<!-- policy的值默认以分钟为单位,0 表示永不过期 -->
<RewriterConfigurations>
<!-- RewriterRule ID = "1" lookFor = "~(/?)" sendTo = "~/Index.aspx?NaviID=1" policy="0"/ -->
<RewriterRule ID = "2" lookFor = "~/Journal(/?)" sendTo = "~/Index.aspx?NaviID=1" policy="1"/>
<RewriterRule ID = "3" lookFor = "~/Journal/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Index.aspx?NaviID=$1" policy="1"/>
<RewriterRule ID = "4" lookFor = "~/Journal/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/List.aspx?NaviID=$1&ZJDM=$2" policy="1"/>
<RewriterRule ID = "5" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/List.aspx?NaviID=$1&ZJDM=$2&ZTDM=$3" policy="1"/>
<RewriterRule ID = "6" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Item.aspx?NaviID=$1&ZJDM=$2&ZTDM=$3&PYKM=$4" policy="0"/>
<RewriterRule ID = "7" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Item.aspx?NaviID=$1&ZJDM=$2&ZTDM=$3&PYKM=$4&Year=$5" policy="0"/>
<RewriterRule ID = "8" lookFor = "~/Journal/(/w+)/(/w+)/(/w+)/(/w+)/(/w+)/(/w+)((/?)|(/.htm(l?)))?" sendTo = "~/Item.aspx?NaviID=$1&ZJDM=$2&ZTDM=$3&PYKM=$4&Year=$5&Issue=$6" policy="0"/>
<RewriterRule ID = "9" lookFor = "~/SiteMap(/.htm(l?))?" sendTo = "~/SiteMap.aspx?NaviID=1" policy="1"/>
</RewriterConfigurations>
<system.web>
<httpModules>
<add name="ReWriteModule" type="Web.HttpModelReWriter, CNKIURLReWriter"/>
</httpModules>
*注意:
1、因为实现可截取URL,会配置IISAPI,对于图片/样式等资源,可能会发生路径问题
2、配置IISAPI后,会发现,所有资源请求都会转向ASP.NET,无论调试还是运行起来,感觉都不太爽
解决办法:另建一个资源服务器,所有资源路径都改为网络资源连接