集中式路由

集中式路由

问题

怎样集中的定义路由

解决方案

通过调用 HttpRouteCollectionExtension 类中的 MapHttpRoute 扩展方法在 HttpRouteCollection 中定义路由,可以通过 HttpConfiguration 对象调用。

最基础的使用就是定义一个非常通用的路由模板,他会通过 {controller} 占位符匹配所有的 Controller。如代码片段 3-1 所示。

代码片段 3-1. ASP.NET WEB API 默认定义的路由以及一个简单的 Controller

 1 config.Routes.MapHttpRoute(
 2     name: "DefaultApi",
 3     routeTemplate: "api/{controller}/{id}",
 4     defaults: new {id = RouteParameter.Optional}
 5     );
 6
 7
 8
 9 public class OrdersController : ApiController
10 {
11     public Order Get(int id)
12     {
13         // 忽略逻辑
14     }
15 }

在路由模板中,可以定义自己的占位符,如代码片段 3-1 所示的 {id}。他与 Action 中的参数名称相匹配匹配,ASP.NET WEB API 会从 request 中提取出相应的值,传入 Action 方法中。也就是,代码片段 3-1 中 OrdersController 的 Get请求方法的这种情

况。

工作原理

从最初版本开始,ASP.NET WEB API 就一直使用集中式路由维护路由表,这和 MVC 如出一辙。

ASP.NET WEB API 定义了很多 MapHttpRoute 的变种。所需参数最少的一个方法,只需要一个路由模板和一个路由名称。

1 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name,
2     string routeTemplate)

除声明简单基础路由以外的方式,也可以通过默认值和约束,或者设置每个路由消息处理程序,将会在下面的章节介绍这个。所有的这些操作都是通过 Map HttpRoute 的重载方法实现的。

1 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name,
2     string routeTemplate, object defaults)
3
4 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name,
5     string routeTemplate, object defaults, object constraints)
6
7 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name,
8     string routeTemplate, object defaults, object constraints, HttpMessageHandler handler)

通过路由默认值,可以直接定位到路由相关的 Controller;可是,这样的特定路由需要定义在通用路由之前,也就是代码片段 3-1 的路由之前。原因就是,路由是顺序匹配的,路由在选定处理一个 HTTP 请求的时候,是在每次请求的时候,扫描路由集合中的所有路由,选用第一个被匹配的路由模板。简单的说,越是特殊的路由定义越靠前,越是通用的路由定义越靠后。

在  Self-hosting 中,ASP.NET WEB API 是以 IDictionary<stirng, IHttpRoute> 的形式在维护路由,Idictionary<string, IHttpRoute> 是在 HttpRouteCollection 类中。在 Web host 中也提供了 System.Web.Routing.RouteCollection 的扩展方法,因此,可以直接在这个里面定义 ASP.NET WEB API 路由。

RouteTable.Routes.MapHttpRoute("DefaultApi", "api/{controller}")

如果使用 ASP.NET 运行时 host WEB API,无论使用什么扩展方法声明路由,都会被添加到同一个 RouteTable 中。内部是通过一个叫做 HostedHttpRouteCollection 的类来实现的,这个类是 HttpRouteCollection 的子类,而不是在字典(比如 self-host)中维护路由,所有转发路由都是查找 System.Web.RouteCollection。

ASP.NET WEB API 与 ASP.NET MVC 是不一样的,API 使用的是基于 HTTP 谓词匹配来处理一个 Controller 请求。换句话说,框架会根据 HTTP 的东西来选择一个 Action 处理请求,选择的逻辑如下:

  • 通过方法名推断 HTTP 谓词,如果名字类似于 PostOrder、GetById 等等。
  • 通过 Action 属性推断 HTTP 谓词。
  • Action 参数定义与路由模板必须匹配。

典型的 ASP.NET WEB API 路由是指向资源的。可以通过 HTTP  谓词调用,还需要除了 Action 之外的参数。如代码片段 3-1 所示的默认路由,可以匹配如下请求:

  • GET myapi.com/api/orders
  • POST myapi.com/api/inovice
  • PUT myapi.com/api/invice/2

小提示 在 ASP.NET WEB API 是可以使用 RPC 的,具体细节会在 3-6 介绍。

代码演示

ASP.NET WEB API 是基于 HTTP 谓词进行分发逻辑的,不像 ASP.NET MVC,很容易出现 AmbiguousMatchEception。例如,可以设想一些使用代码片段 3-1 的路由的例子。

如代码片段 3-2 所示的例子,这三个方法都是可以处理相同的 GET 请求,如,/api/orders/1.

代码片段 3-2.

代码片段 3-2. ASP.NET WEB API Controller

 1 public class BadOrdersController : ApiController
 2 {
 3     [HttpGet]
 4     public Order FindById(int id)
 5     {
 6         // 忽略逻辑
 7     }
 8
 9     public Order GetById(int id)
10     {
11         // 忽略逻辑
12     }
13
14     public Order Get(int id)
15     {
16         // 忽略逻辑
17     }
18 }

同时我们需要注意,定义复杂、多等级、嵌套路由的时候,集中式路由变得有点麻烦。考虑如下路由

  • GET myapi.com/api/teams
  • GET myapi.com/api/teams/1
  • GET myapi.com/api/teams/1/players

使用集中式路由,可以在 Controller 中使用如下三个方法;然而,我们必须注意路由之间冲突的问题,因为有两个 GET 方法都是只使用了一个 int 的参数。如代码片段 3-3 所示。有一个特殊的路由指出了 URI 中包含 /players/ 段会被匹配到,而且这个路由定义在通用路由之前。

