最近忙于学车,抽时间将Nop的一些公用模块添加进来,反应的一些小问题也做了修复。前篇——基于nopCommerce的开发框架(附源码)http://www.cnblogs.com/dreling/p/6906688.html
  最新的代码已经同布到GitHub:https://github.com/dreling8/Nop.Framework,有兴趣的可以关注该项目,后续其它的一些通用模块也会添加进去,如用户、权限、本地化、任务、插件功能等。欢迎star给星星,你的支持是我的动力!

  一、缓存模块

  nopCommerce项目缓存类层级图
  

  

  ICacheManager接口,该接口定义了数据缓存常用的方法。 
  CacheExtensions扩展方法对ICacheManager进行扩展。
  MemoryCacheCache类,使用.net  缓存框架实现数据缓存。
  PerRequestCacheManager类,实现页面请求级的数据缓存。
  RedisCacheManager类,实现Redis数据缓存类。
  NopNullCache类,空的数据缓存类实现。
  IRedisConnectionWrapper接口,redis连接封装接口。
  RedisConnectionWrapper类,redis连接实现。
  

  缓存的使用 
  在依赖注入中(DependencyRegistrar),将缓存注入到IOC容器中,系统默认使用MemoryCacheCache,如果想使用redis缓存可在配置模块启用并设置相关参数。
  

     //cache managers
    if (config != null && config.RedisCachingEnabled)
    {
       builder.RegisterType<RedisConnectionWrapper>().As<IRedisConnectionWrapper>().SingleInstance();
    builder.RegisterType<RedisCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").InstancePerLifetimeScope();
    }
    else
    {
    builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance();
    }
    builder.RegisterType<PerRequestCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_per_request").InstancePerLifetimeScope();
  在用户操作服务UserActivityService中可以了解到,数据缓存是如何处理的,在数据检索时,直接从缓存取数据,其他方法均根据相关正则表达式移除ActivityLogType的所有缓存,以避免读取到脏数据。

          protected virtual IList<ActivityLogTypeForCaching> GetAllActivityTypesCached()
{
//cache
    string key = string.Format(ACTIVITYTYPE_ALL_KEY);
return _cacheManager.Get(key, () =>
{
var result = new List<ActivityLogTypeForCaching>();
var activityLogTypes = GetAllActivityTypes();
foreach (var alt in activityLogTypes)
{
var altForCaching = new ActivityLogTypeForCaching
{
Id = alt.Id,
SystemKeyword = alt.SystemKeyword,
Name = alt.Name,
Enabled = alt.Enabled
};
result.Add(altForCaching);
}
return result;
});
}

  

  二、设置模块

  Nop的设置功能实现比较有意思,先看类层级图。
  

  ILocalizedEntity接口,暂时忽略该接口。 
  ISettings接口,设置接口。 
  Setting类,设置实体类。
  CommonSettings类,一个实现ISettings接口的通用设置类。
  
  通过Autofac的IRegistrationSource接口,将所有的设置类注入。
     public class SettingsSource : IRegistrationSource
{
static readonly MethodInfo BuildMethod = typeof(SettingsSource).GetMethod(
"BuildRegistration",
BindingFlags.Static | BindingFlags.NonPublic); public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrations)
{
var ts = service as TypedService;
if (ts != null && typeof(ISettings).IsAssignableFrom(ts.ServiceType))
{
var buildMethod = BuildMethod.MakeGenericMethod(ts.ServiceType);
yield return (IComponentRegistration)buildMethod.Invoke(null, null);
}
} static IComponentRegistration BuildRegistration<TSettings>() where TSettings : ISettings, new()
{
return RegistrationBuilder
.ForDelegate((c, p) =>
{
////var currentStoreId = c.Resolve<IStoreContext>().CurrentStore.Id;
//uncomment the code below if you want load settings per store only when you have two stores installed.
//var currentStoreId = c.Resolve<IStoreService>().GetAllStores().Count > 1
// c.Resolve<IStoreContext>().CurrentStore.Id : 0; //although it's better to connect to your database and execute the following SQL:
//DELETE FROM [Setting] WHERE [StoreId] > 0
return c.Resolve<ISettingService>().LoadSetting<TSettings>();
})
.InstancePerLifetimeScope()
.CreateRegistration();
} public bool IsAdapterForIndividualComponents { get { return false; } }
}
  
  如何添加相关的设置
  像commonsetting一样,只需要定义一个实现空接口ISettings的类,然后的数据表中添加相关的配置,数据库中Name值对应:类名 + . + 属性名,和接口注入方式一样,不过这里使用类注入。另外需要注意的是在Nop.Core项目ComponentModel目录下的GenericDictionaryTypeConverter和GenericListTypeConverter类中重写了泛型List和泛型Dictionary的CanConvertFrom和ConvertFrom方法,使得数据库中存储字符串能转换成对应的List和Dictionary,如List存储时我们只需要将多个数据使用英文符号(,)分隔符即可。

    public class CommonSettings : ISettings
{
public CommonSettings()
{
IgnoreLogWordlist = new List<string>();
} /// <summary>
/// Gets or sets a value indicating whether stored procedures are enabled (should be used if possible)
/// </summary>
public bool UseStoredProceduresIfSupported { get; set; } /// <summary>
/// Gets or sets a value indicating whether to use stored procedure (if supported) for loading categories (it's much faster in admin area with a large number of categories than the LINQ implementation)
/// </summary>
public bool UseStoredProcedureForLoadingCategories { get; set; } /// <summary>
/// Gets or sets a value indicating whether 404 errors (page or file not found) should be logged
/// </summary>
public bool Log404Errors { get; set; } /// <summary>
/// Gets or sets ignore words (phrases) to be ignored when logging errors/messages
/// </summary>
public List<string> IgnoreLogWordlist { get; set; } }
    public class HomeController : Controller
{
public ILogger _logger;
public IUserActivityService _userActivityService;
public CommonSettings _commonSettings;
public HomeController(
ILogger logger,
IUserActivityService userActivityService,
CommonSettings commonSetting)
{
_logger = logger;
_userActivityService = userActivityService;
_commonSettings = commonSettings;
} public ActionResult Index()
{
TestSettings();
TestLogger();
return View();
} private void TestSettings()
{
var s = _commonSettings.IgnoreLogWordlist;
} private void TestLogger()
{
_logger.InsertLog(LogLevel.Information, "index visit");
_userActivityService.InsertActivity(ActivityLogTypeEnum.AddUser, "添加用户{0},{1}", new string[] { "aaaa", "bbb" });
}
}
  
  数据库配置(IDataProvider)
  之前使用web.config配置的connectionStrings,现在改为IDataProvider的实现来统一配置相关的参数,特别提示数据库配置文件在App_Data目录下的Settings.txt,如果没有新建一个,系统运行后会根据EntityFramework的数据映射自动创建相关表。
