用户信息
帖子内容
1 楼
cainiao1v1
注册会员
积分 188
注册 2008-08-06
     
JTBC.NET 稳健性优化建议:getNroute \ getXRouteInfo 核心方法优化
偶然接到一个需求,要为系统增加一个 url key 的功能
即可以使用如 http://www.jtbc.net/aaa-bbb-ccc
这样的URL来访问文章详细页
此目的是为了优化SEO

具体流程如下
当在浏览器里输入  http://www.jtbc.net/aaa-bbb-ccc 时
会被跳到页面 A ,他用来专门处理页面跳转的
他会接收到 aaa-bbb-ccc 但查出这个URL 所对就的 genre 及 内容ID
然后使用
Server.Execute(string.Format("/{0}/default.aspx?type=detail&id={1}", genre , id), Response.Output);
即可跳到真实页面
从而达到URL重写的目的。

但我在处理 Server.Execute 时发现一个问题就是itake 失效了,取不到 任何HTML模版。
经常找发现问题在
getNroute() 里有这一句
if (File.Exists(HttpContext.Current.Server.MapPath("web.config"))) tnroute = "root";
通过 判断 web.config 的位置来判断模块的层级。
由于 上述的页面A是在根目录下,所以 他永远给我返回的是 root,
但实际上模块并不属于 root
于是我优化了几个内核方法,从而实现了这个需求。
优化内容如下:
找出所有使用了Request.ServerVariables["URL"] 的代码
全改为 Request.CurrentExecutionFilePath
因为前者在上述的环境中得到的根目录的 /default.aspx
而后者则得到的是 模块的genre/default.aspx
明显后者更加准确贴切。

如 string tmyURL = HttpContext.Current.Request.ServerVariables["URL"];
改为 string tmyURL = HttpContext.Current.Request.CurrentExecutionFilePath;

然后把
//if (File.Exists(HttpContext.Current.Server.MapPath("web.config"))) tnroute = "root";
//else
//{
//    if (File.Exists(HttpContext.Current.Server.MapPath("../web.config"))) tnroute = "node";
//    else
//    {
//        if (File.Exists(HttpContext.Current.Server.MapPath("../../web.config"))) tnroute = "child";
//        else
//        {
//            if (File.Exists(HttpContext.Current.Server.MapPath("../../../web.config"))) tnroute = "grandchild";
//            else
//            {
//                if (File.Exists(HttpContext.Current.Server.MapPath("../../../../web.config"))) tnroute = "greatgrandchild";
//            }
//        }
//    }
//}

改为下列方式
switch (count)
{
    case 2:
        tnroute = "root";
        break;
    case 3:
        tnroute = "node";
        break;
    case 4:
        tnroute = "child";
        break;
    case 5:
        tnroute = "grandchild";
        break;
    case 6:
        tnroute = "greatgrandchild";
        break;
}

在得到了准确的 CurrentExecutionFilePath 之后直接用 split('/') 来分割成数组,再根据数组的长度来判断 模块的层级, 这种方法比判断 web.config 的位置的方法更可靠,也更快。

同时所有xml模板文件是通过getXInfo中的
tXMLDom.Load(HttpContext.Current.Server.MapPath(tSourceFileStr));
来读取的
其中的 tSourceFileStr 参数的生成,在上述场景中也会出错,因为 页面A是在根目录,HttpContext.Current.Server.MapPath的当前目录此刻也是在根目录,但实际我们请求的页面却是 指定genre模块下的页面,这会造成 getXRouteInfo 读取xml 内容时会出错。
如 生成的tSourceFileStr 内容是 ../../aaaa/bbbb.jtbc
此是 HttpContext.Current.Server.MapPath 已经在根目录了
再执行 HttpContext.Current.Server.MapPath('../../aaaa/bbbb.jtbc') 就会报错,说不能再退出顶层目录了。
那么我们只需要修改 生成 tSourceFileStr 的方法即可。
这个方法叫 getXRouteInfo,我们修改他,让他不再生成如 ../../ 格式的文件路径,统一生成形如
~/aaa/bbb/ccc/dddddd.jtbc 这种模式的。

优化如下:
        public string[] getXRouteInfo(string argXInfostr, string argXInfoType)
        {
            string path = string.Empty;
            string file = string.Empty;

            string tRoute = string.Empty;
            string tXInfostr = argXInfostr.ToLower();
            string tXInfoType = argXInfoType;
            switch (tXInfoType)
            {
                case "cfg":
                    tRoute = "common";
                    break;
                case "lng":
                    tRoute = "common/language";
                    break;
                case "sel":
                    tRoute = "common/language";
                    break;
                case "tpl":
                    tRoute = "common/template";
                    break;
                default:
                    tRoute = "common";
                    break;
            }
            if (tXInfostr.Substring(0, 7) == "global.")
            {
                tXInfostr = cls.getLRStr(tXInfostr, ".", "rightr");
                if (tXInfostr.IndexOf(":") >= 0)
                {
                    tRoute = cls.getLRStr(tXInfostr, ":", "left") + "/" + tRoute;
                    tXInfostr = cls.getLRStr(tXInfostr, ":", "right");
                }
                //tRoute = cls.getActualRoute(tRoute.Replace(".", "/")); // 不再使用 getActualRoute 去定位

                path = "~";
            }
            else
            {
                // 对于当前模块文件的模板调用,使用 _context.Request.AppRelativeCurrentExecutionFilePath 来判断路径更加准确
                path = cls.getLRStr(HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath, "/", "leftr");
            }

            file = cls.getLRStr(tXInfostr, ".", "leftr").Replace(".", "/") + config.xmlsfx;

            string[] tAry = new string[2];
            tAry[0] = string.Format("{0}/{1}/{2}", path, tRoute, file);
            tAry[1] = cls.getLRStr(tXInfostr, ".", "right");
            return tAry;
        }

通过如上的优化后,得到的 tSourceFileStr 永远是以 ~/ 开头的完整的相对目录字符串了。
java 及 php 版我不太清楚是否有形如 asp.net 的 ~/ 字符可以表示根目录的方法,如果有的话,移植也同理。
本帖由 cainiao1v1 于 2016-10-21 12:10:56 编辑过
2016-10-20 20:46:03