构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(12)-系统日志和异常的处理②
上一讲我们做了日志与异常的结果显示列表,这一节我们讲要把他应用系统中来。
首先我们在App.Common类库中创建一个通用类ResultHelper,这个类里面写了,获取一个GUID,获取当前时间,处理字符串等操作,虽然我们目前要用到的一个就是获取GUID但是以后我们可能还要用到别的,所以我都把他放进入了
然后在App.Admin创建一个核心文件夹,Core,放入LogHandler这个类是主要是写入日志,避免在每次都要实例化这个类,我把他封装起来,大家一看就知道。
然后修改Controller的Create方法,代码如下一一给出。
using System;
using System.Web;
using System.Text.RegularExpressions; namespace App.Common
{
public class ResultHelper
{
/// <summary>
/// 创建一个全球唯一的32位ID
/// </summary>
/// <returns>ID串</returns>
public static string NewId
{
get
{
string id = DateTime.Now.ToString("yyyyMMddHHmmssfffffff");
string guid = Guid.NewGuid().ToString().Replace("-", "");
id += guid.Substring(, );
return id;
}
}
public static string NewTimeId
{
get
{
string id = DateTime.Now.ToString("yyyyMMddHHmmssfffffff");
return id;
}
}
/// <summary>
/// 截取字符串
/// </summary>
/// <param name="value">字符串</param>
/// <param name="length">剩下长度</param>
/// <returns>指定字符串并加...</returns>
public static string SubValue(string value, int length)
{
if (value.Length > length)
{
value = value.Substring(, length); value = value + "..."; return NoHtml(value);
}
else { return NoHtml(value); }
}
//还原的时候
public static string InputText(string inputString)
{ if ((inputString != null) && (inputString != String.Empty))
{
inputString = inputString.Trim();
//if (inputString.Length > maxLength)
//inputString = inputString.Substring(0, maxLength);
inputString = inputString.Replace("<br>", "\n");
inputString = inputString.Replace("&", "&");
inputString = inputString.Replace("'", "''");
inputString = inputString.Replace("<", "<");
inputString = inputString.Replace(">", ">");
inputString = inputString.Replace("chr(60)", "<");
inputString = inputString.Replace("chr(37)", ">");
inputString = inputString.Replace("\"", """);
inputString = inputString.Replace(";", ";"); return inputString;
}
else
{
return "";
} }
//添加的时候
public static string OutputText(string outputString)
{ if ((outputString != null) && (outputString != String.Empty))
{
outputString = outputString.Trim();
outputString = outputString.Replace("&", "&");
outputString = outputString.Replace("''", "'");
outputString = outputString.Replace("<", "<");
outputString = outputString.Replace(">", ">");
outputString = outputString.Replace("<", "chr(60)");
outputString = outputString.Replace(">", "chr(37)");
outputString = outputString.Replace(""", "\"");
outputString = outputString.Replace(";", ";");
outputString = outputString.Replace("\n", "<br>");
return outputString;
}
else
{
return "";
}
}
/// <summary>
/// 去除HTML标记
/// </summary>
/// <param name="NoHTML">包括HTML的源码 </param>
/// <returns>已经去除后的文字</returns>
public static string NoHtml(string Htmlstring)
{
//删除脚本
Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
//删除HTML
Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"…", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"—", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"“", "", RegexOptions.IgnoreCase);
Htmlstring.Replace("<", "");
Htmlstring = Regex.Replace(Htmlstring, @"”", "", RegexOptions.IgnoreCase);
Htmlstring.Replace(">", "");
Htmlstring.Replace("\r\n", "");
Htmlstring = HttpContext.Current.Server.HtmlEncode(Htmlstring).Trim();
return Htmlstring; }
/// <summary>
/// 格式化文本(防止SQL注入)
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string Formatstr(string html)
{
System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"<script[\s\S]+</script *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex2 = new System.Text.RegularExpressions.Regex(@" href *= *[\s\S]*script *:", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex3 = new System.Text.RegularExpressions.Regex(@" on[\s\S]*=", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex4 = new System.Text.RegularExpressions.Regex(@"<iframe[\s\S]+</iframe *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex5 = new System.Text.RegularExpressions.Regex(@"<frameset[\s\S]+</frameset *>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex10 = new System.Text.RegularExpressions.Regex(@"select", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex11 = new System.Text.RegularExpressions.Regex(@"update", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
System.Text.RegularExpressions.Regex regex12 = new System.Text.RegularExpressions.Regex(@"delete", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
html = regex1.Replace(html, ""); //过滤<script></script>标记
html = regex2.Replace(html, ""); //过滤href=javascript: (<A>) 属性
html = regex3.Replace(html, " _disibledevent="); //过滤其它控件的on...事件
html = regex4.Replace(html, ""); //过滤iframe
html = regex10.Replace(html, "s_elect");
html = regex11.Replace(html, "u_pudate");
html = regex12.Replace(html, "d_elete");
html = html.Replace("'", "’");
html = html.Replace(" ", " ");
return html;
}
/// <summary>
/// 检查SQL语句合法性
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public static bool ValidateSQL(string sql, ref string msg)
{
if (sql.ToLower().IndexOf("delete") > )
{
msg = "查询参数中含有非法语句DELETE";
return false;
}
if (sql.ToLower().IndexOf("update") > )
{
msg = "查询参数中含有非法语句UPDATE";
return false;
} if (sql.ToLower().IndexOf("insert") > )
{
msg = "查询参数中含有非法语句INSERT";
return false;
}
return true;
}
//获取当前时间
public static DateTime NowTime
{
get
{
return DateTime.Now;
}
} /// <summary>
/// 将日期转换成字符串
/// </summary>
/// <param name="dt">日期</param>
/// <returns>字符串</returns>
public static string DateTimeConvertString(DateTime? dt)
{
if (dt == null)
{
return "";
}
else
{
return Convert.ToDateTime(dt.ToString()).ToShortDateString();
}
}
/// <summary>
/// 将字符串转换成日期
/// </summary>
/// <param name="str">字符串</param>
/// <returns>日期</returns>
public static DateTime? StringConvertDatetime(string str)
{
if (str == null)
{
return null ;
}
else
{
try
{
return Convert.ToDateTime(str);
}
catch {
return null;
}
}
} public static string GetUserIP()
{
if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
return System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(new char[] { ',' })[];
else
return System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
}
}
ResultHelper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using App.Common;
using App.DAL;
using App.IBLL;
using App.Models;
using Microsoft.Practices.Unity; namespace App.Admin
{
public static class LogHandler
{
[Dependency]
public static ISysLogBLL logBLL { get; set; }
/// <summary>
/// 写入日志
/// </summary>
/// <param name="oper">操作人</param>
/// <param name="mes">操作信息</param>
/// <param name="result">结果</param>
/// <param name="type">类型</param>
/// <param name="module">操作模块</param>
public static void WriteServiceLog(string oper, string mes, string result, string type, string module)
{ SysLog entity = new SysLog();
entity.Id = ResultHelper.NewId;
entity.Operator = oper;
entity.Message = mes;
entity.Result = result;
entity.Type = type;
entity.Module = module;
entity.CreateTime = ResultHelper.NowTime;
using (SysLogRepository logRepository = new SysLogRepository())
{
logRepository.Create(entity);
} }
}
}
LogHandler
[HttpPost]
public JsonResult Create(SysSampleModel model)
{ if (m_BLL.Create(model))
{
LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name, "成功", "创建", "样例程序");
return Json(, JsonRequestBehavior.AllowGet);
}
else
{
LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name, "失败", "创建", "样例程序");
return Json(, JsonRequestBehavior.AllowGet);
} }
SysSampleController
同时App.Common要引用程序集System.Web
运行添加一条记录,然后打开我们的日志模块,OK,日志记录完成了,有点简单。
接下来是异常,上一讲说到,异常我们放在BLL中处理,然后我们把错误或者异常信息返回到Controller中被日志记录,当然异常他是在BLL层被记录的。
我们需要一个异常的集合类,来记录BLL层和DAL层,有时候DAL也要处理异常,所以我们也要用到ref 引用传递,貌似ref我们很喜欢,呵呵
见代码,在App.Common创建一个异常集合类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace App.Common
{
public class ValidationError
{
public ValidationError() { }
public string ErrorMessage { get; set; } }
public class ValidationErrors : List<ValidationError>
{
/// <summary>
/// 添加错误
/// </summary>
/// <param name="errorMessage">信息描述</param>
public void Add(string errorMessage)
{
base.Add(new ValidationError { ErrorMessage = errorMessage });
}
/// <summary>
/// 获取错误集合
/// </summary>
public string Error
{
get {
string error = "";
this.All(a => {
error += a.ErrorMessage;
return true;
});
return error;
}
}
}
}
ValidationErrorHelper.cs
我们也要创建一个封装好的异常写入,类似与Log的LogHandler封装但我们放在BLL中,因为我们以后的其他项目的BLL要引用,这一步要考虑到。
在BLL中创建文件夹Core,写入以下类,BLL引用程序集System.Web里面用到了http的一些方法
using System;
using System.Web.Configuration;
using App.Models;
using System.IO;
using System.Text;
using App.Common; namespace App.BLL.Core
{ /// <summary>
/// 写入一个异常错误
/// </summary>
/// <param name="ex">异常</param>
public static class ExceptionHander
{
/// <summary>
/// 加入异常日志
/// </summary>
/// <param name="ex">异常</param>
public static void WriteException(Exception ex)
{ try
{
using (DBContainer db = new DBContainer())
{
SysException model = new SysException()
{
Id = ResultHelper.NewId,
HelpLink = ex.HelpLink,
Message = ex.Message,
Source = ex.Source,
StackTrace = ex.StackTrace,
TargetSite = ex.TargetSite.ToString(),
Data =ex.Data.ToString(),
CreateTime = ResultHelper.NowTime };
db.SysException.AddObject(model);
db.SaveChanges();
}
}
catch (Exception ep)
{
try
{
//异常失败写入txt
string path = @"~/exceptionLog.txt";
string txtPath = System.Web.HttpContext.Current.Server.MapPath(path);//获取绝对路径
using (StreamWriter sw = new StreamWriter(txtPath, true, Encoding.Default))
{
sw.WriteLine((ex.Message + "|" + ex.StackTrace + "|" + ep.Message + "|" + DateTime.Now.ToString()).ToString());
sw.Dispose();
sw.Close();
}
return;
}
catch { return; }
} }
} }
ExceptionHander
此异常当处理也异常时候,将在网站根目录下写入一个txt文件。
创建一个全局变量
ValidationErrors errors = new ValidationErrors();
我们要用引用传递,所以要修改IBLL和BLL的Create方法,如下
ISysSampleBLL : bool Create(ref ValidationErrors errors, SysSampleModel model);
SysSampleBLL :
/// <summary>
/// 创建一个实体
/// </summary>
/// <param name="errors">持久的错误信息</param>
/// <param name="model">模型</param>
/// <returns>是否成功</returns>
/// <summary>
/// 创建一个实体
/// </summary>
/// <param name="errors">持久的错误信息</param>
/// <param name="model">模型</param>
/// <returns>是否成功</returns>
public bool Create(ref ValidationErrors errors, SysSampleModel model)
{
try
{
SysSample entity = Rep.GetById(model.Id);
if (entity != null)
{
errors.Add("主键重复");
return false;
}
entity = new SysSample();
entity.Id = model.Id;
entity.Name = model.Name;
entity.Age = model.Age;
entity.Bir = model.Bir;
entity.Photo = model.Photo;
entity.Note = model.Note;
entity.CreateTime = model.CreateTime; if (Rep.Create(entity) == )
{
return true;
}
else
{
errors.Add("插入失败");
return false;
}
}
catch (Exception ex)
{
errors.Add(ex.Message);
ExceptionHander.WriteException(ex);
return false;
}
}
修改Controller
[HttpPost]
public JsonResult Create(SysSampleModel model)
{
if (m_BLL.Create(ref errors, model))
{
LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name, "成功", "创建", "样例程序");
return Json(, JsonRequestBehavior.AllowGet);
}
else
{
string ErrorCol = errors.Error;
LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name + "," + ErrorCol, "失败", "创建", "样例程序");
return Json(, JsonRequestBehavior.AllowGet);
} }
注意:ExceptionHander.WriteException(ex);这里是写入异常信息
OK,你现在可以创建一条新的记录和插入一个ID大于50个字符的记录,让他记录日志和异常了。
显然我们的失败错误提示已经不符合国情了。我们返回的json格式是0和1我们要返回多个值了,比如1和成功创建,0和失败了啊,这样的2个值怎么办?
controller能把datagrid传过来的东西用类来接受,那么反过来想,js也能把controller发出去的值分解,创建一个序列化的类
在App.Common类库中创建JsonHandler帮助类,里面有2个重载,一个是返回3个值一个是2个值的。
所以当我们要返回订单的数量和总价格的时候,我们将用到类似的手段
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace App.Common
{
public class JsonHandler
{ public static JsonMessage CreateMessage(int ptype,string pmessage,string pvalue)
{
JsonMessage json = new JsonMessage()
{
type = ptype,
message = pmessage,
value = pvalue
};
return json;
}
public static JsonMessage CreateMessage(int ptype, string pmessage)
{
JsonMessage json = new JsonMessage()
{
type = ptype,
message = pmessage,
};
return json;
}
} public class JsonMessage
{
public int type{get;set;}
public string message{get;set;}
public string value{get;set;}
}
}
JsonHandler
再次修改Controller的Create
[HttpPost]
public JsonResult Create(SysSampleModel model)
{
if (m_BLL.Create(ref errors, model))
{
LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name, "成功", "创建", "样例程序");
return Json(JsonHandler.CreateMessage(, "插入成功"), JsonRequestBehavior.AllowGet);
}
else
{
string ErrorCol = errors.Error;
LogHandler.WriteServiceLog("虚拟用户", "Id:" + model.Id + ",Name:" + model.Name + "," + ErrorCol, "失败", "创建", "样例程序");
return Json(JsonHandler.CreateMessage(, "插入失败" + ErrorCol), JsonRequestBehavior.AllowGet);
} }
修改SysSample的Create的JS部分
<script type="text/javascript">
$(function () {
$("#btnSave").click(function () {
if ($("#CreateForm").valid()) {
$.ajax({
url: "/SysSample/Create",
type: "Post",
data: $("#CreateForm").serialize(),
dataType: "json",
success: function (data) {
if (data.type == ) {
window.parent.frameReturnByMes(data.message);
window.parent.frameReturnByReload(true);
window.parent.frameReturnByClose()
}
else {
window.parent.frameReturnByMes(data.message);
}
}
});
}
return false;
});
});
</script>
由于时间关系,这一讲就先到这里吧!这一讲其实比较仓促。不懂的留言
你需要继续做的就是在删除,编辑等操作也加入这些的。这点留给大家自己表现吧....
下一讲是全局异常的捕获。
构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(12)-系统日志和异常的处理②的更多相关文章
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与目录(持续更新中...)
转自:http://www.cnblogs.com/ymnets/p/3424309.html 曾几何时我想写一个系列的文章,但是由于工作很忙,一直没有时间更新博客.博客园园龄都1年了,却一直都是空空 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(48)-工作流设计-起草新申请
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(48)-工作流设计-起草新申请 系列目录 创建新表单之后,我们就可以起草申请了,申请按照严格的表单步骤和分 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(47)-工作流设计-补充
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(47)-工作流设计-补充 系列目录 补充一下,有人要表单的代码,这个用代码生成器生成表Flow_Form表 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(46)-工作流设计-设计分支
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(46)-工作流设计-设计分支 系列目录 步骤设置完毕之后,就要设置好流转了,比如财务申请大于50000元( ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(45)-工作流设计-设计步骤
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(45)-工作流设计-设计步骤 系列目录 步骤设计很重要,特别是规则的选择. 我这里分为几个规则 1.按自行 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(44)-工作流设计-设计表单
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(44)-工作流设计-设计表单 系列目录 设计表单是比较复杂的一步,完成一个表单的设计其实很漫长,主要分为四 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(43)-工作流设计-字段分类设计
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(43)-工作流设计-字段分类设计 系列目录 建立好42节的表之后,每个字段英文表示都是有意义的说明.先建立 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(42)-工作流设计01
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(42)-工作流设计01 工作流在实际应用中还是比较广泛,网络中存在很多工作流的图形化插件,可以做到拉拽的工 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-【过滤器+Cache】
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-[过滤器+Cache] 系列目录 上次的探讨没有任何结果,我浏览了大量的文章 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(41)-组织架构
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(41)-组织架构 本节开始我们要实现工作流,此工作流可以和之前的所有章节脱离关系,也可以紧密合并. 我们当 ...
随机推荐
- C# 正则表达式大全
文章导读 正则表达式的本质是使用一系列特殊字符模式,来表示某一类字符串.正则表达式无疑是处理文本最有力的工具,而.NET提供的Regex类实现了验证正则表达式的方法.Regex 类表示不可变(只读)的 ...
- lua 学习笔记(1)
一.lua函数赋值与函数调用 在lua中函数名也是作为一种变量出现的,即函数和所有其他值一样都是匿名的,当要使用某个函数时,需要将该函数赋值给一个变量,这样在函数块的其他地方就可以通过 ...
- 【原创经验分享】WCF之消息队列
最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...
- js学习之类型识别
用来判别类型的方法有好多,整理了一下4种方法,平时用的时候,在不同情景下,还是要结合着使用的. 方法一 typeof:可以识别标准类型,除了Null:不能识别具体的对象类型,除了Function &l ...
- 利用Select2优化@Html.ListBoxFor显示,学会用MultiSelectList
最近需要用到多选框,Asp.Net MVC自带的@Html.ListBox或@Html.ListBoxFor的显示效果太差,于是找到了Select2进行优化,并正式了解了多选框的操作方法. 首先介绍多 ...
- .NET面试题集锦①(Part一)
一.前言部分 文中的问题及答案多收集整理自网络,不保证100%准确,还望斟酌采纳. 1.面向对象的思想主要包括什么? 答:任何事物都可以理解为对象,其主要特征: 继承.封装.多态.特点:代码好维护,安 ...
- Tomcat常见问题及常用命令
很长时间不用tomcat好多命令都忘记了,所以准备自己记录下来,以便参考.刚好也希望可以开始养成记博客的好习惯. 1.查看java的版本号 进入java的安装目录后,使用命令:java -versio ...
- Three.JS 从世界坐标系转换到屏幕坐标系
var projector = new THREE.Projector(); var world_vector = new THREE.Vector3(0,0,1); var vector = pro ...
- JavaScript对象和数组
1.JavaScript中有两个非常重要的数据类型是对象和数组. 通过"."或者"[]"来访问对象属性 举例:var book = { topic:" ...
- Atitit.软件开发的三层结构isv金字塔模型
Atitit.软件开发的三层结构isv金字塔模型 第一层,Implements 层,着重与功能的实现.. 第二次,spec层,理论层,设计规范,接口,等.流程.方法论 顶层,val层,价值观层,原则, ...