Rails源代码分析(19):ActionController::Caching(3) PageCache

1 介绍和应用
Page级别的cache,是用于cache整个action output保存为一个html,不需要经过action pack,
这是最快的缓存,不需要经过生成页面的过程,但是,这个只适用于所有用户察看的都是一样的页面,
这种缓存对CMS系统非常有效。
  1.        class WeblogController < ActionController::Base
  2.          caches_page :show:new
  3.        end
将会产生 weblog/show/5.html 或者 weblog/new.html 的缓存文件

可以采用以下方法使之过期:
  1.        class WeblogController < ActionController::Base
  2.          def update
  3.            List.update(params[:list][:id], params[:list])
  4.            expire_page :action => "show":id => params[:list][:id]
  5.            redirect_to :action => "show":id => params[:list][:id]
  6.          end
  7.        end
另外可以采用Sweepers来清理

设置缓存目录:
Base.page_cache_directory = "/document/root"
默认设置是public目录(RAILS_ROOT + "/public")

设置缓存的扩展名
Base.page_cache_extension

2 源代码分析

  1.       def self.included(base) #:nodoc:
  2.         base.extend(ClassMethods)
  3.         base.class_eval do
  4.      # 缓存目录默认为public
  5.           @@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
  6.           cattr_accessor :page_cache_directory
  7.           # 页面扩展默认为html
  8.      @@page_cache_extension = '.html'
  9.           cattr_accessor :page_cache_extension
  10.         end
  11.       end
模块的实现,类方法:
  1.       module ClassMethods
  2.         # Expires the page that was cached with the +path+ as a key. Example:
  3.         #   expire_page "/lists/show"
  4.         def expire_page(path)
  5.           return unless perform_caching
  6.           # 删除文件
  7.      benchmark "Expired page: #{page_cache_file(path)}" do
  8.             File.delete(page_cache_path(path)) if File.exist?(page_cache_path(path))
  9.           end
  10.         end
  11.         # Manually cache the +content+ in the key determined by +path+. Example:
  12.         #   cache_page "I'm the cached content", "/lists/show"
  13.         def cache_page(content, path) # nnd,取了这么一个名字跟caches_page很容易混起来,真受不了
  14.           return unless perform_caching
  15.           benchmark "Cached page: #{page_cache_file(path)}" do
  16.           #创建目录写文件
  17.             FileUtils.makedirs(File.dirname(page_cache_path(path)))
  18.             File.open(page_cache_path(path), "wb+") { |f| f.write(content) }
  19.           end
  20.         end
  21.         # Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that
  22.         # matches the triggering url.
  23.         #
  24.         # Usage:
  25.         #
  26.         #   # cache the index action
  27.         #   caches_page :index
  28.         #
  29.         #   # cache the index action except for JSON requests
  30.         #   caches_page :index, :if => Proc.new { |c| !c.request.format.json? }
  31.         def caches_page(*actions)
  32.           return unless perform_caching
  33.           options = actions.extract_options!
  34.      # 利用after filter来实现
  35.      # 这个after filter是前面提到的filter使用中的直接传proc的方式,而c就是controller
  36.           after_filter({:only => actions}.merge(options)) { |c| c.cache_page }
  37.         end
  38.         private
  39.           def page_cache_file(path)
  40.             name = (path.empty? || path == "/") ? "/index" : URI.unescape(path.chomp('/')) #获取文件名
  41.             name << page_cache_extension unless (name.split('/').last || name).include? '.' #获取名字
  42.             return name
  43.           end
  44.           def page_cache_path(path) #获取cache的文件地址
  45.             page_cache_directory + page_cache_file(path)
  46.           end
  47.       end

controller的实例方法:
  1.       # Expires the page that was cached with the +options+ as a key. Example:
  2.       #   expire_page :controller => "lists", :action => "show"
  3.       def expire_page(options = {})
  4.         return unless perform_caching
  5.         if options.is_a?(Hash)
  6.      # 如果是一组方法,依次过期
  7.           if options[:action].is_a?(Array)
  8.             options[:action].dup.each do |action|
  9.               self.class.expire_page(url_for(options.merge(:only_path => true:skip_relative_url_root => true:action => action)))
  10.             end
  11.           else
  12.       # 如果是一个方法,过期
  13.             self.class.expire_page(url_for(options.merge(:only_path => true:skip_relative_url_root => true)))
  14.           end
  15.         else
  16.      # 如果options不是hash
  17.           self.class.expire_page(options)
  18.         end
  19.       end
  20.       # Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of response.body is used
  21.       # If no options are provided, the requested url is used. Example:
  22.       #   cache_page "I'm the cached content", :controller => "lists", :action => "show"
  23.       def cache_page(content = nil, options = nil)
  24.         return unless perform_caching && caching_allowed
  25.         # 根据options计算路径,默认为request.path
  26.     path = case options
  27.           when Hash
  28.             url_for(options.merge(:only_path => true:skip_relative_url_root => true:format => params[:format]))
  29.           when String
  30.             options
  31.           else
  32.             request.path
  33.         end
  34.         self.class.cache_page(content || response.body, path)
  35.       end
  36.       private
  37.         def caching_allowed
  38.      # 如果是get方法,如果是OK状态
  39.           request.get? && response.headers['Status'].to_i == 200
  40.         end
这里就有疑问:
rails怎么确定cache在什么时候去读取呢?

rails接受到请求后会先去public下查找相应的资源,
如果有那么会直接返回,
如果没有才会进入action_pack。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值