C# WebApi 路由机制剖析

前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分。

它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定;

它可以很神秘:你的url可以千变万化,看到一些看似“无厘头”的url,感觉很难理解它如何找到匹配的action,例如/api/user/1/detail,这样一个url可以让你纠结半天。

它可以很晦涩:当面试官提问“请简单分析下MVC路由机制的原理”,你可能事先就准备好了答案,然后噼里啪啦一顿(型如:UrlRoutingModule→Routes→RouteData→RequestContext→Controller),你可能回答很流利,但并不一定能理解这些个对象到底是啥意思。两年前的面试,博主也这样做过。

博主觉得,究竟路由机制在你的印象中处于哪一面,完全取决于你的求知欲。路由机制博大精深,博主并未完全理解,但博主是一个好奇心重的人,总觉得神秘的东西就得探索个究竟。今天,博主根据自己的理解,分享下WebApi里面路由的原理以及使用,如有考虑不周,欢迎园友们指正。

一、MVC和WebApi路由机制比较

1、MVC里面的路由

在MVC里面,默认路由机制是通过url路径去匹配对应的action方法,比如/Home/GetUser这个url,就表示匹配Home这个Controller下面的GetUser方法,这个很好理解,因为在MVC里面定义了一个默认路由,在App_Start文件夹下面有一个RouteConfig.cs文件

public class RouteConfig
 {
  public static void RegisterRoutes(RouteCollection routes)
  {
   routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

   routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Department", action = "Index", id = UrlParameter.Optional }
   );
  }
 }

url: "{controller}/{action}/{id}"这个定义了我们url的规则,{controller}/{action}定义了路由的必须参数,{id}是可选参数

2、WebApi里面的路由

和MVC里面的路由有点不同,WebApi的默认路由是通过http的方法(get/post/put/delete)去匹配对应的action,也就是说webapi的默认路由并不需要指定action的名称。还是来看看它的默认路由配置,我们新建一个Webapi项目,在App_Start文件夹下面自动生成一个WebApiConfig.cs文件:

public static class WebApiConfig
 {
  public static void Register(HttpConfiguration config)
  {
   // Web API 路由
   config.MapHttpAttributeRoutes();

   config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
   );
  }
 }

和MVC类似,routeTemplate: "api/{controller}/{id}"这个定义了路由的模板,api/{controller}是必选参数,{id}是可选参数,那么问题就来了,如果我们的url不包含action的名称,那么如何找到请求的方法呢?我们先来简单看一个例子:

public class OrderController : ApiController
 {
  [HttpGet]
  public object GetAll()
  {
   return "Success";
  }
 }

我们通过url来访问

说明请求能够成功。

为什么这个请求能够成功呢?那是因为,当我们访问http://localhost:21528/api/Order这个路径的时候,webapi的路由引擎会自动去匹配"api/{controller}/{id}"这个模板,于是找到了控制器是Order这个,那么问题来了?它是如何定位到GetAll()这个方法的呢?这里就是和MVC不同的地方,前面说过,Webapi的路由规则是通过http方法去匹配对应的action,那么,我们通过浏览器访问http://localhost:21528/api/Order这个路径的时候,浏览器默认通过url访问的都是get请求,于是webapi的路由引擎就会去找Order这个控制器里面的get请求的方法,由于没有参数,所以自动匹配到了无参数的get请求→GetAll()方法,所以请求成功!

当然,WebApi也支持MVC里面的路由机制,但RestFul风格的服务要求请求的url里面不能包含action,所以,在WebApi里面是并不提倡使用MVC路由机制的。

这是一个最简单的例子,下面我们就来详细看看WebApi里面的路由原理以及使用。

二、WebApi路由基础

1、默认路由

上面我们提到了,新建一个WebApi服务的时候,会自动在WebApiConfig.cs文件里面生成一个默认路由:

 config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
   );

将MapHttpRoute()方法转到定义可以,它有四个重载方法:

分别来看看各个参数的作用:

name:"DefaultApi"→表示此路由的名称,这里只需要保证路由名称不重复就OK了。

routeTemplate: "api/{controller}/{id}"→表示路由的url规则,“api”是固定部分,主要用来标识当前请求的url是一个api服务的接口,区别MVC的路由,当然,这里并不是一定要写成“api”,如果你改成“apiserver”,那么你请求的url里面也需要写成“apiserver”;“{controller}”是控制器的占位符部分,在真实的url里面,该部分对应的是具体的控制器的名称,这个和MVC里面一致;“{id}”是参数的占位符部分,表示参数,一般这个参数都会在default里面设置可选。有了这个路由模板约束请求的url,比如:我们请求的url写成http://localhost:21528/Order,那么肯定是找不到对应的路由的,因为“api”这个参数必选。如果请求的url匹配不到对应的路由,则会向客户端返回一个404的状态码。

defaults: new { id = RouteParameter.Optional }→表示路由的默认值,比如上面的routeTemplate,{controller}和{id}部分都可以设置默认值,比如:defaults改成new { controller="Order", id = RouteParameter.Optional },那么我们请求http://localhost:21528/api这个url仍然能访问到GetAll()方法。

constraints→表示路由约束,一般是一个约束路由模板的正则表达式。比如:我们加入约束条件 constraints: new { id = @"\d+" } ,这就约束必须要匹配一到多个参数id,那么,我们在OrderController里面加入另一个方法

public class OrderController : ApiController
 {

  [HttpGet]
  public object GetAll()
  {
   return "Success";
  }

  [HttpGet]
  public object GetById(int id)
  {
   return "Success" + id ;
  }
 }

我们通过http://localhost:21528/api/Order/2来访问,得到结果:

我们再通过http://localhost:21528/api/Order/a来访问,得到结果:

这个是很好理解的,id的值不匹配正则表达式。

而我们访问http://localhost:21528/api/Order。结果:

竟然连GetAll()方法都找不到了。这是为什么呢?原来就是这个约束在作怪,正则\d+表示匹配一个或多个数字,所以如果请求的url里面没有传数字,则自动匹配不到。所以,如果需要匹配无参的方法,我们把约束改成这样:constraints: new { id = @"\d*" },这个表示匹配0个或多个数字,再来试试

这样就OK了。

上述说了那么多都是约束id的,其实你也可以使用表达式去约束controller、action等等,但一般不常用,我们就不做过多讲解。

2、自定义路由

上面介绍了这么多,都是关于默认路由原理的介绍。除了默认路由,我们也可以自定义路由,我们将WebApiConfig.cs里面改成这样:

public static class WebApiConfig
 {
  public static void Register(HttpConfiguration config)
  {
   // Web API 路由
   config.MapHttpAttributeRoutes();

   //1.默认路由
   config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
   );

   //2.自定义路由一:匹配到action
   config.Routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "actionapi/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
   );

   //3.自定义路由二
   config.Routes.MapHttpRoute(
    name: "TestApi",
    routeTemplate: "testapi/{controller}/{ordertype}/{id}",
    defaults: new { ordertype="aa", id = RouteParameter.Optional }
   );
  }
 }

除了默认路由,我们再加入另外两个自定义路由规则

2.1、自定义路由一:匹配到action

第一个自定义路由很好理解,和MVC里面的路由机制保持一致,只不过为了区别默认路由,我们将路由模板的前缀改成了“actionapi”。我们通过这个自定义的路由也能找到匹配的方法。

比如我们访问http://localhost:21528/actionapi/Order/GetAll,得到结果:

通过action的名称来匹配很好理解,上面的GetAll()是方法名,webApi会默认它就是action的名称,如果你想要方法名和action的名称不一致,你也可以自定义action的名称,这个可以通过特性ActionName来实现,如下:

[ActionName("TestActionName")]
  [HttpGet]
  public object GetById(int id)
  {
   return "Success" + id ;
  }

测试结果:

之前博主演示参数和返回值的时候都是使用的匹配到action的路由。这种用法和MVC里面保持一致,比较好理解,但是WebApi里面并不提倡。

