路由

路由是 ThinkJS 中一个非常重要的特性,通过自定义路由,可以让 url 更加友好。

当访问 http://hostname:port/分组/控制器/操作/参数名/参数值/参数名2/参数值 2?arg1=argv1&arg2=argv2 时,通过 url.parse 解析到的 pathname/分组/控制器 /操作/参数名/参数值/参数名2/参数值2

url 过滤

有时候为了搜索引擎友好或者其他原因时,pathname 值并不是直接 / 分组 / 控制器 / 操作 / 的方式,而是含有一些前缀后者后缀。

比如:url 后加 .html 让其更加友好,这种情况下可以通过下面的配置使其在识别的时候去除。

  1. //url 过滤配置
  2. 'url_pathname_prefix': '', // 前缀过滤配置'url_pathname_suffix':'.html' // 后缀过滤配置

经过前缀和后缀去除后,pathname 的值就比较干净了。

注: 如果前缀和后缀去除还满足不了需求,可以通过标签位 path_info 来修正 pathname 值。

路由识别

拿到干净的 pathname 值后,默认通过 / 分组 / 控制器 / 操作 的规则来切割识别。

如:pathname 为 /admin/group/list 识别后的分组为 admin,控制器 group,操作为 list

这里的前提是分组 admin 必须在配置 app_group_list 列表中。app_group_list 默认值为:

  1. // 分组列表
  2. 'app_group_list': ["Home", "Admin"],

如果不在配置列表中,那么识别到的分组为默认分组名称,控制器为 admin,操作为 group。

分组、控制器、操作默认值在如下的配置中:

  1. 'default_group': 'Home', // 默认分组
  2. 'default_controller': 'Index', // 默认控制器
  3. 'default_action': 'index', // 默认操作
  4. // 操作默认后缀
  5. 'action_suffix': 'Action',

识别到对应的分组、控制器、操作后,会调用对应的 controller,执行对应的 action 方法。如:

pathname 为:/admin/group/list,会加载 App/Lib/Controller/Admin/GroupController.js 文件,实例化该类,并调用 listAction 方法。

自定义路由

在实际的项目中,有些重要的接口我们想让 url 尽量简单。如:文章的详细页面,默认路由可能是:article/detail/id/10,但我们想要的 url 是 article/10 这种更简洁的方式。这种 url 如果用默认的路由规则解析,解析出来的控制器和操作并不是我们想要的。

为此 ThinkJS 提供一套自定义路由的策略,需要开启如下的配置:

  1. // 默认情况下开启自定义路由
  2. 'url_route_on': true

开启了自定义路由功能后,就可以在路由配置文件中定义想要的路由解析了。路由配置文件为:App/Conf/route.js,格式如下:

  1. //
  2. // 自定义路由规则
  3. module.exports = [
  4. ["规则 1", "需要识别成的 path"], // 规则到具体 pathname 的映射
  5. ["规则 2", { // 同一个规则根据不同的请求方式对应到不同的 pathname 上
  6. "get": "get 请求时识别成的 path",
  7. "delete": "delete 请求时识别成的 path",
  8. "put,post": "put,post 请求时识别成的 path" // 请求方式为 put 或者 post 时对应的 pathname
  9. }]
  10. ]

ThinkJS 里提供了 3 种自定义路由的方式,下面逐一介绍:

正则路由

正则路由是采用正则表示式来定义路由的一种方式,依靠强大的正则表达式,能够定义非常灵活的路由规则。如:

  1. // 正则路由
  2. module.exports = [
  3. [/^doc\/?(.*)$/, "index/doc?doc=:1"]
  4. ]

这个规则表示将 http://hostname:port/doc/xxx/yyy 这种请求识别到 index/doc 下。


对于正则表达式中的每个变量 (即子模式) 部分,如果需要在后面的路由地址中引用,那么可以采用 :1, :2 这样的方式,序号就是子模式的序号。

这里将 doc 后面的 xxx/yyy 值设置到参数 doc 中,那么在 IndexController.js 文件的 docAction 方法就可以通过 this.get("doc") 来获取该值。

规则路由

规则路由包含静态地址和动态地址,或者是两种地址的结合,如:

  1. module.exports = [
  2. ["my", "user/info"],
  3. ["blog/:id", "Blog/detail"],
  4. ["group/:year/:month", "group/list"]
  5. ]

规则路由以 “/“ 进行参数分割,每个参数中以 “:” 开头的参数表示动态参数,并且会自动生成一个对应的 GET 参数,如:上面的 blog/:id,可以在 Controller 里的 Action 里通过 this.get('id') 来获取 id 的值。

静态路由

静态路由是一种纯静态字符串的路由规则,如:

  1. module.exports = [
  2. ["top", "index/top"],
  3. ["info", "index/user/info"]
  4. ]

静态路由有时候做一些地址重定向的时候可能会用到。