简述
本文转自http://yuangang.cnblogs.com并加以整理。 本文用到了Spring的IOC和DI、接口的使用、实现
索引
项目开始
一、Log4net
log4net是一个功能著名的开源日志记录组件。利用log4net可以方便地将日志信息记录到文件、控制台、Windows事件日志和数据库(包括MS SQL Server, Access, Oracle9i, Oracle8i, DB2, SQLite)中。并且我们还可以记载控制要记载的日志级别,可以记载的日志类别包括:FATAL(致命错误)、ERROR(一般错误)、WARN(警告)、INFO(一般信息)、DEBUG(调试信息)。大部分的日志记录都是记录到文件。我们主要记录到数据库,这比较有利于我们的管理员查看日志事件。
- 通过NuGet安装log4net到Webpage中 - Install-Package log4net -ProjectName WebPage
- 在项目的程序集信息描述文件中(properties/assembly.cs),设置Log4net的可记录属性 - 1 - [] 
- 在Webpage程序根目录添加log4net的配置文件log4net.config: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295- <?xml version="1.0" encoding="utf-8"?> 
 <configuration>
 <configSections>
 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
 </configSections>
 <log4net>
 <root>
 <level value="ALL"/>
 </root>
 <logger name="dblog" additivity="false">
 <level value="ALL"/>
 <appender-ref ref="SqlServerAppender" />
 </logger>
 <!--Oracle数据库-->
 <appender name="OracleAppender" type="log4net.Appender.AdoNetAppender">
 <!-- Oracle数据源-->
 <connectionType value="Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
 <!-- Oracle连接字符串-->
 <connectionString value="DATA SOURCE=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.3.206)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)));PASSWORD=watdb;PERSIST SECURITY INFO=True;USER ID=watdb;"/>
 <commandText value="INSERT INTO SYS_LOG(Dates,Levels,Logger,Message,Exception,ClientUser,ClientIP,RequestUrl,Action)VALUES(:Dates,:Levels,:Logger,:Message,:Exception,:ClientUser,:ClientIP,:RequestUrl,:Action)"/>
 <!--
 设置缓存区大小
 1表明有一条日志就要写入
 如果10就表示日志到达10条时一起写入
 -->
 <bufferSize value="0"/>
 <parameter>
 <parameterName value=":Dates" />
 <dbType value="DateTime" />
 <layout type="log4net.Layout.RawTimeStampLayout"/>
 </parameter>
 <parameter>
 <parameterName value=":Levels" />
 <dbType value="String" />
 <size value="50" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%level" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value=":Logger" />
 <dbType value="String" />
 <size value="200" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%logger" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value=":Message" />
 <dbType value="String" />
 <size value="4000" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%message" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value=":Exception" />
 <dbType value="String" />
 <size value="4000" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%exception" />
 </layout>
 </parameter>
 <!--DIY-->
 <parameter>
 <parameterName value=":ClientUser" />
 <dbType value="String" />
 <size value="100" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{ClientUser}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value=":ClientIP" />
 <dbType value="String" />
 <size value="20" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{ClientIP}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value=":RequestUrl" />
 <dbType value="String" />
 <size value="500" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{RequestUrl}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value=":Action" />
 <dbType value="String" />
 <size value="20" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{Action}" />
 </layout>
 </parameter>
 </appender>
 <!--Sqlite数据库-->
 <appender name="SqliteAppender" type="log4net.Appender.AdoNetAppender">
 <bufferSize value="0" />
 <connectionType value="System.Data.SQLite.SQLiteConnection, System.Data.SQLite, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
 <connectionString value="Data Source=|DataDirectory|test.db;Version=3;" />
 <commandText value="INSERT INTO Log (Date, Level, Logger, ClientUser,ClientIP, RequestUrl,Action, Message, Exception) VALUES (@Date, @Level, @Logger,@ClientUser,@ClientIP, @RequestUrl,@Action, @Message, @Exception)" />
 <parameter>
 <parameterName value="@Date" />
 <dbType value="DateTime" />
 <layout type="log4net.Layout.RawTimeStampLayout" />
 </parameter>
 <parameter>
 <parameterName value="@Level" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%level" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Logger" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%logger" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@ClientUser" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{ClientUser}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@ClientIP" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{ClientIP}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@RequestUrl" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{RequestUrl}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Action" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%property{Action}" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Message" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%message" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Exception" />
 <dbType value="String" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%exception" />
 </layout>
 </parameter>
 </appender>
 <!--SqlServer数据库-->
 <appender name="SqlServerAppender" type="log4net.Appender.AdoNetAppender">
 <!-- SqlServer数据源-->
 <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
 <!-- SqlServer连接字符串-->
 <connectionString value="data source=.;initial catalog=wkmvc_db;integrated security=false;persist security info=True;User ID=sa_wkmvc;Password=123456" />
 <commandText value="INSERT INTO SYS_LOG(Dates,Levels,Logger,ClientUser,ClientIP,RequestUrl,Action,Message,Exception)VALUES(@Dates,@Levels,@Logger,@ClientUser,@ClientIP,@RequestUrl,@Action,@Message,@Exception)"/>
 <!--
 设置缓存区大小
 1表明有一条日志就要写入
 如果10就表示日志到达10条时一起写入
 -->
 <bufferSize value="0"/>
 <parameter>
 <parameterName value="@Dates" />
 <dbType value="DateTime" />
 <layout type="log4net.Layout.RawTimeStampLayout" />
 </parameter>
 <parameter>
 <parameterName value="@Levels" />
 <dbType value="String" />
 <size value="50" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%level" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Logger" />
 <dbType value="String" />
 <size value="255" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%logger" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Message" />
 <dbType value="String" />
 <size value="4000" />
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%message" />
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Exception" />
 <dbType value="String" />
 <size value="2000" />
 <layout type="log4net.Layout.ExceptionLayout" />
 </parameter>
 <!--DIY-->
 <parameter>
 <parameterName value="@ClientUser" />
 <dbType value="String" />
 <size value="100" />
 <layout type="log4net.Layout.PatternLayout" >
 <param name="ConversionPattern" value="%property{ClientUser}"/>
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@ClientIP" />
 <dbType value="String" />
 <size value="100" />
 <layout type="log4net.Layout.PatternLayout" >
 <param name="ConversionPattern" value="%property{ClientIP}"/>
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@RequestUrl" />
 <dbType value="String" />
 <size value="500" />
 <layout type="log4net.Layout.PatternLayout" >
 <param name="ConversionPattern" value="%property{RequestUrl}"/>
 </layout>
 </parameter>
 <parameter>
 <parameterName value="@Action" />
 <dbType value="String" />
 <size value="100" />
 <layout type="log4net.Layout.PatternLayout" >
 <param name="ConversionPattern" value="%property{Action}"/>
 </layout>
 </parameter>
 </appender>
 <!--记录到文件-->
 <appender name="SysAppender" type="log4net.Appender.RollingFileAppender,log4net">
 <param name="File" value="datalog" />
 <param name="AppendToFile" value="true" />
 <param name="RollingStyle" value="Date" />
 <param name="DatePattern" value="\\yyyy\\MM-dd-HH\\"SQL_"yyyy-MM-dd".log"" />
 <param name="StaticLogFileName" value="false" />
 <layout type="log4net.Layout.PatternLayout,log4net">
 <param name="ConversionPattern" value="%d - %m%n" />
 <param name="Header" value="