2.2、自定义路由二

第二个自定义路由第一眼看上去是不太好理解的,没关系,我们先来按照它的路由模板规则使用试试。

通过http://localhost:21528/testapi/Order/aa/匹配到GetAll()方法

通过http://localhost:21528/testapi/Order/aa/2匹配到的是GetById()方法

通过http://localhost:21528/testapi/Order/bb/2匹配到的也是GetById()方法。

什么意思呢?也就是说,只要{ordertype}按照路由规则去配置,都能找到对应的方法。这里的{ordertype}有什么用呢?这个要留在下面介绍特性路由的时候来解释。

3、路由原理

有了上面的这些理论作为基础,我们再来分析下WebApi里面路由机制的原理以及路由匹配的过程。由于WebApi的路由机制和MVC有许多的相似性,所以要想理解Webapi的路由机制,有需要搬出来那些asp.net Rounting里面的对象。这个过程有点复杂,博主就根据自己的理解,提提一些主要的过程:

1、WebApi服务启动之后,会执行全局配置文件Global.asax.cs的protected void Application_Start(){GlobalConfiguration.Configure(WebApiConfig.Register);}方法,通过参数委托执行WebApiConfig.cs里面的public static void Register(HttpConfiguration config)这个方法,将所有配置的路由信息添加到HttpRouteCollection对象中(MVC里面可能是RoutCollection对象)保存起来。这里的HttpRoutCollection对象的实例名是Routes,这个很重要,后面要用到。

2、当我们发送请求到WebApi服务器的时候,比如我们访问http://localhost:21528/api/Order这个url的时候,请求首先还是会被UrlRoutingModule监听组件截获,然后,将截获的请求在Routes路由集合中匹配到对应的路由模板(如果匹配不到对应的路由模板,则返回404),得到对应的IHttpRoute对象。IHttpRoute对象是Routes集合里面匹配到的一个实体。

3、将IHttpRoute对象交给当前的请求的上下文对象RequestContext处理,根据IHttpRoute对象里面的url匹配到对应的controller,然后再根据http请求的类型和参数找到对应的action。这样一个请求就能找到对应的方法了。

这个过程本身是非常复杂的,为了简化,博主只选择了最主要的几个过程。更详细的路由机制可以参考:https://www.jb51.net/article/143216.htm。这文章写得有点深,有兴趣的可以看看。

三、WebApi路由过程

通过上文路由的过程,我们知道,一个请求过来之后,路由主要需要经历三个阶段

  • 根据请求的url匹配路由模板
  • 找到控制器
  • 找到action

1、根据请求的url匹配路由模板

这点上面已经说了很多了,主要就是路由模板的配置和url的匹配。在此不作过多说明。

2、找到控制器

如果你反编译路由模块的代码,你会发现控制器的选择主要在IHttpControllerSelector这个接口的SelectController()方法里面处理。

该方法将当前的请求以HttpRequestMessage对象作为参数传入,返回HttpControllerDescriptor对象。这个接口默认由DefaultHttpControllerSelector这个类提供实现

默认实现的方法里面大致的算法机制是:首先在路由字典中找到实际的控制器的名称(比如“Order”),然后在此控制器名称上面加上字符串“Controller”的到请求控制器的全称(比如“OrderController”),最后找到对应的WebApi的Controller,实例化就得到当前请求的控制器对象。

3、找到action

得到了控制器对象之后,Api引擎通过调用IHttpActionSelector这个接口的SelectAction()方法去匹配action。这个过程主要包括:

  1. 解析当前的http请求,得到请求类型(是get、post、put还是delete)
  2. 如果路由模板配置了{action},则直接取到url里面的action名称
  3. 解析请求的参数

如果路由模板配置了{action},那么找到对应的action就很简单,如果没有配置action,则会首先匹配请求类型(get/post/put/delete等),然后匹配请求参数,找到对应的action。我们看个例子,比如,我们的controller加如下一些方法。

