HttpHandler在Asp.net中核心对像之一,我们可以实现IHttpHandler接口来优化Css样式文件. 用一个我们自定义的HttpHandler映射.css的文件.
首先我们最小化Css样式文件尺寸, 然后我们再处理后CSS文件做内存缓存. 缓存依赖物理文件,当文件被修改后,重新加载. 这里我们以Demo为目的,默认
缓存时间2小时. 让我们先来看一下类图是这样的:
我们定义一个IFilesCache的接口,是为了实现两种不能缓存方式.一种是有用System.Web.Caching.Cache,别一个是用.net 4.0下System.Runtime.Caching.ObjectCache的内存Cache. 我们定义一个FilesCacheFactory的类根据.net framework当前版来在创建
当前的实例. 当然你可以直接选择其它组件实现缓存. 下面是Handler的代码:
1: /// <summary>
2: /// MinifyCssHandler
3: /// </summary>
4: public class MinifyCssHandler:IHttpHandler
5: {
6: private IFilesCache cacheContext;
7:
8: /// <summary>
9: /// Initializes a new instance of the <see cref="MinifyCssHandler"/> class.
10: /// </summary>
11: public MinifyCssHandler()
12: {
13: cacheContext = FilesCacheFactory.GetInstance();
14: }
15:
16: #region IHttpHandler Members
17:
18: /// <summary>
19: /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance.
20: /// </summary>
21: /// <returns>true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false.</returns>
22: public bool IsReusable
23: {
24: get { return true; }
25: }
26:
27: /// <summary>
28: /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface.
29: /// </summary>
30: /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
31: public void ProcessRequest(HttpContext context)
32: {
33: string fileContent = string.Empty;
34: string filePath = context.Request.PhysicalPath;
35:
36: string cacheKey = string.Concat("css-", filePath);
37:
38: object cacheValue = cacheContext.GetFromCache(cacheKey);
39:
40: if (cacheValue == null)
41: {
42: fileContent = MinifyFiles(filePath);
43: cacheContext.AddToCache(cacheKey, fileContent, filePath);
44: }
45: else
46: {
47: fileContent = cacheValue as string;
48: }
49: context.Response.ContentType = "text/css";
50: context.Response.Write(fileContent);
51: }
52:
53: #endregion
54:
55: /// <summary>
56: /// MinifyFiles intent to minfiy css files size
57: /// </summary>
58: /// <param name="filePath">css file path</param>
59: /// <returns>css file of content</returns>
60: private string MinifyFiles(string filePath)
61: {
62: string fileContent = File.ReadAllText(filePath);
63: fileContent = string.Concat("/* minifyed at ", DateTime.Now, " by Petter Liu */ ", fileContent);
64: fileContent = Regex.Replace(fileContent, "\t", string.Empty);
65: fileContent = Regex.Replace(fileContent, "\r\n", string.Empty);
66: fileContent = Regex.Replace(fileContent, "\r", string.Empty);
67: fileContent = Regex.Replace(fileContent, "\n", string.Empty);
68: //Replace more than two spaces
69: fileContent = Regex.Replace(fileContent, "[ ]{2,}", string.Empty);
70: return fileContent;
71: }
72: }
与Cache相关的类:
1: /// <summary>
2: /// IFilesCache
3: /// </summary>
4: public interface IFilesCache
5: {
6: /// <summary>
7: /// Add object to cache
8: /// </summary>
9: /// <param name="key">key</param>
10: /// <param name="value">value</param>
11: /// <param name="filePath">file path</param>
12: void AddToCache(string key, object value, string filePath);
13:
14: /// <summary>
15: /// GetFromCache
16: /// </summary>
17: /// <param name="key">key</param>
18: /// <returns>object</returns>
19: object GetFromCache(string key);
20: }
21:
22: /// <summary>
23: /// a simple factory create IFilesCache
24: /// </summary>
25: public class FilesCacheFactory
26: {
27: /// <summary>
28: /// Create IFilesCache instance
29: /// </summary>
30: /// <remarks>System.Runtime.Caching only runtime at .net framework version 4</remarks>
31: /// <returns>IFilesCache</returns>
32: public static IFilesCache GetInstance()
33: {
34: if (Environment.Version.Major==4)
35: return new DotnetRunningCache();
36: return new WebContextCache();
37: }
38:
39: }
40:
41: public class WebContextCache:IFilesCache
42: {
43: #region IFilesCache Members
44: /// <summary>
45: /// Add object to cache
46: /// </summary>
47: /// <param name="key">key</param>
48: /// <param name="value">value</param>
49: /// <param name="filePath">file path</param>
50: public void AddToCache(string key, object value, string filePath)
51: {
52: //Cache two hour
53: HttpContext.Current.Cache.Insert(key, value,
54: new CacheDependency(filePath),
55: DateTime.Now.AddHours(2),
56: TimeSpan.Zero);
57: }
58:
59: /// <summary>
60: /// GetFromCache
61: /// </summary>
62: /// <param name="key">key</param>
63: /// <returns>object</returns>
64: public object GetFromCache(string key)
65: {
66: if (string.IsNullOrEmpty(key))
67: return new ArgumentNullException("cache key should not null");
68: return HttpContext.Current.Cache[key];
69: }
70:
71: #endregion
72: }
73:
74: public class DotnetRunningCache:IFilesCache
75: {
76: #region IFilesCache Members
77: /// <summary>
78: /// Add object to cache
79: /// </summary>
80: /// <param name="key">key</param>
81: /// <param name="value">value</param>
82: /// <param name="filePath">file path</param>
83: public void AddToCache(string key, object value, string filePath)
84: {
85: ObjectCache cache = MemoryCache.Default;
86: var cacheValue = new[] { value };
87: var cachepolicy = new CacheItemPolicy();
88: var filespath=new List<string>(){ filePath};
89: cachepolicy.AbsoluteExpiration = DateTimeOffset.Now.AddHours(2);
90: cachepolicy.ChangeMonitors.Add(new HostFileChangeMonitor(filespath));
91:
92: cache.Add(key, cacheValue, cachepolicy);
93: }
94:
95: /// <summary>
96: /// GetFromCache
97: /// </summary>
98: /// <param name="key">key</param>
99: /// <returns>object</returns>
100: public object GetFromCache(string key)
101: {
102: if (string.IsNullOrEmpty(key))
103: return new ArgumentNullException("cache key should not null");
104:
105: ObjectCache cache = MemoryCache.Default;
106: var objects= (Object[])cache.Get(key);
107: if (objects != null)
108: return objects.FirstOrDefault();
109: return null;
110: }
111:
112: #endregion
113: }
在Web.config中增加:
1: <httpHandlers>
2: <add verb="*" path="*.css" validate="false" type="MyWeb.MinifyCssHandler"/>
3: </httpHandlers>
Ok,对比一下,正常情况下是这样:
当增加这个优化Css的HttpHandler后, 是这样的:
有注意size从4.2KB变成了3.2KB. 以上我们直是实现比较简单的,你可以优化实现更高效的算法. 或增加扩展.
希望这篇Post对您开发有帮助.
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。