代码片段 3-3 使用集中式路由配置嵌套路由

 1 public class TeamsController : ApiController
 2 {
 3     public Team GetTeam(int id)
 4     {
 5         // 忽略逻辑
 6     }
 7     public IEnumerable<Team> GetTeams()
 8     {
 9         // 忽略逻辑
10     }
11     public IEnumerable<Player> GetPlayers(int teamId)
12     {
13         // 忽略逻辑
14     }
15 }
16
17
18
19 config.Routes.MapHttpRoute(
20     name: "players",
21     routeTemplate: "api/teams/{teamid}/players",
22     defaults: new {controller = "teams"}
23     );
24 config.Routes.MapHttpRoute(
25 name: "DefaultApi",
26 routeTemplate: "api/{controller}/{id}",
27 defaults: new { id = RouteParameter.Optional }
28 );

集中式路由的主要问题是,特殊路由的定义,仅仅是处理特殊的 Controller 特殊的 Action。通过定义特殊路由并添加到一般路由之前,在人为干预下短路了路由匹配。

这种处理并不是最理想,当应用程序变大之后,会有更复杂的、多层级的路由,可能就要在集中式路由中痛苦的挣扎(路由维护和调试)。更好的选择就是使用直接式路由,下一篇 3-2 定义直接路由,以及后面介绍路由的时候都会涉及直接式路由。

时间: 2024-10-24 13:28:49

集中式路由的相关文章

ELK+Filebeat+Nginx集中式日志解决方案(二)——添加ElasticSearch集群

一.使用说明: Elasticsearch插件:  Elasticsearch常用的几个插件为: # head # 地址  https://github.com/mobz/elasticsearch-head mobz/elasticsearch-head # kopf # 地址  https://github.com/lmenezes/elasticsearch-kopf lmenezes/elasticsearch-kopf # bigdesk # 地址 https://github.com

集中式日志分析平台 - ELK Stack - 安全解决方案 X-Pack

大数据之心 关注 0.6 2017.02.22 15:36* 字数 2158 阅读 16457评论 7喜欢 9 简介 X-Pack 已经作为 Elastic 公司单独的产品线,前身是 Shield, Watcher, Marvel, Graph, 和 reporting,先来说说这几个爸爸是做什么的吧: Shield: 提供对数据的 Password-Protect,以及加密通信.基于角色的权限控制,IP 过滤,审计,可以有效地: 防止未授权的访问:基于 Password-Protect,基于角

ELK+Filebeat 集中式日志解决方案详解

原文:ELK+Filebeat 集中式日志解决方案详解 链接:https://www.ibm.com/developerworks/cn/opensource/os-cn-elk-filebeat/index.html?ca=drs- ELK Stack 简介 ELK 不是一款软件,而是 Elasticsearch.Logstash 和 Kibana 三种软件产品的首字母缩写.这三者都是开源软件,通常配合使用,而且又先后归于 Elastic.co 公司名下,所以被简称为 ELK Stack.根据

SVN 集中式版本控制软件

简介: 目前流行的版本控制软件中,SVN ( 集中式版本控制 ) 算是使用范围更广.且使用时间更早的一款了,现在 git ( 分布式版本控制 ) 更火爆一点. 一.安装svn [[email protected] ~]# yum -y install subversion [[email protected] ~]# svn --version #查看版本号 svn,版本 1.6.11 (r934486) 二.配置svn 1.创建工作目录及版本库 [[email protected] ~]# m

LTE下行物理层传输机制(9)-集中式和分布式资源映射

LTE系统里,RB资源的动态调度是在eNB侧实现的,这里的"RB资源"实际上是特指虚拟RB(Virtual RB)而不是物理RB(Physical RB).VRB是MAC层在调度的时候使用的,属于逻辑上的概念,而PRB是物理层在实际映射RE资源的时候需要使用的,属于实际物理意义上的概念.VRB和PRB之间,存在着不同的映射关系:最简单的映射关系就是VRB的位置和PRB的位置是相同的,它们之间是一一对应的:另外一种复杂点的关系就是VRB和PRB并不是一一对应的,但是可以依赖某种特定的映射

生产环境ehcache迁移到集中式redis集群

原先项目中使用的ehcache分布式缓存,缺点是浪费内存,并且ehcache使用的是jvm进程的内存,因此内存使用很受限制. 还有就是业务中有时希望更新一个业务实体来使对应的缓存失效的场景,这种情况下如果对应业务实体缓存有多台机子那更新实体后更新缓存只能是其中一台,无法全部更新. 基于以上几点,项目希望切换成集中式缓存. 集中式缓存服务端架构是:网易LBS+Twemproxy+redis集群. 缓存客户端使用的是spring Data Redis. 由于Twemproxy代理本身不支持multi

版本控制系统-集中式与分布式的区别

SVN和CVS都是集中式版本控制系统,而Git是分布式版本控制系统 集中式版本控制系统 版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器. 集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟 分布式版本控制系统 分布式版本控制系统没有"中央服务器",每个人的电脑上都是一个完

ZooKeeper场景实践:(2)集中式配置管理

1. 基本介绍 在分布式的环境中,可能会有多个对等的程序读取同样的配置文件,程序可以部署在多台机器上,如果配置采用文件的话,则需要为部署该程序的机器也部署一个配置文件,一旦要修改配置的时候就会非常麻烦,需要修改多个配置文件,而且容易产生不一致. 集中式配置管理的思路是,将配置数据集中发布到ZooKeeper的节点上,供订阅者动态获取数据.实现配置的集中式管理和动态更新.可以简单的理解为配置数据与程序分离. 2. 场景分析 (1).集中式配置管理 通常来说,大部分项目里面都有约定的配置文件格式,如

集中式(CVS、SVN)VS分布式(Git)

集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器.中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆. 集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊. 那分布式版本控制系统与集中式版