【知识碎片】Net项目经验积累
响应报文 隐藏服务器信息
HttpContext.Response.Headers.Remove("X-AspNet-Version"); HttpContext.Response.Headers.Remove("X-AspNetMvc-Version"); HttpContext.Response.Headers.Set("Server", "Nginx-57blog-VIP");
URL重写方案总结
负载均衡
硬件Netscaler F5 Radware Array
软件 LVS nginx apache tengine(淘宝的,提交给nginx nginx不接受,就自己写了)
LVS:http://www.cnblogs.com/edisonchou/p/4281978.html
Page类回调技术 单页模式
在前台页面直接写一个 protected void Page_Load(obeject obj,Event e) 就不需要后台页面了 可以直接删除了,要放在 <script runat="server"></script> 内
这里面也可以写其他函数 不过还是写在后台效率高,直接编译dl了,aspx是动态编译效率低
通过一个aspx文件直接获取服务器web.config文件
<%@ Page Language="C#" ContentType="text/html" ResponseEncoding="gb2312" %> <%@ Import Namespace="System.Text" %> <%@ Import Namespace="System.IO"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>用户注册</title> <script language="javascript"> </script> <script language="c#" runat="server"> string result=""; //服务器上执行的方法 public void Page_Load(Object sender,EventArgs e) { using (FileStream fs = new FileStream(Server.MapPath("/")+"Web.config", FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); string msg = System.Text.Encoding.UTF8.GetString(buffer); //Response.Write(msg); string timeNow = DateTime.Now.ToString(); Response.Clear(); Response.Buffer = false; Response.ContentType = "application/octet-stream"; Response.AppendHeader("content-disposition", "attachment;filename=" + "Web" + ".config;"); Response.Write(msg); Response.Flush(); Response.End(); } } </script> </head> <body> </body> </html>
NVelocity 视图模板引擎
NVelocity 视图模板引擎 如 razor vtemplate
订单存储过程
存储过程比放在程序里的SQL速度快
存储过程只编译一次 程序里的每次请求都需要编译
安全 不会有SQL注入
缺点 可移植性差
互联网项目一般不用存储过程
create proc createOrder @address nvarchar(255),--收货人地址 @orderId nvarchar(50),--订单号 @userId int,--用户编号 @totalMoney money output --总金额 as begin declare @error int set @error=0 begin transaction ---计算总金额 select @totalMoney=sum([Count]*UnitPrice)from Cart inner join Books on Cart.BookId=Books.Id where Cart.UserId=@userId set @error=@@error+@error --向订单主表中插入数据。 insert into dbo.Orders(OrderId, OrderDate, UserId, TotalPrice, PostAddress, state) values(@orderId,getdate(),@userId,@totalMoney,@address,0) set @error=@@error+@error --行订单明细表中插入数据 insert into dbo.OrderBook(OrderID, BookID, Quantity, UnitPrice) select @orderId,Cart.BookId,Cart.Count,Books.UnitPrice from Cart inner join Books on Cart.BookId=Books.Id where Cart.UserId=@userId set @error=@@error+@error --删除购物车表中的数据 delete from Cart where UserId=@userId set @error=@@error+@error if @error>0 begin rollback transaction--回滚 end else begin commit transaction--提交 end end
.Net自带缓存helper
using System; using System.Web; using System.Collections; public class CookiesHelper { /**//// <summary> /// 获取数据缓存 /// </summary> /// <param name="CacheKey">键</param> public static object GetCache(string CacheKey) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; return objCache[CacheKey]; } /**//// <summary> /// 设置数据缓存 /// </summary> public static void SetCache(string CacheKey, object objObject) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert(CacheKey, objObject); } /**//// <summary> /// 设置数据缓存 /// </summary> public static void SetCache(string CacheKey, object objObject, TimeSpan Timeout) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert(CacheKey, objObject, null, DateTime.MaxValue, Timeout, System.Web.Caching.CacheItemPriority.NotRemovable, null); } /**//// <summary> /// 设置数据缓存 /// </summary> public static void SetCache(string CacheKey, object objObject, DateTime absoluteExpiration, TimeSpan slidingExpiration) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert(CacheKey, objObject, null, absoluteExpiration, slidingExpiration); } /**//// <summary> /// 移除指定数据缓存 /// </summary> public static void RemoveAllCache(string CacheKey) { System.Web.Caching.Cache _cache = HttpRuntime.Cache; _cache.Remove(CacheKey); } /**//// <summary> /// 移除全部缓存 /// </summary> public static void RemoveAllCache() { System.Web.Caching.Cache _cache = HttpRuntime.Cache; IDictionaryEnumerator CacheEnum = _cache.GetEnumerator(); while (CacheEnum.MoveNext()) { _cache.Remove(CacheEnum.Key.ToString()); } } }
Url重写
把带参数的改写成不带参数的,BookDetail.aspx?id=52 -->BookDetai_52.aspx
有利于SEO优化
(不推荐这样在管道写,推荐使用IIS插件 url rewrite)
using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Web; using System.Web.Security; using System.Web.SessionState; namespace BookShop.Web { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { } protected void Session_Start(object sender, EventArgs e) { } /// <summary> /// 请求管道中第一个事件触发以后调用的方法,完成URL重写。 /// URL重写。 ///带参数的URL地址进行改写。改写成不带参数的。 //BookDetail.aspx?id=2; BookDetail_2.aspx //为什么将带参数的URL地址改成不带参数的?URL重写的目的就是SEO。 //SEO. //怎样进行URL重写? /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Application_BeginRequest(object sender, EventArgs e) { string url = Request.AppRelativeCurrentExecutionFilePath;//~/BookDetail_4976.aspx Match match=Regex.Match(url, @"~/BookDetail_(\d+).aspx"); if (match.Success) { Context.RewritePath("/BookDetail.aspx?id="+match.Groups[1].Value); } //Match match = Regex.Match(url, @"~/BookDetail_(\d+).aspx"); //if (match.Success) //{ // Context.RewritePath("/BookDetail.aspx?id=" + match.Groups[1].Value); //} } protected void Application_AuthenticateRequest(object sender, EventArgs e) { } protected void Application_Error(object sender, EventArgs e) { } protected void Session_End(object sender, EventArgs e) { } protected void Application_End(object sender, EventArgs e) { } } }
SWFUpload 文件上传
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CutPhoto.aspx.cs" Inherits="BookShop.Web.Member.CutPhoto" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <link href="../Css/themes/ui-lightness/jquery-ui-1.8.2.custom.css" rel="stylesheet" /> <script src="../js/jquery-1.7.1.js"></script> <script src="../js/jquery-ui-1.8.2.custom.min.js"></script> <script src="../SWFUpload/swfupload.js"></script> <script src="../SWFUpload/handlers.js"></script> <script type="text/javascript"> var swfu; window.onload = function () { swfu = new SWFUpload({ // Backend Settings upload_url: "/ashx/upload.ashx?action=upload", post_params: { "ASPSESSID": "<%=Session.SessionID %>" }, // File Upload Settings file_size_limit: "2 MB", file_types: "*.jpg;*.gif", file_types_description: "JPG Images", file_upload_limit: 0, // Zero means unlimited // Event Handler Settings - these functions as defined in Handlers.js // The handlers are not part of SWFUpload but are part of my website and control how // my website reacts to the SWFUpload events. swfupload_preload_handler: preLoad, swfupload_load_failed_handler: loadFailed, file_queue_error_handler: fileQueueError, file_dialog_complete_handler: fileDialogComplete, upload_progress_handler: uploadProgress, upload_error_handler: uploadError, upload_success_handler: showImage, upload_complete_handler: uploadComplete, // Button settings button_image_url: "/SWFUpload/images/XPButtonNoText_160x22.png", button_placeholder_id: "spanButtonPlaceholder", button_width: 160, button_height: 22, button_text: '<span class="button">请选择上传图片<span class="buttonSmall">(2 MB Max)</span></span>', button_text_style: '.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }', button_text_top_padding: 1, button_text_left_padding: 5, // Flash Settings flash_url: "/SWFUpload/swfupload.swf", // Relative to this file flash9_url: "/SWFUpload/swfupload_FP9.swf", // Relative to this file custom_settings: { upload_target: "divFileProgressContainer" }, // Debug Settings debug: false }); } //上传成功以后调用该方法 function showImage(file, serverData) { // $("#showPhoto").attr("src", serverData); var data = serverData.split(':'); //将上传成功的图片作为DIV的背景 $("#hiddenImageUrl").val(data[0]);//将上传成功的图片路径存储到隐藏域中。 $("#divContent").css("backgroundImage", "url('" + data[0] + "')").css("width",data[1]+"px").css("height",data[2]+"px"); } $(function () { //让DIV可以移动与拖动大小 $("#divCut").draggable({ containment: "#divContent", scroll: false }).resizable({ containment: "#divContent" }); $("#btnCut").click(function () { cutPhoto(); }); }) //截取头像 function cutPhoto() { //计算要截取的头像的范围。 var y = $("#divCut").offset().top - $("#divContent").offset().top;//纵坐标 var x = $("#divCut").offset().left - $("#divContent").offset().left; var width = $("#divCut").width(); var heigth = $("#divCut").height(); var pars = { "x": x, "y": y, "width": width, "height": heigth, "action": "cut", "imgSrc": $("#hiddenImageUrl").val() }; $.post("/ashx/upload.ashx", pars, function (data) { $("#showPhoto").attr("src",data); }); } </script> </head> <body> <form id="form1" runat="server"> <div id="content"> <div id="swfu_container" style="margin: 0px 10px;"> <div> <span id="spanButtonPlaceholder"></span> </div> <div id="divFileProgressContainer" style="height: 75px;"></div> <div id="thumbnails"></div> <div id="divContent" style="width:300px; height:300px;"> <div id="divCut" style="width:100px;height:100px; border:solid red 1px"> </div> </div> <input type="button" value="截取图片" id="btnCut" /> <input type="hidden" id="hiddenImageUrl" /> <img id="showPhoto"></img> </div> </div> </form> </body> </html>
using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Web; namespace BookShop.Web.ashx { /// <summary> /// upload 的摘要说明 /// </summary> public class upload : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string action = context.Request["action"]; if (action == "upload")//上传图片 { ProcessFileUpload(context); } else if (action =="cut")//截取图片 { ProcessCutPhoto(context); } else { context.Response.Write("参数错误!!"); } } /// <summary> /// 文件上传 /// </summary> /// <param name="context"></param> private void ProcessFileUpload(HttpContext context) { HttpPostedFile file = context.Request.Files["Filedata"]; if (file != null) { string fileName = Path.GetFileName(file.FileName); string fileExt = Path.GetExtension(fileName); if (fileExt == ".jpg") { string dir = "/ImageUpload/" + DateTime.Now.Year + "/" + DateTime.Now.Month + "/" + DateTime.Now.Day + "/"; if (!Directory.Exists(context.Request.MapPath(dir))) { Directory.CreateDirectory(context.Request.MapPath(dir)); } string newfileName = Guid.NewGuid().ToString(); string fullDir = dir + newfileName + fileExt; file.SaveAs(context.Request.MapPath(fullDir)); using (Image img = Image.FromFile(context.Request.MapPath(fullDir))) { context.Response.Write(fullDir + ":" + img.Width + ":" + img.Height); } //file.SaveAs(context.Request.MapPath("/ImageUpload/"+fileName)); //context.Response.Write("/ImageUpload/" + fileName); } } } /// <summary> /// 图片的截取 /// </summary> /// <param name="context"></param> private void ProcessCutPhoto(HttpContext context) { int x = Convert.ToInt32(context.Request["x"]); int y = Convert.ToInt32(context.Request["y"]); int width = Convert.ToInt32(context.Request["width"]); int height = Convert.ToInt32(context.Request["height"]); string imgSrc = context.Request["imgSrc"];//获取上传成功的图片的路径 using (Bitmap map = new Bitmap(width, height)) { using (Graphics g = Graphics.FromImage(map)) { using (Image img = Image.FromFile(context.Request.MapPath(imgSrc))) { //第一个参数:表示画哪张图片. //二:画多么大。 //三:画原图的哪块区域 g.DrawImage(img, new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height), GraphicsUnit.Pixel); string newfileName = Guid.NewGuid().ToString(); string fullDir = "/ImageUpload/" + newfileName + ".jpg"; map.Save(context.Request.MapPath(fullDir),System.Drawing.Imaging.ImageFormat.Jpeg); context.Response.Write(fullDir); } } } } public bool IsReusable { get { return false; } } } }
一般处理程序调用session
一般处理程序调用session 必须实现接口 IReadOnlySessionState
spring.net
1 ioc 控制反转 以前自己new 这个是交给容器new
2 di 依赖注入 在创建类实例的时候 可以给一些属性完成初始化复制 (spring.net 配置文件中ref和value 等同,只是他是指的对象)
Memcache
socket通信,网站服务器上安装客户端端,其他的缓存服务器 称为服务端,通过它的算法,取其中一个存取
没有主从 存取都是在memcache客户端
惰性删除:它并没有提供监控数据过期的机制,而是惰性的,当查询到某个key数据时,如果过期那么直接抛弃,如果存满了,把一些不经常访问的删除掉
http://www.cnblogs.com/caokai520/p/4390646.html
实例代码 建议修改一下 把下面的两个结合一下
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; using Memcached.ClientLibrary; namespace Hep.Memcached.Uitils { public class MemberHelper { static SockIOPool _pool; #region 创建Memcache服务 /// <summary> /// 创建Memcache服务 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">Socket连接池名称</param> /// <returns>Memcache客户端代理类</returns> private static MemcachedClient CreateServer(ArrayList serverlist, string poolName) { if (_pool != null) { } else { ////初始化memcache服务器池 _pool = SockIOPool.GetInstance(poolName); //设置Memcache池连接点服务器端。 _pool.SetServers(serverlist); ////其他参数根据需要进行配置 //各服务器之间负载均衡的设置 _pool.SetWeights(new int[] { 1 }); //socket pool设置 _pool.InitConnections = 5; //初始化时创建的连接数 _pool.MinConnections = 5; //最小连接数 _pool.MaxConnections = 250; //最大连接数 //连接的最大空闲时间,下面设置为6个小时(单位ms),超过这个设置时间,连接会被释放掉 _pool.MaxIdle = 1000 * 60 * 60 * 6; //通讯的超时时间,下面设置为3秒(单位ms),.NET版本没有实现 _pool.SocketTimeout = 1000 * 3; //socket连接的超时时间,下面设置表示连接不超时,即一直保持连接状态 _pool.SocketConnectTimeout = 0; _pool.Nagle = false; //是否对TCP/IP通讯使用Nalgle算法,.NET版本没有实现 //维护线程的间隔激活时间,下面设置为60秒(单位s),设置为0表示不启用维护线程 _pool.MaintenanceSleep = 60; //socket单次任务的最大时间,超过这个时间socket会被强行中断掉(当前任务失败) _pool.MaxBusy = 1000 * 10; _pool.Initialize(); } //创建了一个Memcache客户端的代理类。 MemcachedClient mc = new MemcachedClient(); mc.PoolName = poolName; mc.EnableCompression = false;//是否压缩 return mc; } #endregion #region 缓存是否存在 /// <summary> /// 缓存是否存在 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="key">键</param> /// <returns></returns> public static bool CacheIsExists(ArrayList serverlist, string poolName, string key) { MemcachedClient mc = CreateServer(serverlist, poolName); if (mc.KeyExists(key)) { return true; } else { return false; } } #endregion #region 添加缓存 #region 添加缓存(键不存在则添加,键存在则不能添加) /// <summary> /// 添加缓存(键不存在则添加,键存在则不能添加) /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <param name="value">值</param> /// <param name="minutes">过期分钟数</param> /// <returns></returns> public static bool AddCache(ArrayList serverlist, string poolName, string key, string value, int minutes) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.Add(key, value, DateTime.Now.AddMinutes(minutes)); } #endregion #region 添加缓存(键不存在则添加,键存在则不能添加) /// <summary> /// 添加缓存(键不存在则添加,键存在则不能添加) /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <param name="value">值</param> /// <param name="minutes">过期分钟数</param> /// <returns></returns> public static bool AddCache(ArrayList serverlist, string poolName, string key, object value, int minutes) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.Add(key, value, DateTime.Now.AddMinutes(minutes)); } #endregion #region 添加缓存(键不存在则添加,键存在则覆盖) /// <summary> /// 添加缓存(键不存在则添加,键存在则覆盖) /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <param name="value">值</param> /// <param name="minutes">过期分钟数</param> /// <returns></returns> public static bool SetCache(ArrayList serverlist, string poolName, string key, string value, int minutes) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.Set(key, value, DateTime.Now.AddMinutes(minutes)); } #endregion #region 添加缓存(键不存在则添加,键存在则覆盖) /// <summary> /// 添加缓存(键不存在则添加,键存在则覆盖) object 类型 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <param name="value">值</param> /// <param name="minutes">过期分钟数</param> /// <returns></returns> public static bool SetCache(ArrayList serverlist, string poolName, string key, object value, int minutes) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.Set(key, value, DateTime.Now.AddMinutes(minutes)); } #endregion #endregion #region 替换缓存 #region 替换缓存(键存在的才能替换,不存在则不替换) /// <summary> /// 替换缓存(键存在的才能替换,不存在则不替换) /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <param name="value">值</param> /// <param name="minutes">过期分钟数</param> /// <returns></returns> public static bool ReplaceCache(ArrayList serverlist, string poolName, string key, string value, int minutes) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.Replace(key, value, DateTime.Now.AddMinutes(minutes)); } #endregion #endregion #region 获取缓存 #region 获取单个键对应的缓存 /// <summary> /// 获取单个键对应的缓存 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <returns></returns> public static object GetCache(ArrayList serverlist, string poolName, string key) { MemcachedClient mc = CreateServer(serverlist, poolName); if (mc.KeyExists(key)) { return mc.Get(key); } else { return ""; } } #endregion #region 获取键数组对应的值 /// <summary> /// 获取键数组对应的值 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="keys">键列表</param> /// <returns>Hashtable键值对</returns> public static Hashtable GetCacheHt(ArrayList serverlist, string poolName, string[] keys) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.GetMultiple(keys); } #endregion #region 获取键数组对应的值 /// <summary> /// 获取键数组对应的值 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="keys">键列表</param> /// <returns>值的数组(不包含键)</returns> public static object[] GetCacheList(ArrayList serverlist, string poolName, string[] keys) { MemcachedClient mc = CreateServer(serverlist, poolName); object[] list = mc.GetMultipleArray(keys); ArrayList returnList = new ArrayList(); for (int i = 0; i < list.Length; i++) { if (list[i] != null) { returnList.Add(list[i]); } } return returnList.ToArray(); } #endregion #endregion #region 删除缓存 /// <summary> /// 删除缓存 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <param name="key">键</param> /// <returns></returns> public static bool DelCache(ArrayList serverlist, string poolName, string key) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.Delete(key); } #endregion #region 清空所有缓存 /// <summary> /// 清空所有缓存 /// </summary> /// <param name="serverlist">IP端口列表</param> /// <param name="poolName">连接池名称</param> /// <returns></returns> public static bool FlushAll(ArrayList serverlist, string poolName) { MemcachedClient mc = CreateServer(serverlist, poolName); return mc.FlushAll(); } #endregion } }
{ private static readonly ILog Logger = LogManager.GetCurrentClassLogger(); private readonly MemcachedClient _cache; public MemcachedCachePolicy() { _cache = MemcachedClient.GetInstance("MemcachedConfig"); _cache.MaxPoolSize = 10000; } public void Add<T>(string key, T value) { if (_cache.Set(key, value)) { Logger.Debug("Set _cache for key successed, key[" + key + "]"); } else { Logger.Debug("Set _cache for key failed"); } } public void Add<T>(string key, T value, DateTime dt) { _cache.Set(key, value, dt); } public T Get<T>(string key) { try { return (T)_cache.Get(key); } catch (Exception e) { Logger.Debug("Get _cache for key failed, key[" + key + "]", e); _cache.Delete(key); return default(T); } } public void Add(string key, object value) { _cache.Set(key, value); } public void Add(string key, object value, DateTime dt) { _cache.Set(key, value, dt); } public object Get(string key) { return _cache.Get(key); } public void Delete(string key) { _cache.Delete(key); } }
using Memcached.ClientLibrary; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CZBK.ItcastOA.Common { public class MemcacheHelper { private static readonly MemcachedClient mc = null; static MemcacheHelper() { //最好放在配置文件中 string[] serverlist = { "127.0.0.1:11211", "10.0.0.132:11211" }; //初始化池 SockIOPool pool = SockIOPool.GetInstance(); pool.SetServers(serverlist); pool.InitConnections = 3; pool.MinConnections = 3; pool.MaxConnections = 5; pool.SocketConnectTimeout = 1000; pool.SocketTimeout = 3000; pool.MaintenanceSleep = 30; pool.Failover = true; pool.Nagle = false; pool.Initialize(); // 获得客户端实例 mc = new MemcachedClient(); mc.EnableCompression = false; } /// <summary> /// 存储数据 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public static bool Set(string key,object value) { return mc.Set(key, value); } public static bool Set(string key, object value,DateTime time) { return mc.Set(key, value,time); } /// <summary> /// 获取数据 /// </summary> /// <param name="key"></param> /// <returns></returns> public static object Get(string key) { return mc.Get(key); } /// <summary> /// 删除 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool Delete(string key) { if (mc.KeyExists(key)) { return mc.Delete(key); } return false; } } }
多线程处理 lucene.net 单例模式
using CZBK.ItcastOA.Model.EnumType; using Lucene.Net.Analysis.PanGu; using Lucene.Net.Documents; using Lucene.Net.Index; using Lucene.Net.Store; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Web; namespace CZBK.ItcastOA.WebApp.Models { public sealed class IndexManager { //不用写跟新方法了,因为添加的时候,是先删除然后添加 //单列模式 sealed 不允许被继承 // 只允许在自己的类中 创建私有的构造函数 //readonly 不允许改 只读的 private static readonly IndexManager indexManager = new IndexManager(); private IndexManager() { //创建私有的构造函数 保证不被外部new } public static IndexManager GetInstance() { return indexManager; } public Queue<ViewModelContent> queue = new Queue<ViewModelContent>(); /// <summary> /// 向队列中添加数据 /// </summary> /// <param name="id"></param> /// <param name="title"></param> /// <param name="content"></param> public void AddQueue(int id, string title, string content) { ViewModelContent viewModel = new ViewModelContent(); viewModel.Id = id; viewModel.Title = title; viewModel.Content = content; viewModel.LuceneTypeEnum = LuceneTypeEnum.Add; queue.Enqueue(viewModel); } /// <summary> /// 要删除的数据 /// </summary> /// <param name="id"></param> public void DeleteQueue(int id) { ViewModelContent viewModel = new ViewModelContent(); viewModel.Id = id; viewModel.LuceneTypeEnum = LuceneTypeEnum.Delete; queue.Enqueue(viewModel); } /// <summary> /// 开始一个线程 /// </summary> public void StartThread() { Thread thread = new Thread(WriteIndexContent); thread.IsBackground = true; thread.Start(); } /// <summary> /// 检查队列中是否有数据,如果有数据获取。 /// </summary> private void WriteIndexContent() { while (true) { if (queue.Count > 0) { CreateIndexContent(); } else { Thread.Sleep(3000); } } } private void CreateIndexContent() { string indexPath = @"C:\lucenedir";//注意和磁盘上文件夹的大小写一致,否则会报错。将创建的分词内容放在该目录下。//将路径写到配置文件中。 FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());//指定索引文件(打开索引目录) FS指的是就是FileSystem bool isUpdate = IndexReader.IndexExists(directory);//IndexReader:对索引进行读取的类。该语句的作用:判断索引库文件夹是否存在以及索引特征文件是否存在。 if (isUpdate) { //同时只能有一段代码对索引库进行写操作。当使用IndexWriter打开directory时会自动对索引库文件上锁。 //如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁(提示一下:如果我现在正在写着已经加锁了,但是还没有写完,这时候又来一个请求,那么不就解锁了吗?这个问题后面会解决) if (IndexWriter.IsLocked(directory)) { IndexWriter.Unlock(directory); } } IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);//向索引库中写索引。这时在这里加锁。 //如果队列中有数据,获取队列中的数据写到Lucene.Net中。 while(queue.Count>0) { ViewModelContent viewModel=queue.Dequeue(); writer.DeleteDocuments(new Term("Id",viewModel.Id.ToString()));//删除 if (viewModel.LuceneTypeEnum == LuceneTypeEnum.Delete) { continue; } Document document = new Document();//表示一篇文档。 //Field.Store.YES:表示是否存储原值。只有当Field.Store.YES在后面才能用doc.Get("number")取出值来.Field.Index. NOT_ANALYZED:不进行分词保存 document.Add(new Field("Id", viewModel.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); //Field.Index. ANALYZED:进行分词保存:也就是要进行全文的字段要设置分词 保存(因为要进行模糊查询) //Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS:不仅保存分词还保存分词的距离。 document.Add(new Field("Title", viewModel.Title, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS)); document.Add(new Field("Content", viewModel.Content, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS)); writer.AddDocument(document); } writer.Close();//会自动解锁。 directory.Close();//不要忘了C } } }
调用上面的单列
using CZBK.ItcastOA.WebApp.Models; using log4net; using Spring.Web.Mvc; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace CZBK.ItcastOA.WebApp { // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明, // 请访问 http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : SpringMvcApplication //System.Web.HttpApplication { protected void Application_Start() { log4net.Config.XmlConfigurator.Configure();//读取了配置文件中关于Log4Net配置信息. IndexManager.GetInstance().StartThread();//开始线程扫描LuceneNet对应的数据队列。 这里就不能new了 因为你是单列模式 所以直接掉他的方法创建实例,他只允许自己的内部创建 AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); //开启一个线程,扫描异常信息队列。 string filePath = Server.MapPath("/Log/"); ThreadPool.QueueUserWorkItem((a) => { while (true) { //判断一下队列中是否有数据 if (MyExceptionAttribute.ExecptionQueue.Count() > 0) { Exception ex=MyExceptionAttribute.ExecptionQueue.Dequeue(); if (ex != null) { //将异常信息写到日志文件中。 //string fileName = DateTime.Now.ToString("yyyy-MM-dd"); //File.AppendAllText(filePath+fileName+".txt",ex.ToString(),System.Text.Encoding.UTF8); ILog logger = LogManager.GetLogger("errorMsg"); logger.Error(ex.ToString()); } else { //如果队列中没有数据,休息 Thread.Sleep(3000); } } else { //如果队列中没有数据,休息 Thread.Sleep(3000); } } },filePath); } //异常处理的过滤器。 } }
测试上面的队列
using CZBK.ItcastOA.WebApp.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace CZBK.ItcastOA.WebApp.Controllers { public class TestController : Controller { // // GET: /Test/ public ActionResult Index() { return View(); } public ActionResult ShowResult() { int a = 2; int b = 0; int c = a / b; return Content(c.ToString()); } public ActionResult TestCreate() { Model.Books model = new Model.Books(); model.AurhorDescription = "jlkfdjf"; model.Author = "asfasd"; model.CategoryId = 1; model.Clicks = 1; model.ContentDescription = "Ajax高级编程"; model.EditorComment = "adfsadfsadf"; model.ISBN = "111111111111111111"; model.PublishDate = DateTime.Now; model.PublisherId = 72; model.Title = "Ajax"; model.TOC = "aaaaaaaaaaaaaaaa"; model.UnitPrice = 22.3m; model.WordsCount = 1234; //1.将数据先存储到数据库中。获取刚插入的数据的主键ID值。 IndexManager.GetInstance().AddQueue(9999, model.Title, model.ContentDescription);//向队列中添加 return Content("ok"); } } }
lucene.net 返回的时候 为什么只返回文档的编号 而不是吧整个文档返回?
节省内存,如果把符合结果的文档全部返回,那样占的内存就大了
拿到文档ID之后 在根据文档ID 单条搜索文档内容
此处我感觉 lucene是可以存文档内容的 看具体需求吧
区分同一from表单不同按钮提交
当一个form表单 有两个提交按钮的时候怎么区别? 比如 “搜索”、“创建索引库”
根据 submit的值,点哪个提交哪个的值,另一个值是空
if(!string.IsNullOrEmpty(Request["btnSearth"])){}
session原理
memcache 分布式session原理 创建缓存的唯一key GUID 然后以cookie的形式存客户浏览器内存上,这就是原生session的原理
队列:
dot.net 自带了队列 队列和栈相反,队列是先进 先出
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; using System.Web.Mvc; namespace CZBK.ItcastOA.WebApp.Models { public class MyExceptionAttribute : HandleErrorAttribute { //静态的 保证在一个队列里,如果每次都new得话就不是一个队列了 public static Queue<Exception> ExecptionQueue = new Queue<Exception>(); /// <summary> /// 可以捕获异常数据 /// </summary> /// <param name="filterContext"></param> public override void OnException(ExceptionContext filterContext) { base.OnException(filterContext); Exception ex = filterContext.Exception; //写到队列 ExecptionQueue.Enqueue(ex); //跳转到错误页面. filterContext.HttpContext.Response.Redirect("/Error.html"); } } }