简述
本文转自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
71using 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
2Install-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>