一、功能简介
用户购买物品生成订单后,系统将发送邮件提醒给用户
二、操作步骤
- 后台配置一个系统的默认发送邮箱
- 启动定时任务,这里包括多个任务,只需要启动邮件任务
- 查看邮件发送情况
三、数据库分析
- [dbo].[Log] 系统日志表,可查看邮件发送失败的异常信息
- [dbo].[EmailAccount] 系统发送邮件配置表
- [dbo].[QueuedEmail] 订单邮件序列表,[SentTries]为重试次数,默认尝试3次失败后不再发送。
- [dbo].[ScheduleTask] 定时任务信息表,存储定时任务信息。
四、源码解析
- 根据MVC命名规则,可定位到Nop.Admin.Controllers命名空间,
- 查看ScheduleTaskController的RunNow方法,可跟踪查看到任务调用机制。
- 通过反射类型,采用autofac实例化对象,然后执行。
- 任务实现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 }
五、技术解析
- Autofac的依赖注入
- 反射
我的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; }); }标签:scheduleTask,缓存,之旅,cache,task,NopCommerce,var,null,邮件 From: https://www.cnblogs.com/Alex80/p/17207219.html