DataProvider: sqlserver
DataConnectionString: Data Source=.;Initial Catalog=nopFramework;Integrated Security=False;Persist Security Info=False;User ID=sa;Password=sa1234

 三、日志模块

  ILogger接口,日志接口。 
  NullLogger类,Logger接口空实现。
  DefaultLogger类,Nop默认的日志接口实现。 
  LoggingExtensions类,日志扩展,使用日志的扩展方法来存储不同级别的日志记录。
  IUserActivityService接口,用户操作服务接口。
  UserActivityService类,用户操作服务实现。
 
  Nop没有使用类似于Log4net的开源日志记录组件,当然如果你想使用可以通过实现接口来引入。IUserActivityService用于记录用户操作的记录,需要在ActivityLogType表配置好用户操作的类型,这里优化了一下,将类型通过枚举列出来,这样在记录用户操作的时候不至于输错参数。在首页的控制器中加入测试代码,日志和操作记录都添加到了数据库中。
     private void TestLogger()
{
_logger.InsertLog(LogLevel.Information, "index visit");
_userActivityService.InsertActivity(ActivityLogTypeEnum.AddUser, "添加用户{0},{1}", new string[] { "aaaa", "bbb" });
}
  
  至此,开发框架中添加了常用的缓存、网站设置、系统日志、用户操作日志功能。

