`
yipsilon
  • 浏览: 246269 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

关于URL路由的一些事儿

阅读更多
虽然有人抱怨使用Apache的mod_rewrite在访问量大的时候经常会出现CPU的占用率为 100%的情况,但是对于一些中小型网站来说,这样做毕竟会美化URL,有益于搜索引擎的收录。

因此CMSPAD 1.1的最后一个特性就是支持URL路由(或URL Rewrite?),以下称URLR。那么,CMSPAD是如何支持URLR的呢?下面我们来分析一下URL路径的一些特性。

一个URL由协议、主机、端口、访问路径组成,前三者忽略,说说访问路径吧,它是一个由“/”分隔的一个字符串,用来定位文件位置。正常的一个网站的URL模式为:
http://www.yourcompany.com/index.php

其中“/index.php”就是其访问路径(或叫URI?不知道,自己查查吧)。而好多网站为了隐藏整站程序的实现技术,一般都隐藏了文件后缀,例如:
http://www.yourcompany.com/hello/world/2007/12/20

通过某些URLR技术来进行路径重写到指定脚本文件中。Servlet路径模式匹配和RoR都是这样干的。

因此,如何使用CMSPAD把路径给优化成很不错的感觉呢?其实很简单。

1. 建立一个Dispatcher文件,是PHP的。
<?php
require_once('kernel/global.php'); //包含CMSPAD核心文件
import('Dispatcher'); //导入Dispatcher包
$dispatcher = new Dispatcher('default'); //创建Dispatcher实例,这里使用默认的URLR解析器
$dispatcher->dispatch(isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:''); //使用PATH_INFO作为参数进行URLR转换。
?>
当然,如果你不想使用PATH_INFO作为路径转换,可以使用其他的数据,例如GET参数。将文件保存在网站目录下,例如 /index.php。

2. 增加 .htaccess 文件:就是写Apache的URL Rewrite规则,这里就不提了。

3. 新建一个Portlet,如果不知道什么叫Portlet,那就看看偶本博客中以前的文章。
class DefaultPortal extends Portlet{
  public function pageDefaultPortal($params){
    return 'This is home page: '.$params[0];
  }
  public function pageHelloWorld($params){
    return 'This is hello world page: '.print_r($params);
  }
}
看到了没有,所有的URLR方法都是以“page”开头的,并且有个类型为单项数组的参数($params),并返回输出的内容,将代码保存到Portlet主目录下的DefaultPortal.php文件中。

4. 本节就三个字:搞定鸟。

在测试之前,大家需要了解一下CMSPAD URLR的一些路径处理规则:

1. default: 默认的路径处理方法,格式为 /[PortletName]/[PageName]/[Param1[/Param2[...]]]

2. statics: 伪静态页的路径处理方法,格式为:/[PortletName]/[PageName]/[Param1[,Param2[...]]].html

在这里如果没有PageName,那么CMSPAD将自动匹配到与PortletName同名的方法,例如使用默认模式的路径 /SimplePortlet/100/200/300 将被转换为 /SimplePortlet/SimplePortlet/100/200/300。

如果连PortletName也没有,没事儿,CMSPAD可以通过配置信息变量 $_CONFIG['DISPATCH']['PORTAL'] 来作为默认的Portlet使用;如果连 $_CONFIG['DISPATCH']['PORTAL'] 变量都没有定义,也没事儿,系统会自动使用 DefaultPortal 作为Portlet名字来使用;如果连 DefaultPortal 也没定义,那没办法了,系统会返回404错误。

下面就开始测试了:

把Apache服务器打开,假设以上程序在web根目录下,在浏览器中敲入下列地址 http://localhost/index.php/DefaultPortal/100000,你将会看到以下内容:
This is home page: 100000
,而敲入 http://localhost/index.php/DefaultPortal/helloWorld/100/200,则会看到:
This is hello world page: Array([0] => 100, [1] => 200)


而如果使用statics模式,则路径分别为:http://localhost/index.php/DefaultPortal/100000.html 和 http://localhost/index.php/DefaultPortal/helloWorld/100,200.html

这就有个问题了,如果可以任意转换URLR处理器,那么在模板中使用路径时怎么样动态转换路径呢?答案当然是有的啦,哈哈

在模板中,使用hyperlink函数即可实现,例如:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>URL Router Portal Test</title>
</head>
<body>
<!-- 完整的使用方法 1-->
<a href="<{hyperlink portlet="DefaultPortal" page="DefaultPortal" arg1="100" arg2="200"}>">Portal Link 1</a><br/>
<!-- 完整的使用方法 2-->
<a href="<{hyperlink portlet="DefaultPortal" page="helloworld" arg1="100" arg2="200"}>">Portal Link 2</a><br/>
<!-- 最简使用方法,使用当前Portlet的名字,如果没有在Portlet中使用则使用默认的DefaultPortal,方法名与Portlet名字相同 -->
<a href="<{hyperlink arg1="100" arg2="200"}>">Portal Link 3</a><br/>
<!-- 简便使用方法 1,方法名与Portlet名相同 -->
<a href="<{hyperlink portlet="DefaultPortal" arg1="100" arg2="200"}>">Portal Link 4</a><br/>
<!-- 简便使用方法 2,使用当前Portlet的名字,如果没有在Portlet中使用则使用默认的DefaultPortal-->
<a href="<{hyperlink page="helloworld" arg1="100" arg2="200"}>">Portal Link 5</a><br/>
</body>
</html>
这样,当在后台转换URLR路径处理了方法时,则模板中自动应用了新的路径。

使用默认URLR处理器时输出为:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>URL Router Portal Test</title>
</head>
<body>
<a href="/index.php/DefaultPortal/100/200">Portal Link 1</a><br/>
<a href="/index.php/DefaultPortal/helloworld/100/200">Portal Link 2</a><br/>
<a href="/index.php/DefaultPortal/100/200">Portal Link 3</a><br/>
<a href="/index.php/DefaultPortal/100/200">Portal Link 4</a><br/>
<a href="/index.php/DefaultPortal/helloworld/100/200">Portal Link 5</a><br/>
</body>
</html>
而使用statics处理器时输出为:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>URL Router Portal Test</title>
</head>
<body>
<a href="/index.php/DefaultPortal/100,200.html">Portal Link 1</a><br/>
<a href="/index.php/DefaultPortal/helloworld/100,200.html">Portal Link 2</a><br/>
<a href="/index.php/DefaultPortal/100,200.html">Portal Link 3</a><br/>
<a href="/index.php/DefaultPortal/100,200.html">Portal Link 4</a><br/>
<a href="/index.php/DefaultPortal/helloworld/100,200.html">Portal Link 5</a><br/>
</body>
</html>


下面来看看如何开发URLR路径处理器吧:

创建一个名字为 cmspad_router_<文件名字>的类,实现 URLRouter接口,并实现接口里的两个函数:
class cmspad_router_myrule implements URLRouter{
  public function route($pathinfo){
    // 处理并输出路径所对应的内容。
  }

  public function hyperlink($portlet = null, $method = null, $parameters = array()){
    // 生成并返回该规则的URL路径。
  }
}
将以上代码保存到 inc/urlrouters/myrule.php 文件中。然后在创建Dispatcher文件的代码中将
$dispatcher = new Dispatcher('default'); 
改成
$dispatcher = new Dispatcher('myrule'); 
这样,你写的规则就应用上去了。

下面给出当前默认实现(default)的源代码:
<?php
cmspad_import('util.PortletUtil');
class cmspad_router_default implements URLRouter{
  
  private $portal;
  
  public function __construct($portal = 'DefaultPortal'){
    $this->portal = $portal;
  }

  public function route($pathinfo){
    while(strpos($pathinfo,'//') !== false){
      $pathinfo = str_replace('//','/',$pathinfo);
    }
    $pathinfo = trim($pathinfo,' /');
    if(empty($pathinfo)){
      $pathinfo = $this->portal . '/' . $this->portal;
    }
    $arr = explode('/',$pathinfo);
    if(count($arr) > 0){
      $portlet = $arr[0];
      $portletObj = PortletUtil::newObject($portlet);
      if($portletObj === null || $portletObj === false){
        $portletObj = PortletUtil::newObject($portlet = $this->portal);
      }else{
        array_shift($arr);
      }
    }
    if($portletObj === null || $portletObj === false){
      return false;
    }
    if(count($arr) > 0){
      $portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($arr[0]));
      if($portletArr === null || $portletArr === false){
        $portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($portlet));
      }else{
        array_shift($arr);
      }
      $portletArg = $arr;
    }else{
      $portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($portlet));
      $portletArg = array();
    }
    if($portletArr === null || $portletArr === false){
      return false;
    }
    
    $contents = call_user_func($portletArr,$portletArg);
    if($contents){
      echo $contents;
    }
    return true;
  }

  public function hyperlink($portlet = null,$method = null,$params = null){
    global $_CONFIG;
    if(isset($_CONFIG['DISPATCH']['SCRIPT'])){
      $url = $_CONFIG['DISPATCH']['SCRIPT'];
    }else{
      $url = $_SERVER['SCRIPT_NAME'];
    }
    if(!$portlet){
      $portlet = $this->portal;
    }
    if($portlet){
      $url .= ($portlet == $this->portal?'':'/' . $portlet);
      if($method){
        $url .= ($method == $portlet?'':'/' . $method);
      }
      if($params){
        $url .= '/' . implode('/',$params);
      }
    }
    return $url;
  }
}
?>
此代码保存在 inc/urlrouters/default.php 中。
分享到:
评论

相关推荐

    aio-routes:asyncio 的 URL 路由库

    aio-routes Aio-routes 是一个用于 Web 应用程序的 URL 路由库。 它不支持典型的基于模式或正则表达式的路由。 而是在解析 url 时遍历对象。 请参阅下面的示例,了解更多信息Aioroutes 不仅适用于 HTTP,还适用于...

    路由:Nette路由:双向URL转换

    Nette路由:双向URL转换 介绍 路由器负责有关URL的所有事情,因此您不必再考虑它们。 我们将展示: 如何设置路由器,使URL看起来像您想要的 有关SEO重定向的一些注意事项 我们将向您展示如何编写自己的路由器 它...

    react-reactroutercomponentReact的声明式路由器组件

    7. 路由事件:路由器提供了一些生命周期方法,如`willTransitionTo`和`willTransitionFrom`,允许在路由切换前后执行特定操作,如验证权限、数据预加载等。 8. 路由状态:`react-router-component` 可以通过`state....

    还儿童一个健康上网环境,正式开启我的路由器URL网址白名单之旅

    在建立URL白名单这个事情上,因为不了解路由器,所以我走了很多弯路,花费了大量的时间精力和金钱。 前后尝试过华硕RT-AC1900P、华为荣耀pro2、斐讯K2P、TP-LINK企业无线路由器 TL-WAR1200L以及软路由openwrt都不是...

    ouija:路由解析库用于需要诸如RESTful应用路由处理之类的事情

    2. **路由处理**:如何定义和处理路由,包括URL模式匹配、参数捕获、中间件和路由分发。 3. **OCaml编程语言**:了解OCaml的基本语法、类型系统、函数式编程概念,以及OCaml的模块系统和面向对象编程特性。 4. **...

    Vue路由前后端设计总结

    一开始我还以为vue的路由只能用在工程化的项目里面呢,然后研究了一下才发现,在脚本化里面也是可以用的。其实呢不管在哪里用,把原理研究明白就对了。 一、 官网demo 这里不得不吐槽一下官网,写的不清不楚的,在...

    rudy:Rudy Router-适用于react-redux应用程序的MVC样式路由异步控制器

    它可以做的一些事情: 在您选择的URL和Redux操作之间保持双向映射。 就您的应用而言,URL更改是Redux操作,而路由状态是Redux状态。 此映射的工作方式与服务器端和客户端渲染相同。 触发在redux操作(包括但不...

    angular-api-urls:用于管理 API url 的简单角度提供程序

    例子首先用一个简单的安装模块bower install --save angular-api-urls 然后做一些很酷的事情。 有两种配置 API 的方法。 如果您只有一个 API,只需使用APIUrlsProvider参数对其进行配置。 否则,您可以在apis属性中...

    关于vue-router的那些事儿

    但在 Vue Router 的单页应用中,路由不再对应服务器上的具体文件,而是通过 JavaScript 处理 URL 变化,实现页面组件的动态切换,无需重新加载整个页面。这样可以提高用户体验,减少网络传输。 Vue Router 的核心...

    移除AngularJS下URL中的#字符的方法

    AngularJS 默认将会使用一个 # 号来对URL进行路由. 例如:  http://example.com/  http://example.com/#/about  http://example.com/#/contact 要获得干净的URL并将井号从URL中移除是很容易的. 完成两件事情就行了...

    url_server:用于切换黑客马拉松项目 URL 的基本 http 代理

    通过JavaScript,开发者可以在服务器端执行逻辑,处理HTTP请求和响应,这正是`url_server`所做的事情。 在黑客马拉松中,团队通常需要快速迭代并测试他们的应用,而这些应用可能部署在不同的临时服务器上,或者使用...

    takeme:一个简单有效的路由解决方案

    那时的事情更简单 :rose: 具有简单单向数据流的简单客户端路由解决方案: url ------&gt; ApplicationState ------&gt; YourView :up-left_arrow: :down-left_arrow: navigate | link | browser history 使用 ...

    微信小程序-微信小程序-木棉小镇

    cottonTown 微信小程序-木棉小镇 一个朋友的项目,所有前端代码在这里公开,都是模拟数据,后面的接口将不会更新。 项目主要有以下几个特点: ...开发者不用维护路由,不用管理状态,这些事情微信的框架都帮你做了。

    Laravel开发-laravel-skeleton

    - **路由服务提供者**:Laravel 的路由系统允许开发者通过简单易懂的语法定义 URL 路由,并关联到控制器方法或闭包。 **2. Laravel-skeleton 的结构分析** 在 `laravel-skeleton-master` 文件中,我们可以看到以下...

    django-easy-app

    在基于 django 类的视图类上使用新的“路由”属性指定 url 路由的能力。 这使得编写和使用基于类的视图成为可能,而无需理解正则表达式并单独更新 urls.py。 将starteasyapp命令添加到 manage.py 以允许轻松创建...

    精通AngularJS part1

    路由映射URL174 定义路由时指定控制器174 导航的不足175 63使用AngularJS自带的路由服务175 基础路由定义175 显示匹配的路由内容176 匹配灵活的路由177 定义默认路由178 访问路由参数178 多个控制器重用...

    VUE面试必备题(含答案)

    * mounted:挂载后,在这发起后端请求,拿回数据,配合路由钩子做一些事情 * beforeUpdate:数据更新之前 * updated:数据更新完成之后 * beforeDestroy:销毁之前,你确认删除 XX 吗?或者确认退出吗? * destroyed...

    Exchange 2007 安装完后需要注意的几件事情

    因此,必须创建一个新的发送连接器,配置其目标为Internet,并正确配置出站路由规则,以确保邮件可以成功发送。 3. 证书: 默认情况下,IIS服务器获得的证书可能未被企业信任,这可能导致安全问题和用户访问问题。...

    基于PHP的boa框架.zip

    1. **路由系统**: boa提供灵活的路由规则,允许开发者根据URL映射到不同的控制器和动作。 2. **依赖注入**: boa支持依赖注入,使得组件间的耦合度降低,提高代码的可测试性和可维护性。 3. **模型层**: boa的模型...

    micro-frontend:这个专案讨论一些“微前端”的一些事情

    3. **路由聚合**:通过统一的路由管理系统,根据URL路径来决定加载哪个子应用,例如使用`single-spa`库。 4. **组件化共享**:通过全局注册和懒加载,实现跨应用组件复用,如`@vue/composition-api`或React的...

Global site tag (gtag.js) - Google Analytics