public class OrderController : ApiController
 {
  [HttpGet]
  public IHttpActionResult GetAll()
  {
   return Ok<string>("Success");
  }

  [HttpGet]
  public IHttpActionResult GetById(int id)
  {
   return Ok<string>("Success" + id );
  }

  [HttpPost]
  public HttpResponseMessage PostData(int id)
  {
   return Request.CreateResponse();
  }

  [HttpPost]
  public HttpResponseMessage SavaData(ORDER order)
  {
   return Request.CreateResponse();
  }

  [HttpPut]
  public IHttpActionResult Put(int id)
  {
   return Ok();
  }

  [HttpDelete]
  public IHttpActionResult DeleteById(int id)
  {
   return Ok();
  }
 }

匹配action的结果

url http方法 参数 结果
http://localhost:21528/api/Order get none 匹配GetAll方法
http://localhost:21528/api/Order get id 匹配GetById方法
http://localhost:21528/api/Order post order 匹配SavaData方法
http://localhost:21528/api/Order put id 匹配Put方法 
http://localhost:21528/api/Order delete id 匹配DeleteById方法 

WebApi还提供了一个action同时支持多个http方法的请求,使用AcceptVerbs特性去标记。但博主觉得实际使用并不多,有兴趣的可以了解下。

 [AcceptVerbs("GET", "POST")]
  public IHttpActionResult GetById(int id)
  {
   return Ok<string>("Success" + id );
  }

四、WebApi特性路由

上面说了这么多都是路由的一些全局配置。并且存在问题:

如果http请求的方法相同(比如都是post请求),并且请求的参数也相同。这个时候似乎就有点不太好办了,这种情况在实际项目中还是比较多的。比如

public class OrderController : ApiController
 {
  //订单排产
  [HttpPost]
  public void OrderProduct([FromBody]string strPostData)
  {

  }

  //订单取消
  [HttpPost]
  public void OrderCancel([FromBody]string strPostData)
  {

  }

  //订单删除
  [HttpPost]
  public void OrderDelete([FromBody]string strPostData)
  {

  }
 }

这个时候如果使用我们上面讲的Restful风格的路由是解决不了这个问题的。当然,有园友可能就说了,既然这样,我们在路由模板里面加上“{action}”不就搞定了么!这样确实可行。但还是那句话,不提倡。我们来看看如何使用特性路由解决这个问题。

1、启动特性路由

如果要使用特性路由,首先在WebApiConfig.cs的Register方法里面必须先启用特性路由:

public static void Register(HttpConfiguration config)
  {
   // 启用Web API特性路由
   config.MapHttpAttributeRoutes();

   //1.默认路由
   config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
   );
  }

一般情况下,当我们新建一个WebApi项目的时候,会自动在Register方法里面加上这句话。

2、最简单的特性路由

我们在OrderController这个控制器里面加这个action

[Route("Order/SaveData")]
  [HttpPost]
  public HttpResponseMessage SavaData(ORDER order)
  {
   return Request.CreateResponse();
  }

然后我们通过Web里面的Ajax调用

$(function () {
 $.ajax({
  type: 'post',
  url: 'http://localhost:21528/Order/SaveData',
  data: { ID: 2, NO:"aaa"},
  success: function (data, status) {
   alert(data);
  }
 });
});

得到结果:

当然,有人可能就有疑义了,这个特性路由的作用和“{action}”的作用一样嘛,其实不然,如果这里改成[Route("Test/AttrRoute")],然后请求的url换成http://localhost:21528/Test/AttrRoute,一样能找到对应的action。

特性路由的目的是为了解决我们公共路由模板引擎解决不了的问题。一个action定义了特性路由之后,就能通过特性路由上面的路由规则找到。

3、带参数的特性路由

特性路由的规则可以使用“{}”占位符动态传递参数,比如我们有这样一个特性路由

[Route("ordertype/{id}/order")]
  [HttpGet]
  public IHttpActionResult GetById(int id)
  {
   return Ok<string>("Success" + id );
  }

在浏览器里面调用

