我的NopCommerce之旅(2): 定时任务之邮件

一、功能简介

用户购买物品生成订单后,系统将发送邮件提醒给用户

二、操作步骤

  1. 后台配置一个系统的默认发送邮箱
  2. 启动定时任务,这里包括多个任务,只需要启动邮件任务
  3. 查看邮件发送情况

三、数据库分析

  1. [dbo].[Log] 系统日志表,可查看邮件发送失败的异常信息
  2. [dbo].[EmailAccount] 系统发送邮件配置表
  3. [dbo].[QueuedEmail] 订单邮件序列表,[SentTries]为重试次数,默认尝试3次失败后不再发送。
  4. [dbo].[ScheduleTask] 定时任务信息表,存储定时任务信息。

四、源码解析

  1. 根据MVC命名规则,可定位到Nop.Admin.Controllers命名空间,
  2. 查看ScheduleTaskController的RunNow方法,可跟踪查看到任务调用机制。
    1. 通过反射类型,采用autofac实例化对象,然后执行。
    2. 任务实现Nop.Services.Tasks.ITask接口的Execute()方法,如Nop.Services.Messages.QueuedMessagesSendTask。
复制代码
复制代码
 1         private ITask CreateTask(ILifetimeScope scope)
 2         {
 3             ITask task = null;
 4             if (this.Enabled)
 5             {
 6                 var type2 = System.Type.GetType(this.Type);
 7                 if (type2 != null)
 8                 {
 9                     object instance;
10                     if (!EngineContext.Current.ContainerManager.TryResolve(type2, scope, out instance))
11                     {
12                         //not resolved
13                         instance = EngineContext.Current.ContainerManager.ResolveUnregistered(type2, scope);
14                     }
15                     task = instance as ITask;
16                 }
17             }
18             return task;
19         }
复制代码
复制代码
复制代码
复制代码
 1         /// <summary>
 2         /// Executes the task
 3         /// </summary>
 4         /// <param name="throwException">A value indicating whether exception should be thrown if some error happens</param>
 5         /// <param name="dispose">A value indicating whether all instances should be disposed after task run</param>
 6         /// <param name="ensureRunOnOneWebFarmInstance">A value indicating whether we should ensure this task is run on one farm node at a time</param>
 7         public void Execute(bool throwException = false, bool dispose = true, bool ensureRunOnOneWebFarmInstance = true)
 8         {
 9             ...
10                 //initialize and execute 初始化成功后执行任务
11                 var task = this.CreateTask(scope);
12                 if (task != null)
13                 {
14                     this.LastStartUtc = DateTime.UtcNow;
15                     if (scheduleTask != null)
16                     {
17                         //update appropriate datetime properties
18                         scheduleTask.LastStartUtc = this.LastStartUtc;
19                         scheduleTaskService.UpdateTask(scheduleTask);
20                     }
21                     task.Execute();
22                     this.LastEndUtc = this.LastSuccessUtc = DateTime.UtcNow;
23                 }
24             }
25             catch (Exception exc)
26             {
27                 this.Enabled = !this.StopOnError;
28                 this.LastEndUtc = DateTime.UtcNow;
29 
30                 //log error
31                 var logger = EngineContext.Current.ContainerManager.Resolve<ILogger>("", scope);
32                 logger.Error(string.Format("Error while running the '{0}' schedule task. {1}", this.Name, exc.Message), exc);
33                 if (throwException)
34                     throw;
35             }
36 
37             if (scheduleTask != null)
38             {
39                 //update appropriate datetime properties
40                 scheduleTask.LastEndUtc = this.LastEndUtc;
41                 scheduleTask.LastSuccessUtc = this.LastSuccessUtc;
42                 scheduleTaskService.UpdateTask(scheduleTask);
43             }
44 
45             //dispose all resources
46             if (dispose)
47             {
48                 scope.Dispose();
49             }
50         }
复制代码
复制代码

 

五、技术解析

  1. Autofac的依赖注入
  2. 反射

我的NopCommerce之旅(5): 缓存

 

一、基础介绍

1.什么是cache
     Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。
2.为什么要用cache
     即cache的作用,有以下几点:
     2.1.减少网络带宽消耗;
     2.2.降低服务器压力;
     2.3.减少网络延迟、加快页面打开速度。
3.cache的分类
     常见分类如下:
     3.1.数据库数据缓存;
     3.2.服务器端缓存;
          a.代理服务器缓存
          b.CDN缓存
     3.3.浏览器缓存;
     3.4.Web应用缓存

二、NopCommerce的缓存分析

1.UML
     接口ICacheManager;
     实现MemoryCacheManager(HTTP请求缓存,生命周期长),NopNullCache(仅实现接口,不提供缓存机制),PerRequestCacheManager(HTTP请求缓存,生命周期短),RedisCacheManager(Redis缓存);
     扩展CacheExtensions;
2.代码分析
     2.1.Nop.Web.Framework.DependencyRegistrar类,配置依赖注入的ICacheManager。
     
复制代码
复制代码
1             //cache managers
2             if (config.RedisCachingEnabled)
3             {
4                 builder.RegisterType<RedisCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").InstancePerLifetimeScope();
5             }
6             else
7             {
8                 builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance();
9             }
复制代码
复制代码

     2.2.RedisCachingEnabled通过读取配置文件,见Nop.Core.Configuration.NopConfig

     
复制代码
复制代码
 1             var redisCachingNode = section.SelectSingleNode("RedisCaching");
 2             if (redisCachingNode != null && redisCachingNode.Attributes != null)
 3             {
 4                 var enabledAttribute = redisCachingNode.Attributes["Enabled"];
 5                 if (enabledAttribute != null)
 6                     config.RedisCachingEnabled = Convert.ToBoolean(enabledAttribute.Value);
 7 
 8                 var connectionStringAttribute = redisCachingNode.Attributes["ConnectionString"];
 9                 if (connectionStringAttribute != null)
10                     config.RedisCachingConnectionString = connectionStringAttribute.Value;
11             }
复制代码
复制代码

3.应用

     通过依赖注入,生成缓存管理类实例,通过方法读取、设置缓存。
     
复制代码
复制代码
        [NonAction]
        protected virtual List<int> GetChildCategoryIds(int parentCategoryId)
        {
            string cacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_CHILD_IDENTIFIERS_MODEL_KEY, 
                parentCategoryId, 
                string.Join(",", _workContext.CurrentCustomer.GetCustomerRoleIds()), 
                _storeContext.CurrentStore.Id);
            return _cacheManager.Get(cacheKey, () =>
            {
                var categoriesIds = new List<int>();
                var categories = _categoryService.GetAllCategoriesByParentCategoryId(parentCategoryId);
                foreach (var category in categories)
                {
                    categoriesIds.Add(category.Id);
                    categoriesIds.AddRange(GetChildCategoryIds(category.Id));
                }
                return categoriesIds;
            });
        }
复制代码
复制代码

posted on   大西瓜3721  阅读(55)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
历史上的今天:
2019-03-11 C# WebAPI学习
2018-03-11 sqlserver学习笔记(三)—— 为数据库添加新的用户
2018-03-11 [.Net MVC] Win7下IIS部署
2017-03-11 上位机编程工控控件全览
2017-03-11 C#自定义工业控件开发
2017-03-11 C#搞工控的一些代码
2016-03-11 .Net开源工作流Roadflow的使用与集成

导航

点击右上角即可分享
微信分享提示