一个具有缓存数据功能的HttpWebRequest工具类
背景:一个公共站点中的数据,供其它子站点共享,为了提高性能,简单实现了Http 1.1的缓存功能
特点:可以缓存Html数据到内存中;缓存具有过期时间;缓存过期后,通过再确认的方式来决定是否更新缓存;浏览器刷新后,无论缓存是否过期都会强制再验证;
未实现的包括:不能通过no-store来强制清空缓存,缓存再确认时没有验证Etag
/// <summary>
/// 启用缓存的HttpRequest
/// </summary>
public static class CacheHttpRequest
{
private static Dictionary<String,HtmlLocalCache> _caches = new Dictionary<string,HtmlLocalCache>();
private static object AddCacheLock = new Object(); public static String GetHtml(String url)
{
HtmlLocalCache cache;
//如果有缓存,且缓存尚未过期,或不需要重新验证,则直接返回内容
if(_caches.TryGetValue(url,out cache))
{
if(!cache.NeedRevalidate())
{
return cache.Html;
}
} var webRequest = (HttpWebRequest)WebRequest.Create(url);
//如果有缓存,且需要重新验证,则设置它的IMS信息,为了简便,这里没有验证ETag
if(cache != null)
{
webRequest.IfModifiedSince = cache.LastModified;
} HttpWebResponse response = null;
Stream stream = null;
try
{
response = webRequest.GetHttpResponse();
//如果服务器资源没有修改,则修改缓存信息后,返回内容
if (cache != null && response.StatusCode == HttpStatusCode.NotModified)
{
cache.UpdateCacheProperty(response);
return cache.Html;
} //服务器资源已经修改,重新获取内容,并放入缓存
if (response.StatusCode == HttpStatusCode.OK)
{
stream = response.GetResponseStream();
TextReader reader = new StreamReader(stream); cache = new HtmlLocalCache();
cache.SetCacheProperty(response);
cache.Html = reader.ReadToEnd();
AddHtmlToCache(url, cache); return cache.Html;
} return "";
}
finally
{
if(response != null) response.Close();
if(stream != null) stream.Dispose();
}
} private static void AddHtmlToCache(string url, HtmlLocalCache cache)
{
lock (AddCacheLock)
{
if (!_caches.ContainsKey(url))
{
_caches.Add(url, cache);
}
}
} /// <summary>
/// 缓存数据
/// </summary>
private class HtmlLocalCache
{
public String Html;
public DateTime LastModified;
public DateTime? ExpiredTime;
public DateTime HttpDate;
private Object _updateLock = new Object(); public Boolean NeedRevalidate()
{
if (ExpiredTime == null) return true;
if (FromRefresh()) return true;
return DateTime.Now > ExpiredTime;
} /// <summary>
/// 看是否是页面刷新
/// </summary>
/// <returns></returns>
private static bool FromRefresh()
{
string requestCacheControl = HttpContext.Current.Request.Headers["Cache-Control"];
String pragma = HttpContext.Current.Request.Headers["Pragma"];
Boolean isRefresh = (pragma != null &&
pragma.Equals("no-cache", StringComparison.OrdinalIgnoreCase)
|| requestCacheControl != null &&
requestCacheControl.Equals("no-cache", StringComparison.OrdinalIgnoreCase)); if (isRefresh) return true;
return false;
} private void SetCacheControl(string cacheControl)
{
if (String.IsNullOrEmpty(cacheControl)) return; if(cacheControl.Contains("max-age"))
{
Double maxAge = Double.Parse(cacheControl.Substring(cacheControl.IndexOf('=')+));
ExpiredTime = HttpDate.AddSeconds(maxAge);
}
} public void SetCacheProperty(HttpWebResponse response)
{
LastModified = response.LastModified;
HttpDate = Convert.ToDateTime(response.Headers["Date"]);
//使用cache-control来控制缓存过期时间,不使用expires
SetCacheControl(response.Headers["Cache-Control"]);
} public void UpdateCacheProperty(HttpWebResponse response)
{
lock (_updateLock)
{
SetCacheProperty(response);
}
}
}
}
一个具有缓存数据功能的HttpWebRequest工具类的更多相关文章
- Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源,BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 各种后台管理系统
Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 家庭理财系统 各种后 ...
- 推荐一个同步Mysql数据到Elasticsearch的工具
把Mysql的数据同步到Elasticsearch是个很常见的需求,但在Github里找到的同步工具用起来或多或少都有些别扭. 例如:某记录内容为"aaa|bbb|ccc",将其按 ...
- 浅析Android Camera开发中的三个尺寸和三种变形 (贡献一个自适配Picturesize和Previewsize的工具类)
转至 (http://blog.csdn.net/yanzi1225627/article/details/17652643) 经常听人问Camera开发中,各种变形问题,今天有空就在此梳理总结下. ...
- 下载数据到Excel,工具类
使用反射将model数据下载到Excel中 package test.upload.utils; import java.lang.reflect.Method; import java.math.B ...
- Android 开发 记录一个DP、PX、SP转换工具类
public class UnitConversionUtil { /** * 根据手机分辨率从DP转成PX * @param context * @param dpValue * @return * ...
- 一个HttpWebRequest工具类
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.N ...
- 一个java创建,删除,构建Jenkins等功能的JenkinsUtil工具类
package com.vip.webpagetest.utils; import java.io.InputStream;import java.util.ArrayList;import java ...
- 一个很好的通用 excel 导出工具类
此类用主要 jxl +注解+流 实现扩展性很强,jxl性能会比poi好一点,值得我们学习. package oa.common.utils; import java.io.OutputStream; ...
- 封装一个List集合和datatable相互转换的工具类(可对指定列进行重命名并且指定输出列)
/// <summary> /// List转换为DataTable对象 /// </summary> public class ListTranTableModel { // ...
随机推荐
- 20155227《网络对抗》Exp7 网络欺诈防范
20155227<网络对抗>Exp7 网络欺诈防范 实践内容(3.5分) 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 (1)简单应用SET工具建 ...
- # 2017-2018-2 20155319《网络对抗技术》Exp9 :Web安全基础
2017-2018-2 20155319<网络对抗技术>Exp9 :Web安全基础 实践过程 webgoat准备 从GitHub上下载jar包(老师的虚拟机中有 无需下载) 拷贝到本地,并 ...
- TreeSet排序相关总结
java的集合这一块在工作中用得还比较多,有些东西老是忘,因此在此记录下来. TreeSet原理 1.特点 TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺 ...
- WPF编程,通过Double Animation同时动态缩放和旋转控件的一种方法。
原文:WPF编程,通过Double Animation同时动态缩放和旋转控件的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_4330793 ...
- Photoshop CS4破解方法
先在网上下载Photoshop CS4的版本,安装后按如下步骤操作即可. 激活码: 1330-1082-3503-2270-3738-6738 1330-1776-8671-6289-7706-291 ...
- [hdu5503]EarthCup[霍尔定理]
题意 一共 \(n\) 只球队,两两之间会进行一场比赛,赢得一分输不得分,给出每只球队最后的得分,问能否构造每场比赛的输赢情况使得得分成立.多组数据 \(T\le 10,n\le 5\times 10 ...
- 利用matlab写一个简单的拉普拉斯变换提取图像边缘
可以证明,最简单的各向同性微分算子是拉普拉斯算子.一个二维图像函数 f(x,y) 的拉普拉斯算子定义为 其中,在 x 方向可近似为 同理,在 y 方向上可近似为 于是 我们得到满足以上三个 ...
- 树莓派Raspberry Pi微改款,Model B 3+规格探析
18年3月树莓派基金会推出了ModelB 3+版的新款树莓派单板计算机.从编号数字上看,3+仅是3的再提升,在规格上有小幅异动,究竟改进或提升了哪些部分,本文将对此进行探讨. 树莓派版本观察 从过往的 ...
- error: Build input file cannot be found: '*******/node_modules/react-native/Libraries/WebSocket/libfishhook.a' 问题解决记录
解决了刚才的'config.h' file not found问题,本以为就可以顺畅的跑起来,谁知道又被恶心到了,Build input file cannot be found!!! 问题: err ...
- 《Linux内核--分析Linux内核创建一个新进程的过程 》 20135311傅冬菁
20135311傅冬菁 分析Linux内核创建一个新进程的过程 一.学习内容 进程控制块——PCB task_struct数据结构 PCB task_struct中包含: 进程状态.进程打开的文件. ...