----------------------begin--------------------------
" />
 <param name="Footer" value="
----------------------end--------------------------
" />
 </layout>
 </appender>
 </log4net>
 <!--必须指定框架,否则不执行,新版本默认支持4.0,可修改源文件,项目属性设定为.NET FRAMEWORK2.0后,打开重新编译,去掉其中的.NET 4.0编译导致错误环节,如此只能使用在.net 2.0框架-->
 <startup>
 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
 </startup>
 </configuration>
 <!--
 调用实例
 log4net.ILog log = log4net.LogManager.GetLogger("Filelog");
 log.Info(Message);
 %m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息
 %n(new line):换行
 %d(datetime):输出当前语句运行的时刻
 %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数
 %t(thread id):当前语句所在的线程ID
 %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等
 %c(class):当前日志对象的名称
 %L:输出语句所在的行号
 %F:输出语句所在的文件名
 %-数字:表示该项的最小长度,如果不够,则用空格填充
 例如,转换模式为%r [%t]%-5p %c - %m%n 的 PatternLayout 将生成类似于以下内容的输出:
 176 [main] INFO org.foo.Bar - Located nearest gas station.
 -->
二、创建日志表SYS_LOG
上面的代码中,我们配置日志记录到了数据库的日志表SYS_LOG
| 1 | <commandText value="INSERT INTO SYS_LOG(Dates,Levels,Logger,ClientUser,ClientIP,RequestUrl,Action,Message,Exception)VALUES(@Dates,@Levels,@Logger,@ClientUser,@ClientIP,@RequestUrl,@Action,@Message,@Exception)"/> | 
我们在数据库中新建这个日志表SYS_LOG:
| 序号 | 列名 | 数据类型 | 长度 | 小数位 | 允许空 | 说明 | 
|---|---|---|---|---|---|---|
| 1 | ID | int | 4 | 0 | 否 | 主键ID | 
| 2 | DATES | datetime | 8 | 3 | 是 | 创建时间 | 
| 3 | LEVELS | nvarchar | 20 | 0 | 是 | 日志等级 | 
| 4 | LOGGER | nvarchar | 200 | 0 | 是 | 日志调用 | 
| 5 | CLIENTUSER | nvarchar | 100 | 0 | 是 | 使用用户 | 
| 6 | CLIENTIP | nvarchar | 20 | 0 | 是 | 访问IP | 
| 7 | REQUESTURL | nvarchar | 500 | 0 | 是 | 访问来源 | 
| 8 | ACTION | nvarchar | 20 | 0 | 是 | 操作动作 | 
| 9 | MESSAGE | nvarchar | 4000 | 0 | 是 | 消息 | 
| 10 | EXCEPTION | nvarchar | 4000 | 0 | 是 | 异常消息 | 
| 1 | USE [wkmvc_db] | 
三、新建用户登录控制器AccountController
- 首先添加webpage对其他3个类库的引用 
- 配置Config/controllers.xml - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- <?xml version="1.0" encoding="utf-8" ?> 
 <objects xmlns="http://www.springframework.net">
 <description>Spring注入控制器,容器指向Service层封装的接口</description>
 <!--系统管理 Begin-->
 <!--登录控制器-->
 <object type="WebPage.Areas.SysManage.Controllers.AccountController,WebPage" singleton="false">
 <property name="UserManage" ref="Service.User"/>
 </object>
 <!--系统管理 end-->
 </objects>
