`
fantaxy025025
  • 浏览: 1329242 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Rails源码阅读(六)ActionController::Dispatcher_用户请求在rails中的处理流程(1)

 
阅读更多

Rails源码阅读(六)ActionController::Dispatcher和接下来的处理流程_用户请求在rails中的处理流程(1)

--紧接这一节:Rails源码阅读(二)_script/server

前面的分析小回顾:

用户的请求,经过rack的栈后,终于到了rails的ActionController::Dispatcher,这也是一个rack的实现,因此,请求会去调用ActionController::Dispatcher的call方法,并且应该返回一个样子的数组:[status, header, body]

 

=ActionController::Dispatcher的new代码:

    # DEPRECATE: Remove arguments, since they are only used by CGI
    def initialize(output = $stdout, request = nil, response = nil)
      @output = output
      build_middleware_stack if @@cache_classes 
    end

#1 @@cache_classes 用处

 

@@cache_classes = true #这个是默认的,但是在develop环境中,设置为false

如果设置为false的话,每次请求都会重新加载???,这个在开发环境非常有用。

 

#2 build_middleware_stack做什么

    private
      def build_middleware_stack
        @app = @@middleware.build(lambda { |env| self.dup._call(env) })
      end

@@middleware从字面上也可以看出来,是存储middleware们的。

@@middleware是MiddlewareStack的一个实例

 

@@middleware的赋值代码:

    cattr_accessor :middleware
    self.middleware = MiddlewareStack.new do |middleware|
      middlewares = File.join(File.dirname(__FILE__), "middlewares.rb") 
      middleware.instance_eval(File.read(middlewares))
    end

# middlewares.rb文件内存储的是需要固定使用的rack们

use "Rack::Lock", :if => lambda {

  !ActionController::Base.allow_concurrency

}

use "ActionController::Failsafe"

use lambda { ActionController::Base.session_store },

    lambda { ActionController::Base.session_options }

use "ActionController::ParamsParser"

use "Rack::MethodOverride"

use "Rack::Head"

use "ActionController::StringCoercion"

# @@middleware是MiddlewareStack的一个实例,这个实例的build方法返回一个rack,这个rack是已经排列好stack顺序的rack

    def build(app)
      active.reverse.inject(app) { |a, e| e.build(a) } #看了后面就知道这里为啥用reverse了
    end

每一个在middlewares.rb里的rack,都会执行下面的方法

      def build(app)
        if block
          klass.new(app, *build_args, &block)
        else
          klass.new(app, *build_args)
        end
      end 

这样的结果是:每一个在middlewares.rb文件里的rack,都会new一个实例出来

 

build的结果:组成了一个很好的rack栈,先new的在顶端,app在最底端。返回的是顶端的实例。

是这样做到的:

    #ActionController::ParamsParser.new和.call的代码是这样的:
    def initialize(app)
      @app = app
    end
 
    def call(env) #先执行自己
      if params = parse_formatted_parameters(env)
        env["action_controller.request.request_parameters"] = params
      end
      @app.call(env) #后执行别人,即new的时候传入的app
    end

这样最后实现了目的:new的时候,持有了下一层的句柄@app,先执行自己的代码,最后执行@app.call,这样就实现了过滤栈的效果。这种方式不错~~  

 

 

@app = @@middleware.build(lambda { |env| self.dup._call(env) })在这里传入的一个block,会在放在stack的最底端。

@app就是最终的rack栈的句柄

有个小问题:self即inner_app = ActionController::Dispatcher.new对象,为啥dup呢???

 

分析完了new代码,接下来执行的应该是call代码:

=call的代码:

    def call(env)
      if @@cache_classes
        @app.call(env)
      else
        Reloader.run do
          # When class reloading is turned on, we will want to rebuild the
          # middleware stack every time we process a request. If we don't
          # rebuild the middleware stack, then the stack may contain references
          # to old classes metal classes, which will b0rk class reloading.
          build_middleware_stack
          @app.call(env)
        end
      end
    end

这里解释了在develop环境下时,@@cache_classes是关闭的,走else分支,每个请求都重新build rack-stack。

请求执行的过程为:

当有一个请求来的时候,会执行call,

执行call的时候,会build出一个rack栈,

先执行之前加入到rack栈中的rack,最后执行block,代码为:self.dup._call(env)

    #_call的代码:
    def _call(env)
      @env = env
      dispatch
    end

这里才进入主操作:就是dispatch方法!!

    def dispatch
      begin
        run_callbacks :before_dispatch
        Routing::Routes.call(@env)
      rescue Exception => exception
        if controller ||= (::ApplicationController rescue Base)
          controller.call_with_exception(@env, exception).to_a
        else
          raise exception
        end
      ensure
        run_callbacks :after_dispatch, :enumerator => :reverse_each
      end
    end

在这里,dispach做的真正的操作交给了Routing::Routes.call(@env) 

 

 

总结:

ActionController::Dispatcher这个rack的call操作做了哪些操作:

#1 根据配置build出了一个rack栈(并没有用栈,怎么实现的上面讲了)

#2 在develop中,@@cache_classes是false,每次请求都重新build一次rack-stack

#3 dispach操作,交给了ActionController::Routing::Routes.call(@env)

 

 

 

====结束====

===           ===

==                ==

=                     =

|                       |

 

分享到:
评论

相关推荐

    rails-exporter-源码.rar

    在 Rails 应用中,模型负责数据操作,视图负责展示,控制器则作为两者之间的桥梁,处理用户请求并协调数据展示。 二、Exporter 概念 数据导出是 web 应用中常见的需求,例如生成 CSV、Excel 或 PDF 文件供用户下载...

    Rails的精简版本Rails::API.zip

    Rails::API 是 Rails 的精简版本,针对不需要使用完整 Rails 功能的开发者。 Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails ...

    Rails项目源代码

    在这个图片分享项目中,模型可能包括`User`(用户)、`Image`(图片)等,视图则展示图片和用户界面,控制器处理用户的请求和响应。 3. **Sign标签**: "Sign"可能是项目的登录或注册模块,它涉及用户认证和授权。...

    Rails进行敏捷Web开发(所有版本的源码rails3.0-4.0)

    1. Rails 3.0: Rails 3是重大升级,引入了ActionController::Metal,这是一个轻量级的控制器,用于提高性能。同时,它引入了多路由引擎支持,如Rack中间件,使得与其他Web服务器的集成更加容易。此外,ActiveRecord...

    Rails中应用Ext.tree:以中国的省市地区三级联动选择为例

    在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种用户交互功能,例如三级联动选择,这在处理如中国省市区这样的地理数据时尤其常见。这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为...

    Rails上的API:使用Rails构建REST APIAPIs on Rails: Building REST APIs with Rails

    在本篇内容中,我们将深入探讨如何利用Ruby on Rails(简称Rails)这一强大的Web应用程序框架来构建可伸缩且易于维护的RESTful API。Rails以其简洁优雅的语法、高效的开发速度以及良好的社区支持而闻名,这使得它...

    weixin_rails_middleware, 微信集成 ruby weixin_rails_middleware for integration weixin..zip

    `weixin_rails_middleware` 是基于 Ruby 的 Rack 技术构建的,它能够插入到 Rails 应用的请求处理流程中。当收到微信服务器发来的请求时,中间件会自动处理这些请求,如验证签名、解析XML数据,并提供相应的响应。 ...

    bhl_rails_solr-源码.rar

    4. **错误处理**:在与Solr通信过程中,可能会遇到网络故障、索引错误等问题,源码中应有相应的异常处理机制,确保应用的健壮性。 此外,深入研究源码,我们可以学习到以下几点: 1. **Solr与Rails的交互机制**:...

    ruby on rails 教程源码

    在Rails中,`sample_app-master`可能是一个示例应用程序的主目录,它包含了完整的项目结构。让我们详细探讨一下Rails项目的基本组成部分和关键概念: 1. **Gemfile**: 这个文件定义了项目所需的外部库(称为Gems)...

    Ruby on Rails的启动时间助推器,可阻止加载整个流血路线,因此应用程序可以快速启动:sign_of_the_horns:-Ruby开发

    延迟加载整个血腥路由,因此应用程序可以快速启动:sign_of_the_horns:route_lazy_routes route_lazy_routes是一个邪恶的Rails插件,它延迟加载整个血腥路由,直到服务器获得第一个请求,因此应用程序可以旋转快起来...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    - **配置**:在`config/routes.rb`文件中添加新的路由规则,例如`get 'new_route' => 'controller#action'`。 - **效果**:这将在应用中增加一个新的URL路径,指向指定控制器的动作。 #### 七、渲染视图 - **方法*...

    simple_workflow:添加绕路并返回到Ruby On Rails中先前工作流的方法

    对Rails的扩展,以允许使用绕道而行,返回简单的工作流浏览器导航。 特征 将您的“ link_to”行切换为“ detour_to”,并将您的控制器“ redirect_to”切换为“ back_or_redirect_to”,以允许用户从其来访者返回。 ...

    rails_admin_acts_as_list:rails_admin插件以对记录进行排序

    在您的config/initializers/rails_admin.rb初始化程序中添加配置: RailsAdmin . config do | config | config . model Post do list do sort_by :position # Add Default sorting sort_reverse false # sort p

    For-Rails-Beginners::Japanese_symbol_for_beginner:Ruby on Rails的初学者有福了

    Model负责处理数据和业务逻辑,View负责展示用户界面,Controller作为两者之间的桥梁,处理用户请求并协调Model和View。 3. **路由(Routing)**:Rails的路由系统将HTTP请求映射到相应的控制器方法。通过配置...

    todds_blog:Basic Rails博客:man_technologist::railway_track::writing_hand:

    持续移动且不破坏事物 ‍:factory: :building_construction: :construction: :construction_worker: 正在建设中-请稍后再回来!

    rails_admin_nested_set:用于编辑rails_admin的嵌套集的界面

    主存储库已移至gitlab,所有新代码将在其中: 它的外观和感觉完全类似于但是使用了jQuery Nested Sortable和或而不是Nestable和Ancestry 。 与和awesome_nested_set一起使用。 奖励功能: 对带有rails_admin_...

    vite_rails:Rails中的:high_voltage:Vite.js,为您JavaScript体验带来欢乐

    允许您使用为Rails应用程序的前端供电。 是将前端工具像Ruby一样进行编程,纯属喜悦! :smiling_face_with_heart-eyes: 或在运行的检查。 产品特点 :high_voltage: :light_bulb: 即时服务器启动 :high_voltage: ...

    rails_best_practices:Rails项目的代码度量工具

    在Rails应用程序的根目录中,运行: rails_best_practices . 或用于HTML输出: rails_best_practices -f html . 默认情况下,rails_best_practices将解析vendor , spec , test和features目录中的代码。 排除目录...

    shopping_card_rails-源码.rar

    1. **模型(Models)**:在Rails中,模型负责处理业务逻辑和数据操作。购物车系统可能包含如`Product`(产品)、`Cart`(购物车)和`CartItem`(购物车内项)等模型。`Product`存储商品信息,`Cart`管理用户的购物车...

    基于ruby on rails开发示例源码

    在Rails中,`模型`负责处理数据和业务逻辑,`视图`负责展示用户界面,而`控制器`则作为模型和视图之间的桥梁,处理用户请求并协调它们之间的交互。Rails的许多特性,如ActiveRecord(ORM)、ActiveModel、Action...

Global site tag (gtag.js) - Google Analytics