标签:contain include c51 lsp etc pcl mil 规范 set
我知道有些地方没说到位,希望大神们提出来,我会吸取教训,大家共同进步!
三种方法:(1)数据库(2)页面静态化(3)Redis、Memcached
概述:redis是一种nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(string,list列表[队列和栈],set[集合],sorted set[有序集合] hash(hash表))
注:关于Redis的安装网上有很多文章,讲的要比我的好,建议大家去看那些大神的文章,这里我只简单介绍一下。
如果你看到有6379 在监听,说明ok(默认的端口号时候:6379)
前言:Redis中存储的数据都为字符串格式的。下面来分别介绍Redis中常用的数据结构。
太简单了,略过。
概述: 什么是list ,list是一种数据结构,可以当做队列和栈来使用。
当你从左边添加数据,再从左边取数据,就模拟出栈;当你从右边添加数据,再从左边取数据,就模拟出队列。因此Redis真的很强大,看到栈和队列这样的数据结构,你难道就不激动吗?这样的数据结构太TM好了,能帮我们处理很多棘手的问题。这里我先卖个关子,下面会介绍我在项目中是如何使用Redis解决棘手的问题。
和list结构差不多,这里不再啰嗦。
下面就是操作set的一些命令。
图中的"user:100"就相当于key,而它所指向的类似于表结构的数据就是value,这样的数据结构有利于存储对象数据。也是非常常用的方法。
注意:
redis指令不区分大小写,但是出于规范考虑,应该使用大写
redis中存放的键是区分大小写的.
Redis常用命令文档:http://redis.readthedocs.io/en/2.6/
3.1C#中如何使用Redis来解决邮箱激活的实效性。
首先思考个问题:为什么要进行邮件激活?激活码该存到哪里?(大家先思考,我不直接说,这样通过下面的例子你会体会的更深。)
原因:用户在注册的时候,虽然正则表达式能检查邮箱的格式是否正确,但是正则检查不了邮箱是否可用,于是让用户进行激活,就能避免用户填写一个不可用的邮箱。
传统方法的代码实现:
1)数据库表的设计:
在用户注册的表中添加一个字段:IsActive用来判断激活的状态。
该表用来存放激活码。
代码实现:
BLL层代码:
1 /// <summary> 2 /// 2016-08-30 3 /// 注册的时候看看是否已经存在该用户 4 /// </summary> 5 /// <param name="username"></param> 6 /// <returns></returns> 7 public T_Users GetByUserName(string username) 8 { 9 T_UsersDAL userDal = new T_UsersDAL(); 10 return userDal.GetByUserName(username); 11 }
1 /// <summary> 2 /// 注册的时候看看邮箱是否已经被注册 3 /// </summary> 4 /// <returns></returns> 5 public bool CheckEmailOnReg(string email) 6 { 7 T_UsersDAL userDal = new T_UsersDAL(); 8 T_Users user= userDal.CheckEmailOnReg(email); 9 return user == null; 10 }
DAL层代码:
1 /// <summary> 2 /// 注册时候看看是否已经存在该用户名 3 /// </summary> 4 /// <param name="username"></param> 5 /// <returns></returns> 6 public T_Users GetByUserName(string username) 7 { 8 string sql = "select * from T_Users where UserName=@UserName"; 9 DataTable dt = SqlHelper.ExecuteQuery(sql, new SqlParameter("@UserName", username)); 10 T_Users userInfo = null; 11 if (dt.Rows.Count > 0) 12 { 13 foreach (DataRow dr in dt.Rows) 14 { 15 userInfo = RowToUserInfoByDataRow(dr); 16 } 17 } 18 return userInfo; 19 }
1 /// <summary> 2 /// 注册的时候检查用户的邮箱是否被注册 3 /// </summary> 4 /// <param name="email"></param> 5 /// <returns></returns> 6 public T_Users CheckEmailOnReg(string email) 7 { 8 string sql = "select * from T_Users where Email=@Email "; 9 DataTable dt = SqlHelper.ExecuteQuery(sql, new SqlParameter("@Email",email)); 10 11 T_Users userInfo = null; 12 if (dt.Rows.Count>0) 13 { 14 foreach (DataRow dr in dt.Rows) 15 { 16 userInfo=RowToUserInfoByDataRow(dr); 17 } 18 } 19 return userInfo; 20 }
UI层代码:
1 <!--#include file="/html/head.html"--> 2 <title>注册</title> 3 <!--#include file="/html/linkscript.html"--> 4 <script type="text/javascript"> 5 function checkPasswordLevel(value) { 6 if (!value) { 7 return 1; 8 } 9 if (value.length < 6) { 10 return 1; 11 } 12 if (value.length == 6 && (/[0-9]/.test(value) || /[a-z]/.test(value))) { 13 return 1; 14 } 15 16 if (value.length >= 6 && /[0-9]/.test(value) && /[a-z]/.test(value) && /(?=[\x21-\x7e]+)[^A-Za-z0-9]/.test(value)) { 17 return 3; 18 } 19 return 2; 20 } 21 $(function () { 22 $("#btnReg").click(function () { 23 var username = $("#username").val(); 24 var password = $("#password").val(); 25 var password2 = $("#password2").val(); 26 var email = $("#email").val(); 27 var phone = $("#PhoneNum").val(); 28 var qq = $("#qq").val(); 29 var school = $("#school").val(); 30 31 var validCode = $("#validCode").val(); 32 //todo:非空验证。JQuery EasyUI 33 if (phone == "") { 34 $("#phoneMsg").text("手机号不能为空!"); 35 return; 36 } 37 else { 38 var reg = "^1(3[0-9]|4[57]|5[0-35-9]|7[01678]|8[0-9])\\d{8}$"; 39 if (!reg.test(phone)) { 40 $("#phoneMsg").text("手机号不合法!"); 41 return; 42 } 43 } 44 if (qq=="") { 45 $("#qqMsg").text("QQ号不能为空!"); 46 return; 47 } 48 if (school=="") { 49 $("#schoolMsg").text("学校不能为空!"); 50 } 51 if (validCode == "") { 52 $("#validateCodeMsg").text("验证码不能为空!"); 53 return; 54 } 55 if (password == "") { 56 $("#userPasswordMsg").text("密码不能为空!"); 57 return; 58 } 59 if (password != password2) { 60 $("#pwdError").text("两次输入的密码不一致!"); 61 return; 62 } 63 64 $.ajax({ 65 url: "UserController.ashx", type: "post", 66 dataType: "json", 67 data: { action: "registerSubmit", username: username, password: password, email: email, validCode: validCode, phone: phone, qq: qq, school: school }, 68 success: function (data) { 69 if (data.status == "ok") { 70 alert("注册成功"); 71 window.location.href = "index.shtml"; 72 } 73 else { 74 alert("注册失败:" + data.msg); 75 //只有这句话刷新验证码是不安全的,需要后台也刷新验证码 76 $("#imgValidCode").attr("src", "UserController.ashx?action=createValideCode&id=" + new Date()); 77 78 79 } 80 }, 81 error: function () { 82 alert("注册请求失败"); 83 } 84 }); 85 86 }); 87 88 $("#password").keyup(function () { 89 90 var level = checkPasswordLevel($("#password").val()); 91 switch (level) { 92 case 1: { 93 $("#td1").css("backgroundColor", "#FF8000"); 94 $("#td2").css("backgroundColor", ""); 95 $("#td3").css("backgroundColor", ""); 96 } 97 break; 98 case 2: { 99 $("#td1").css("backgroundColor", ""); 100 $("#td2").css("backgroundColor", "#FF4000"); 101 $("#td3").css("backgroundColor", ""); 102 } 103 break; 104 case 3: { 105 $("#td1").css("backgroundColor", ""); 106 $("#td2").css("backgroundColor", ""); 107 $("#td3").css("backgroundColor", "#5CB85C"); 108 } 109 break; 110 } 111 }) 112 $("#password2").blur(function () { 113 var password = $("#password").val(); 114 var password2 = $("#password2").val(); 115 if (password != password2) { 116 $("#pwdError").text("两次输入的密码不一致!"); 117 return; 118 } 119 else { 120 $("#pwdError").text(""); 121 } 122 }); 123 //todo:焦点离开email的时候,编写正则表达式检查email地址是否正确 124 //todo:前台用户的注册:邮件发送激活码,一个邮件只能注册一个账号。 125 $("#email").blur(function () { 126 var email = $(this).val(); 127 if (email == "") { 128 $("#userEmailMsg").text("邮箱不能为空!"); 129 return; 130 } 131 else { 132 var re = /^\w+@[a-z0-9]+(\.[a-z]+){1,3}$/; 133 if (re.test(email)) { 134 $.ajax({ 135 url: "UserController.ashx", type: "post", dataType: "json", 136 data: { action: "checkEmail", email: email }, 137 success: function (data) { 138 if (data.status == "ok") { 139 $("#userEmailMsg").text(data.msg); 140 return; 141 } 142 else if (data.status == "error") { 143 $("#userEmailMsg").text(data.msg); 144 return; 145 } 146 }, 147 error: function () { 148 $("#userEmailMsg").text("检查邮箱是否可用失败"); 149 return; 150 } 151 }) 152 } 153 else { 154 $("#userEmailMsg").text("邮箱的格式不正确!"); 155 return; 156 } 157 } 158 159 }); 160 $("#username").keyup(function () { 161 $("#userNameMsg").text(""); 162 }); 163 $("#email").keyup(function () { 164 $("#userEmailMsg").text(""); 165 }); 166 //检查用户名是否可用。 167 $("#username").blur(function () { 168 var username = $("#username").val(); 169 if (username == "") { 170 $("#userNameMsg").text("用户名不能为空!"); 171 return; 172 } 173 $.ajax({ 174 url: "UserController.ashx", type: "post", dataType: "json", 175 data: { action: "checkUserName", username: username }, 176 success: function (data) { 177 if (data.status == "ok") { 178 $("#userNameMsg").text("此用户名可用"); 179 } 180 else { 181 $("#userNameMsg").text("此用户名不可用,请换用其他用户名"); 182 } 183 }, 184 error: function () { 185 $("#userNameMsg").text("检查用户名是否可用失败"); 186 } 187 }); 188 }); 189 }); 190 </script> 191 <style type="text/css"> 192 #table td 193 { 194 width: 70px; 195 height: 12px; 196 background-color: lightgray; 197 border: 1px solid #D0D0D0; 198 color: #BBBBBB; 199 line-height: 9px; 200 color: white; 201 font-size: 12px; 202 font-family: 微软雅黑; 203 } 204 </style> 205 <!--#include file="/html/headend.html"--> 206 <!--#include file="/html/navbar.html"--> 207 <main id="post-page" class="container mainContent" role="main"> 208 <table> 209 <tr><td><label for="username">用户名:</label></td><td><input type="text" id="username" /><span id="userNameMsg"></span></td></tr> 210 <tr> 211 <td><label for="password">输入密码:</label></td> 212 <td> 213 <input type="password" id="password" /><span id="userPasswordMsg"></span> 214 <table id="table" border="0" cellpadding="0" cellspacing="1" style="display: inline-table;"> 215 <tr> 216 <td id="td1" style="height: 12px; text-align: center;">弱</td> 217 <td id="td2" style="height: 12px; text-align: center;">中</td> 218 <td id="td3" style="height: 12px; text-align: center;">强</td> 219 </tr> 220 </table> 221 </td> 222 223 </tr> 224 <tr><td><label for="password2">再次输入密码:</label></td><td><input type="password" id="password2" /><label id="pwdError"></label></td></tr> 225 <tr><td><label>邮箱:</label></td><td><input type="text" id="email" /><span id="userEmailMsg"></span></td></tr> 226 <tr><td><label>手机号:</label></td><td><input type="text" id="PhoneNum" /><span id="phoneMsg"></span></td></tr> 227 <tr><td><label>QQ:</label></td><td><input type="text" id="qq" /><span id="qqMsg"></span></td></tr> 228 <tr><td><label>学校:</label></td><td><input type="text" id="school"/><span id="schoolMsg"></span></td></tr> 229 230 <tr><td><label>验证码:</label></td><td><input type="text" id="validCode" /><img src="UserController.ashx?action=createValideCode" id="imgValidCode" /><span id="validateCodeMsg"></span></td></tr> 231 <tr><td><input type="button" id="btnReg" value="注册" /></td><td></td></tr> 232 </table> 233 </main> 234 <!--#include file="/html/foot.html"-->
一般处理程序:
/// <summary> /// 用户注册 /// </summary> /// <param name="context"></param> public void registerSubmit(HttpContext context) { //获取请求报文中从浏览器传过来的数据 string username = context.Request["username"]; string password = context.Request["password"]; string email = context.Request["email"]; string phone = context.Request["phone"]; string qq = context.Request["qq"]; string school = context.Request["school"]; string validCode = context.Request["validCode"]; //注意:通过js进行数据合法性校验,只是为了用户用起来方便而已,在服务器中校验才能保证数据的安全。 if (string.IsNullOrWhiteSpace(phone)) { AjaxHelper.WriteJson(context.Response, "error", "手机号不能为空!"); return; } if (string.IsNullOrWhiteSpace(qq)) { AjaxHelper.WriteJson(context.Response,"error","QQ号不能为空!"); return; } if (string.IsNullOrWhiteSpace(school)) { AjaxHelper.WriteJson(context.Response,"error","学校不能为空!"); return; } if (string.IsNullOrWhiteSpace(username)) { AjaxHelper.WriteJson(context.Response,"error","用户名不能为空!"); return; } if (string.IsNullOrWhiteSpace(password)) { AjaxHelper.WriteJson(context.Response,"error","密码不能为空!"); return; } if (string.IsNullOrWhiteSpace(email)) { AjaxHelper.WriteJson(context.Response,"error","邮箱不能为空!"); return; } if (string.IsNullOrWhiteSpace(validCode)) { AjaxHelper.WriteJson(context.Response,"error","验证码不能为空!"); return; } if (validCode!=CommonHelper.GetValidCode(context)) { AjaxHelper.WriteJson(context.Response,"error","验证码错误"); CommonHelper.ResetValidCode(context); return; } T_UsersBLL userBll = new T_UsersBLL(); if (!userBll.CheckUserNameOnReg(username)) { AjaxHelper.WriteJson(context.Response,"error","当前用户不可用"); return; } if (!userBll.CheckEmailOnReg(email)) { AjaxHelper.WriteJson(context.Response,"error","该邮箱已被注册!"); return; } //插入数据库(T_Users) long userId = userBll.AddNewUser(username, password, email,phone,qq,school); //激活码 Random rand = new Random(); string activeCode = rand.Next(10000,99999).ToString(); //方案一:把激活码存入到数据库(T_UserActiveCodes) T_UserActiveCodes userActiveCode = new T_UserActiveCodes(); userActiveCode.UserName = username; userActiveCode.RegDateTime = DateTime.Now; userActiveCode.ActiveCode = activeCode; //插入到激活码数据表中 new T_UserActiveCodesBLL().Add(userActiveCode); //邮件链接和正文 string activeUrl = "http://localhost:22585/UserController.ashx?action=active&username=" + context.Server.UrlEncode(username) + "&activeCode=" + activeCode; string emailBody = "尊敬的" + username + "您好,请点击下面的链接激活您的账户" + "<a href=‘" + activeUrl + "‘>点击此链接激活您的账号</a>,如果链接打不开,则把下面的地址复制到浏览器中进行激活:" + activeUrl; //发送邮件 FrontHelper.SendEmail(email,"请激活您的***账号",emailBody); /* * 测试了网易和qq邮箱,能发是能发但是,对所发的邮件标题和内容是有限制的,不能发很容就能识别出来是垃圾邮件的邮件,标题和正文要正式点,负责不会接收到。 * 在生产环境中:无法使用163、qq等这种免费邮箱发送大量的邮件。 * Edm专用服务器,掏钱就ok。 SendCloud、Comm100、yiye */
邮件发送代码:
public static void SendEmail(string toEmail, string subject, string body) { string smtpServer = ConfigurationManager.AppSettings["SmtpServer"]; string smtpFrom = ConfigurationManager.AppSettings["SmtpFrom"]; string smtpUserName = ConfigurationManager.AppSettings["SmtpUserName"]; string smtpPassword = ConfigurationManager.AppSettings["SmtpPassword"]; MailMessage mailObj = new MailMessage(); mailObj.IsBodyHtml = true; //from:abc@qq.com mailObj.From = new MailAddress(smtpFrom); //发送人邮箱地址 mailObj.To.Add(toEmail); //收件人邮箱地址 mailObj.Subject = subject; //主题 mailObj.Body = body; //正文 SmtpClient smtp = new SmtpClient();//通过.Net内置的SmtpClient类和邮件服务器进行通讯,发送邮件。 //是和发邮件方的smtp通讯,由发邮件方的邮件服务器和收邮件方的邮件服务器通讯进行邮件的转接。 smtp.Host = smtpServer; //smtp服务器名称 smtp.UseDefaultCredentials = true; smtp.Credentials = new NetworkCredential(smtpUserName, smtpPassword); //发送人的登录名和密码 smtp.Send(mailObj); } 关于邮箱的账号和密码最好配置到配置文件中。为了安全。
好好思考一下这样写的缺陷在哪?不仅有缺陷而且还有安全问题,有哪些安全问题?如果用户量大的话这样设计是否合理?会对什么有压力?如果不合理该如何优化?
首先我们来分析一下:
上面的方法是在用户表的基础上再增加一个字段,用来存激活码。这样合理吗?
由于激活码只用一次,所以在用户表的基础上再增加一个字段会麻烦一下,之前的功能会有影响。那到底该怎么解决比较好?
这时候Redis的好处就非常明显了,key-value数据库,并且还能设置数据的有效时间,很好的解决了上面遇到的问题,只需要改动上面很少的一部分代码就可以实现想要的功能。
代码如下:
1 //方案二:把激活码存入的Redis中(最佳) 2 //Redis代替数据库保存UserName和激活码的字典结构 3 using (var client = RedisManager.ClientManager.GetClient()) 4 { 5 client.Set<string>(ACTIVECODE_PREFIX + username, activeCode, DateTime.Now.AddMinutes(30)); 6 }
如果到这里真的就OK了吗?我在这里买个关子,大家可以想想为什么我要添加下面的这段代码:
1 //把注册用户信息,放入消息队列。便于另外一个程序来获取消息队列数据,发送邮件 2 using (var client = RedisManager.ClientManager.GetClient()) 3 { 4 string info = username + "|" + email; 5 client.EnqueueItemOnList("NewRegUsers", info); 6 }
请大家先好好思考一下,问题有哪些,在评论区可以提出来,后面我会一一分析,因为后面会提到很多东西,比如并发量、定时器、Redis的消息队列、多线程、Windows服务等等。尽情期待~~~~~~~~~~
尽情期待~~~~~~~~~~
尽情期待~~~~~~~~~~
标签:contain include c51 lsp etc pcl mil 规范 set
原文地址:http://www.cnblogs.com/runningsmallguo/p/5871412.html