当前位置: 移动技术网 > IT编程>开发语言>.net > CreateOutputCachedItemKey 缓存key的创建

CreateOutputCachedItemKey 缓存key的创建

2017年12月12日  | 移动技术网IT编程  | 我要评论

专业舞狮,弥海砂h,南通大学白陆

有关outputcache的相关资料大家可以查看 outputcacheprovider outputcache的一点点认识 ,我们还是复习一下outputcache内容,outputcache 的处理是在outputcachemodule类中注册resolverequestcache、updaterequestcache这2个方法,一个 用于获取一个用于设置缓存。缓存内容分为两部分,一部分为缓存策略cachedvary,一部分为缓存数据cachedrawresponse,一个页面 缓存策略只有一个cachedvary,但是它却可以有多个缓存内容cachedrawresponse。缓存内容的获取和设置主要是依赖于httpresponse的getsnapshot() usesnapshot(httprawresponse rawresponse, bool sendbody)方法。一般我们的缓 存都是要占用存储空间的尽量减少缓存内容的副本是非常重要的,那么我们现在就来看看缓存key是如何创建的,key的创建取决于 createoutputcacheditemkey方法。createoutputcacheditemkey方法的内容还是比较复杂的,现在让我们一 起来看看它的具体实现吧。

createoutputcacheditemkey方法又是如何调用的了,创建缓存策略key的代码:this.createoutputcacheditemkey(context, null);创建缓存key的代码:this.createoutputcacheditemkey(context, cachedvary)区别就在于参数cachedvary 的值一个为null,一个是真正的cachedvary 实例。我这里的代码是通过reflector.exe反编译得到,感觉和真实的代码有点差别,不过逻辑上是一样的。
我还是以一个实际的例子来变解析边说明,我这里是用asp.net mvc建立的一个demo。请求url:http://localhost:7503/home/index 那么path就应该是:home/index
首先我们的可以需要区分我们的请求是get还是post,post以a1打头,否则已a2打头,紧接着追加当前的path:
复制代码 代码如下:

if (verb == httpverb.post)
{
builder = new stringbuilder("a1", path.length + "a1".length);
}
else
{
builder = new stringbuilder("a2", path.length + "a2".length);
}
builder.append(cultureinfo.invariantculture.textinfo.tolower(path));

到这个时候我们的缓存策略key及确定的,我这里的策略key为:a2/home/index
如果我们的cachedvary不为null则继续执行:
复制代码 代码如下:

for (int i = 0; i <= 2; i++)
{
int num;
string[] array = null;
namevaluecollection servervarswithoutdemand = null;
bool flag = false;
switch (i)
{
case 0:
builder.append("h");
array = cachedvary._headers;
if (array != null)
{
servervarswithoutdemand = request.getservervarswithoutdemand();
}
break;
case 1:
builder.append("q");
array = cachedvary._params;
if (request.hasquerystring && ((array != null) || cachedvary._varybyallparams))
{
servervarswithoutdemand = request.querystring;
flag = cachedvary._varybyallparams;
}
break;
default:
builder.append("f");
if (verb == httpverb.post)
{
array = cachedvary._params;
if (request.hasform && ((array != null) || cachedvary._varybyallparams))
{
servervarswithoutdemand = request.form;
flag = cachedvary._varybyallparams;
}
}
break;
}
if (flag && (servervarswithoutdemand.count > 0))
{
array = servervarswithoutdemand.allkeys;
num = array.length - 1;
while (num >= 0)
{
if (array[num] != null)
{
array[num] = cultureinfo.invariantculture.textinfo.tolower(array[num]);
}
num--;
}
array.sort(array, invariantcomparer.default);
}
if (array != null)
{
num = 0;
int length = array.length;
while (num < length)
{
string str = array[num];
if (servervarswithoutdemand == null)
{
varybycustomstring = "+n+";
}
else
{
varybycustomstring = servervarswithoutdemand[str];
if (varybycustomstring == null)
{
varybycustomstring = "+n+";
}
}
builder.append("n");
builder.append(str);
builder.append("v");
builder.append(varybycustomstring);
num++;
}
}
}

这段代码说白了就是给key值追加hqf3个字符,这个循环首先处理服务器的数据,
array = cachedvary._headers;
servervarswithoutdemand = request.getservervarswithoutdemand();
其次是处理querystring数据:
array = cachedvary._params;
servervarswithoutdemand = request.querystring;
最后处理form数据
array = cachedvary._params;
servervarswithoutdemand = request.form;
servervarswithoutdemand是namevaluecollection 类型的数据,这里循环servervarswithoutdemand里面的每个key,每个key对应的追加字符串为n+key+v+value,如果value是null则从新赋值为“+n+”,可以看见不同的请求这里的key及有所不同了。在querystring和form时这里的servervarswithoutdemand的取值与
cachedvary._varybyallparams有关,cachedvary的创建是在outputcachemodule 的onleave方法中:
vary = new cachedvary(varybycontentencodings, varybyheaders, varybyparams, varybyallparams, currentsettings.varybycustom);
varybyallparams的取值如下:
复制代码 代码如下:

bool varybyallparams = false;
if (varybyparams != null)
{
varybyallparams = (varybyparams.length == 1) && (varybyparams[0] == "*");
}

可见varybyallparams基本都是false,只有varybyparams有且紧有一个元素并且为*时,varybyallparams才为true,varybyallparams为false时这里的servervarswithoutdemand取值为getservervarswithoutdemand方法,与我们的querystring、form3没什么关系。getservervarswithoutdemand()方法大家可能都不怎么熟悉,我们来看看它的定义:
复制代码 代码如下:

internal namevaluecollection getservervarswithoutdemand()
{
return this.getservervars();
}

对这个方法不了解不要紧,我们有一个servervariables(获取 web 服务器变量的集合)属性和他相似:
复制代码 代码如下:

public namevaluecollection servervariables
{
get
{
if (httpruntime.hasaspnethostingpermission(aspnethostingpermissionlevel.low))
{
return this.getservervars();
}
return this.getservervarswithdemand();
}
}

其中getservervarswithdemand方法也是调用getservervars方法。现在servervarswithoutdemand的数据我们也搞清楚了。
builder.append("c"); 接下来在追加字符c
接下来我们该处理缓存_varybycustom的配置了
复制代码 代码如下:

if (cachedvary._varybycustom != null)
{
builder.append("n");
builder.append(cachedvary._varybycustom);
builder.append("v");
try
{
varybycustomstring = context.applicationinstance.getvarybycustomstring(context, cachedvary._varybycustom);
if (varybycustomstring == null)
{
varybycustomstring = "+n+";
}
}
catch (exception exception)
{
varybycustomstring = "+e+";
httpapplicationfactory.raiseerror(exception);
}
builder.append(varybycustomstring);
}

这个方法很好明白,如果_varybycustom不为null那么我们就追加n+key+v+value格式的字符。其中key就是_varybycustom字符串,value是调用context.applicationinstance.getvarybycustomstring(context, cachedvary._varybycustom)得到的value,如果value值为null,则设置为“+n+” builder.append("d");
复制代码 代码如下:

if (((verb == httpverb.post) && cachedvary._varybyallparams) && (request.form.count == 0))
{
int contentlength = request.contentlength;
if ((contentlength > 0x3a98) || (contentlength < 0))
{
return null;
}
if (contentlength > 0)
{
byte[] asbytearray = ((httpinputstream) request.inputstream).getasbytearray();
if (asbytearray == null)
{
return null;
}
varybycustomstring = convert.tobase64string(machinekeysection.hashdata(asbytearray, null, 0, asbytearray.length));
builder.append(varybycustomstring);
}
}

这段代码主要是给key追加一个字符d,然后在处理post的请求(非表单request.form.count == 0)把请求的内容(字节)转化为字符追加到key中,一般的http很少会发生此情况,典型的是httpwebrequest发生的post请求会触发。
复制代码 代码如下:

builder.append("e");
string[] strarray2 = cachedvary._contentencodings;
if (strarray2 != null)
{
string httpheadercontentencoding = context.response.gethttpheadercontentencoding();
if (httpheadercontentencoding != null)
{
for (int j = 0; j < strarray2.length; j++)
{
if (strarray2[j] == httpheadercontentencoding)
{
builder.append(httpheadercontentencoding);
break;
}
}
}
}

这段代码首先给key追加一个字符e,然后最佳contentencoding,contentencoding的取值为 context.response.gethttpheadercontentencoding()并且在缓存策略中的 _contentencodings存在才追加。
到现在为止我们的createoutputcacheditemkey方法讲完了,缓存策略的key没什么说的,与http请求方式get和post、request的path属性有关。但是缓存数据的key有关对象:
(1)与我们的_headers有关,即配置中的 varybyheader属性有关,varybyheader取值不同,key则不同
(2)与_varybyallparams有关,当它为true时,实际上就是与 request.querystring有关,如果此请求是post则还与request.form有关;_varybyallparams默认为 false,为true的情况也很单一 varybyallparams = (varybyparams.length == 1) && (varybyparams[0] == "*")
(3)与_varybycustom有关,它会把 context.applicationinstance.getvarybycustomstring(context, cachedvary._varybycustom)方法返回值追加到key中,
(4)与_contentencodings有关,如果 context.response.gethttpheadercontentencoding()返回的值在_contentencodings中则追加其返回值。
注意:如果此http处理是一个post并且request.form.count ==0&& _varybyallparams为rue的时候海域我们post过来的数据有关。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网