基于NopCommerce的开发框架——缓存、网站设置、系统日志、用户操作日志的更多相关文章

  1. 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

    在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...

  2. SqlServer设置特定用户操作特定表(插入、删除、更新、查询 的权限设置)

    目录 一.需求场景: 二.操作步骤: 表上右键选择[属性],选择[权限]选项卡: 点击[搜索],在弹出的框中点击[浏览],选择需要设置的用户: 在上面点击[确定]后,就可以在[权限]选项卡中看到权限列 ...

  3. .Net捕获网站异常信息记录操作日志

    第一步:在Global.asax文件下的Application_Error()中写入操作日志 /// <summary> /// 整个网站出现异常信息,都会执行此方法 /// </s ...

  4. 基于nopCommerce的开发框架(附源码)

    .NET的开发人员应该都知道这个大名鼎鼎的高质量b2c开源项目-nopCommerce,基于EntityFramework和MVC开发,拥有透明且结构良好的解决方案,同时结合了开源和商业软件的最佳特性 ...

  5. 053医疗项目-模块五:权限设置-将用户操作权限写入Session

    权限管理指的是用户授权,与拦截器没有关系.拦截器只是一个技术,也可以用别的技术来实现的.别人问你权限管理,可不要和人家说什么拦截器.要说用户授权 前一篇文章是把实现了不同的用户呈现不用的菜单.这一篇文 ...

  6. 基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理

    在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间 ...

  7. 基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

    在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件 ...

  8. 基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理

    在早期的随笔就介绍过,把常规页面的内容拆分为几个不同的组件,如普通的页面,包括列表查询.详细资料查看.新增资料.编辑资料.导入资料等页面场景,这些内容相对比较独立,而有一定的代码量,本篇随笔介绍基于V ...

  9. 基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用

    在我们实际项目开发过程中,往往需要根据实际情况,对组件进行封装,以更简便的在界面代码中使用,在实际的前端应用中,适当的组件封装,可以减少很多重复的界面代码,并且能够非常简便的使用,本篇随笔介绍基于El ...

随机推荐

  1. angular directive

    1.restrict (字符串)可选参数,指明指令在DOM里面以什么形式被声明: 取值有:E(元素),A(属性),C(类),M(注释),其中默认值为A: E(元素):<directiveName ...

  2. 一款好用的jquery评分插件

    一.使用说明 1.jQuery评分插件的功能: 图标显示用户评分,更美观 可实时点击,切换评分 返回用户评分,记录用户评分 实现类似下图效果 2.优点: 美观,方便 3.缺点: 只能用于jquery开 ...

  3. netty——私有协议栈开发案例

    netty--私有协议栈开发案例 摘要: 在学习李林峰老师的Netty权威指南中,觉得第十二章<私有协议栈开发>中的案例代码比较有代表性,讲的也不错,但是代码中个人认为有些简单的错误,个人 ...

  4. 【转】JDBC学习笔记(10)——调用函数&存储过程

    转自:http://www.cnblogs.com/ysw-go/ 如何使用JDBC调用存储在数据库中的函数或存储过程: * 1.通过COnnection对象的prepareCall()方法创建一个C ...

  5. SpringMVC结合ajaxfileupload文件无刷新上传

    jQuery没有提供ajax的文件上传,我们可以通过ajaxfileupload实现ajax文件的上传.其实ajaxfileupload文件上传特别的简单.下面就演示一下在SpringMVC中实现aj ...

  6. 窝上课不听,how to learn C language easily(1)

    C language 学习心得 附:为啥起这么霸气侧漏,招大神们鄙视的标题,正如我在<C language>随笔的介绍中写的,这是一个写个妹纸们看的C language的文章.没错!!写这 ...

  7. 初识Celery

    本系列文章的开发环境: window + python2. + pycharm5 + celery3.1.25 + django1.9.4 在我们日常的开发工作中,经常会遇到这几种情况: 1.在web ...

  8. 【JAVAWEB学习笔记】13_servlet

    JavaWeb核心之Servlet 教学目标 案例一.完成用户登录功能 案例二.记录成功登录系统的人次 一.Servlet简介 1.什么是Servlet Servlet 运行在服务端的Java小程序, ...

  9. HTM CSS 笔记乱炖

    一.常用实体(字符转义) '<' == '<' '©' == '©' '>' == '>' '"' == '"' ' ' == ' ' '®' == '®' ...

  10. Neo4j 第二篇:图形数据库

    在深入学习图形数据库之前,首先理解属性图的基本概念.一个属性图是由顶点(Vertex),边(Edge),标签(Lable),关系类型和属性(Property)组成的有向图.顶点也称作节点(Node), ...