- 在/Areas/SysManage/Controllers下新建AccountController控制器 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71- using Common; 
 using Common.JsonHelper;
 using Service.IService;
 using System;
 using System.Web.Mvc;
 namespace WebPage.Areas.SysManage.Controllers
 {
 public class AccountController : Controller
 {
 
 /// <summary>
 /// 用户管理
 /// </summary>
 IUserManage UserManage { get; set; }
 /// <summary>
 /// 日志记录
 /// </summary>
 Common.Log4NetHelper.IExtLog log = Common.Log4NetHelper.ExtLogManager.GetLogger("dblog");
 
 
 public ActionResult Index()
 {
 return View();
 }
 /// <summary>
 /// 登录验证
 /// </summary>
 []
 public ActionResult Login(Domain.SYS_USER item)
 {
 var json = new JsonHelper() { Msg = "登录成功", Status = "n" };
 try
 {
 //调用登录验证接口 返回用户实体类
 var users = UserManage.UserLogin(item.ACCOUNT.Trim(), item.PASSWORD.Trim());
 if (users != null)
 {
 //是否锁定
 if (users.ISCANLOGIN == 1)
 {
 json.Msg = "用户已锁定,禁止登录,请联系管理员进行解锁";
 log.Warn(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
 return Json(json);
 }
 json.Status = "y";
 log.Info(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
 }
 else
 {
 json.Msg = "用户名或密码不正确";
 log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
 }
 }
 catch (Exception e)
 {
 json.Msg = e.Message;
 log.Error(Utils.GetIP(), item.ACCOUNT, Request.Url.ToString(), "Login", "系统登录,登录结果:" + json.Msg);
 }
 return Json(json, JsonRequestBehavior.AllowGet);
 }
 
 
 
 }
 }
- 添加视图SysManage/Views/Account/Index.cshtml: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77- @model Domain.SYS_USER 
 <html>
 <head>
 <meta charset="utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>后台登录</title>
 </head>
 <body>
 <div>
 <div>
 @using (Ajax.BeginForm("login", null, new AjaxOptions()
 {
 HttpMethod = "Post",
 OnBegin = "dig.Loading",
 OnSuccess = "dig.Success",
 OnFailure = "dig.Failure",
 OnComplete = "dig.Complete"
 }, new { @class = "form-signin" }))
 {
 @Html.AntiForgeryToken()
 @Html.TextBoxFor(model => model.ACCOUNT,
 new
 {
 @class = "form-control",
 @placeholder = "登录用户名",
 @maxlength = 15,
 @required = "required"
 })
 @Html.PasswordFor(model => model.PASSWORD,
 new
 {
 @class = "form-control",
 @placeholder = "登录密码",
 @maxlength = 12,
 @required = "required"
 })
 <button type="submit" id="login-button">Login</button>
 }
 </div>
 </div>
 <script type="text/javascript" src="/Content/js/jquery-1.10.2.min.js"></script>
 <script type="text/javascript" src="/Content/js/jquery.unobtrusive-ajax.min.js"></script>
 <script type="text/javascript">
 var dig = {
 Loading: function () {
 $("#login-button").attr("disabled", "disabled");;
 },
 Success: function (result) {
 if (result.Status == "y") {
 alert(result.Msg);
 } else {
 alert(result.Msg);
 dig.Complete();
 }
 },
 Failure: function () {
 alert(result.Msg);
 dig.Complete();
 },
 Complete: function () {
 $("#login-button").attr("disabled", false);
 },
 ErrorMsg: function (msg) {
 alert(msg);
 }
 };
 </script>
 </body>
 </html>
随便输入用户名密码,点击登录,如果出现如下图片,你成功了!
 
常见错误解决
有时候暴露出错误再解决问题更易于加深我们的理解和未来应对相似问题的解决能力。如果你遇到如下错误,那么恭喜你,你有这样的机会去尝试解决问题了。我总结了目前最可能遇到的几个问题并给出相应解决方案。如果你遇到其他的问题,并且感到很难解决,可以留言,咱们共同解决。
- 出现类似log4net版本不正确,一般解决方法是把用到log4net的项目、类库用nuget更新到一致,一般跟新到最新就可以 
- 未能加载System.Web.Http  - 因为我们新建的是一个空的MVC项目,缺少引用。所以通过NuGet 程序包管理器控制台添加: - 1 
 2- Install-Package Microsoft.AspNet.WebApi 
 Update-Package Microsoft.AspNet.WebApi -reinstall(存在)
- 忘记把Service或者Webpage中Config文件夹下的xml文件属性改成嵌入资源 
  
- 缺少根元素  - xml只有 - <?xml version="1.0" encoding="utf-8" ?>,在这后面至少添加上- 1 
 2- <objects xmlns="http://www.springframework.net"> 
 </objects>
- 如果缺少连接字符串,则在Domain/app.config拷贝connectionStrings添加到web.config - 1 
 2
 3- <connectionStrings> 
 <add name="Entities" connectionString="metadata=res://*/Sql_Wkdb.csdl|res://*/Sql_Wkdb.ssdl|res://*/Sql_Wkdb.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=wkmvc_db;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
 </connectionStrings>
 