调用成功。到此,我们就能看懂本文最开始那个看似“怪异”的路由→/api/user/1/detail这个了。

4、参数的约束和默认值

[Route("api/order/{id:int=3}/ordertype")]
  [HttpGet]
  public IHttpActionResult GetById(int id)
  {
   return Ok<string>("Success" + id );
  }

这里约束可变部分{id}的取值必须是int类型。并且默认值是3.

看看效果

不满足约束条件,则直接返回404。

5、路由前缀

在正式项目中,同一个控制器的所有的action的所有特性路由标识一个相同的前缀,这种做法并非必须,但这样能够增加url的可读性。一般的做法是在控制器上面使用特性[RoutePrefix]来标识。

[RoutePrefix("api/order")]
 public class OrderController : ApiController
 {
  [Route("")]
  [HttpGet]
  public IHttpActionResult GetAll()
  {
   return Ok<string>("Success");
  }

  [Route("{id:int}")]
  [HttpGet]
  public IHttpActionResult GetById(int id)
  {
   return Ok<string>("Success" + id );
  }

  [Route("postdata")]
  [HttpPost]
  public HttpResponseMessage PostData(int id)
  {
   return Request.CreateResponse();
  }
 }

那么这个这个控制器的action的时候,都需要/api/order开头,后面接上action特性路由的规则。

五、第一个Restful风格的WebApi服务

通过以上,我们就可以构造一个Restful风格的WebApi服务。

[RoutePrefix("api/AttrOrder")]
 public class OrderController : ApiController
 {
  [Route("")]
  [HttpGet]
  public IHttpActionResult GetAll()
  {
   return Ok<string>("Success");
  }

  [Route("{id:int=3}/OrderDetailById")]
  [HttpGet]
  public IHttpActionResult GetById(int id)
  {
   return Ok<string>("Success" + id );
  }

  [Route("{no}/OrderDetailByNo")]
  [HttpGet]
  public IHttpActionResult GetByNO(string no)
  {
   return Ok<string>("Success" + no);
  }

  [Route("{name}/OrderDetailByName")]
  [HttpGet]
  public IHttpActionResult GetByName(string name)
  {
   return Ok<string>("Success" + name);
  }

  [Route("postdata")]
  [HttpPost]
  public HttpResponseMessage PostData(int id)
  {
   return Request.CreateResponse();
  }

  [Route("Test/AttrRoute")]
  [HttpPost]
  public HttpResponseMessage SavaData(ORDER order)
  {
   return Request.CreateResponse();
  }
 }

得到结果

六、总结

整了这么久终于整完了。如果你觉得本文对你有帮助,请帮忙博主推荐,您的支持是博主最大的动力!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • c#在WebAPI使用Session的方法

    最近在改写WebApp时要将以前用泛型处理例程写的Captcha 改成使用WebApi 来实作机制,在实作的过程中发现使用IRequiresSessionState session也无法使用(context.Session==null) 查过一些文章才发现需要在注册api路由需将RouteHandler 改写,才能使用.以下用ASP.net MVC 4来说明要实作的部分 建立HttpControllerHandler和HttpControllerRouteHandler 并覆写它 public

  • C# WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇C#进阶系列--WebApi接口传参不再困惑:传参详解,这篇博文内容本身很基础,没想到引起很多园友关注,感谢大家的支持.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了下WebApi的传参机制,今天再来看看WebApi里面另一个重要而又基础的知识点:返回值.还是那句话:本篇针对初初使用WebApi的同学们,比较基础,有兴趣的且看看.

  • C# WebApi 异常处理解决方案

    前言:上篇C#进阶系列--WebApi接口传参不再困惑:传参详解介绍了WebApi参数的传递,这篇来看看WebApi里面异常的处理.关于异常处理,作为程序员的我们肯定不陌生,记得在介绍 AOP的时候,我们讲过通过AOP可以统一截获异常.那么在我们的WebApi里面一般是怎么处理异常的呢,今天这一篇,博主带着大家一起来实践下WebApi的异常处理. 为什么说是实践?因为在http://www.asp.net里面已经明确给出WebApi的异常处理机制.光有理论还不够,今天我们还是来试一把.通过实践,

  • C# WebApi CORS跨域问题解决方案

    前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题.本篇主要从实例的角度分享下CORS解决跨域问题一些细节. 一.跨域问题的由来 同源策略:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容. 正是由于这个原因,我们不同项目之间的调用就会被浏览器阻止.比如我们最常见的场景:WebApi作为数据服务层,它是一个单独的项目,我们的MVC项目作为Web的显示层,这个时候我们的MVC里面就

  • 详解C# WebApi 接口测试工具:WebApiTestClient

    前言:这两天在整WebApi的服务,由于调用方是Android客户端,Android开发人员也不懂C#语法,API里面的接口也不能直接给他们看,没办法,只有整个详细一点的文档呗.由于接口个数有点多,每个接口都要详细说明接口作用.参数类型.返回值类型等等,写着写着把博主惹毛了,难道这种文档非要自己写不成?难道网上没有这种文档的展示工具吗?带着这两个问题,在网络世界里寻找,网络世界很奇妙,只要你用心,总能找到或多或少的帮助!这不就被博主找到了这个好用的组件:WebApiTestClient.它对于接

  • C# WebApi 接口传参详解

    前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料.如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方式方法,算是一个笔记,也希望能帮初学者少走弯路.本篇针对初初使用WebApi的同学们,比较基础,有兴趣的且看看. 本篇打算通过get.post.put.delete四种请求方式分别谈谈基础类型(包括int/string/datetime等).实体.数组等类型的参数如何传递. 一.get请求 对于取数据,我们使用最多的应该就是get请求了吧.下面通过

  • C#进阶系列 WebApi身份认证解决方案推荐:Basic基础认证

    前言:最近,讨论到数据库安全的问题,于是就引出了WebApi服务没有加任何验证的问题.也就是说,任何人只要知道了接口的url,都能够模拟http请求去访问我们的服务接口,从而去增删改查数据库,这后果想想都恐怖.经过一番折腾,总算是加上了接口的身份认证,在此记录下,也给需要做身份认证的园友们提供参考. 一.为什么需要身份认证 在前言里面,我们说了,如果没有启用身份认证,那么任何匿名用户只要知道了我们服务的url,就能随意访问我们的服务接口,从而访问或修改数据库. 1.我们不加身份认证,匿名用户可以

  • C# WebApi 路由机制剖析

    前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: 它可以很神秘:你的url可以千变万化,看到一些看似"无厘头"的url,感觉很难理解它如何找到匹配的action,例如/api/user/1/detail,这样一个url可以让你纠结半天. 它可以很晦涩:当面试官提问"请简单分析下MVC路由机制的原理",你可能事先就准备好

  • AngularJS入门教程之路由机制ngRoute实例分析

    本文实例讲述了AngularJS路由机制ngRoute.分享给大家供大家参考,具体如下: 引言 在我们介绍路由之前我们首先谈一下SPA,所以SPA就是我们现在经常说的单页应用single page APP,为了实现无刷新的视图切换我们之前的做法就是利用AJAX从后取出数据然后渲染在前台页面HTML中,但是AJAX有一个致命的缺点就是不能实现浏览器的后退按钮失效,为了解决这个问题我们通常使用hash,监听hashchange事件来进行视图切换,另一个方法是用HTML5的history API,通过

  • Zend Framework框架路由机制代码分析

    本文分析了Zend Framework框架路由机制代码.分享给大家供大家参考,具体如下: 在框架中,有关路由的调用关系为: 1.apache的mod_rewrite模块把请求路由到框架的启动脚本,一般是index.php: 2.前端控制器Zend_Controller_Front通过dispatch函数进行请求分发: 3.路由器Zend_Controller_Router_Rewrite通过route函数处理路由,对路由器中已有的路由规则,按照加入顺序的逆序(类似于栈,后进先出)对每个route

  • ThinkPHP路由机制简介

    本文实例讲述了ThinkPHP路由机制.分享给大家供大家参考,具体如下: ThinkPHP 支持 URL 路由功能,要启用路由功能,需要设置ROUTER_ON参数为true.开启路由功能后,系统会自动进行路由检测,如果在路由定义里面找到和当前URL匹配的路由名称,就会进行路由解析和重定向.路由功能需要定义路由定义文件,位于项目的配置目录下面,文件名为 routes.php 定义格式: Return Array( 'RouteName'=>array('模块名称','操作名称','参数定义','额

  • flutter 路由机制的实现

    目录 实现基础 _routeNamed _flushHistoryUpdates add push pop remove 总结 整个 flutter 应用的运行都只是基于原生应用中的一个 view,比如 android 中的 FlutterView,flutter 中的页面切换依赖于它的路由机制,也就是以 Navigator 为中心的一套路由功能,使得它能够完成与原生类似且能够自定义的页面切换效果. 下面将介绍 flutter 中的路由实现原理,包括初始化时的页面加载.切换页面的底层机制等. 实

  • Ingress七层路由机制实现域名的方式访问k8s

    Ingress概念: 通俗来讲:Ingress和之前说的Service.Deployment一样,也是一个k8s的资源类型:Ingress用于实现域名的方式访问k8s的内部应用,Service可能更适于服务间访问. 这东西我们使用的k8s官方维护的本版,另外nginx官方也有一个版本,怎么用看个人. Ingress支持多种方案:包括 Nginx.Haproxy.Traefik.istio等:在实际中Ingress上面可能还有一层公司的硬件层代理. 大概的流程图如下: 创建一个Ingress: 这

  • NodeJS仿WebApi路由示例

    用过WebApi或Asp.net MVC的都知道微软的路由设计得非常好,十分方便,也十分灵活.虽然个人看来是有的太灵活了,team内的不同开发很容易使用不同的路由方式而显得有点混乱. 不过这不是重点,我在做Node项目的时候就觉得不停的用use(...)来指定路由路径很烦人,所以用Typescript写了这个基于Koa和Koa-router的路由插件,可以简单实现一些类似WebApi的路由功能. 目标是和WebApi一样: 1.加入的controller会自动加入路由. 2.也可以通过path(

  • RabbitMQ消息确认机制剖析

    目录 前言 消息确认 基本流程 消息确认模式 ConfirmCallback确认模式 ReturnCallback退回模式 消息发送者确认 消息接收者确认 basicAck模式 basicNack模式 basicReject模式 测试 解决办法 消费者确认失败 总结 前言 上一章讲解了RabbitMq的三种Exchange消息发送的模式,但是在默认情况下RabbitMQ并不能保证消息是否发送成功,以及是否能被成功消费,为了保证消息在传递过程中不丢失,需要对消息进行确认机制,来提高消息的可靠性.

  • angular学习之ngRoute路由机制

    ngRoute简介 路由是AngularJS很重要的一环,它可以把你项目的页面串联起来,构成一个项目,常用的路由有ngRoute和ui-route,我这里先讲ngRoute.ngRoute是一个Module,提供路由和深层链接所需的服务和指令. 注意一点,和之前的文章不一样,使用ngRoute之前你需要引入另外一个js文件angular-route.js: <script src="script/angular.min.js"></script> <scr

  • Redis中主键失效的原理及实现机制剖析

    作为一种定期清理无效数据的重要机制,主键失效存在于大多数缓存系统中,Redis 也不例外.在 Redis 提供的诸多命令中,EXPIRE.EXPIREAT.PEXPIRE.PEXPIREAT 以及 SETEX 和 PSETEX 均可以用来设置一条 Key-Value 对的失效时间,而一条 Key-Value 对一旦被关联了失效时间就会在到期后自动删除(或者说变得无法访问更为准确).可以说,主键失效这个概念还是比较容易理解的,但是在具体实现到 Redis 中又是如何呢?最近本博主就对 Redis

随机推荐