我的NopCommerce之旅(8): 路由分析
一、导图和基础介绍
本文主要介绍NopCommerce的路由机制,网上有一篇不错的文章,有兴趣的可以看看NopCommerce源码架构详解--对seo友好Url的路由机制实现源码分析
SEO,Search Engine Optimization,中文叫做搜索引擎优化,主要是为了提高网站关键词排名,提高访问量。SEO是一个很广的话题,我们这里主要了解NopCommerce的友好Url机制(它是实现SEO的一个步骤)。
二、承上启下
我的NopCommerce之旅(6): 应用启动中介绍在应用启动时,进行了常见的MVC物件的注册,包括Area、Route。这里通过调用公共接口方法,调用了所有实现了公共接口的类,实现对所有路由的注册。
//Registering some regular mvc stuff
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
//register custom routes (plugins, etc)
var routePublisher = EngineContext.Current.Resolve<IRoutePublisher>();
routePublisher.RegisterRoutes(routes);
/// <summary>
/// Register routes
/// </summary>
/// <param name="routes">Routes</param>
public virtual void RegisterRoutes(RouteCollection routes)
{
var routeProviderTypes = typeFinder.FindClassesOfType<IRouteProvider>();
var routeProviders = new List<IRouteProvider>();
foreach (var providerType in routeProviderTypes)
{
//Ignore not installed plugins
var plugin = FindPlugin(providerType);
if (plugin != null && !plugin.Installed)
continue; var provider = Activator.CreateInstance(providerType) as IRouteProvider;
routeProviders.Add(provider);
}
routeProviders = routeProviders.OrderByDescending(rp => rp.Priority).ToList();
routeProviders.ForEach(rp => rp.RegisterRoutes(routes));//根据顺序,注册路由
}
三、公共接口
Nop.Web.Framework.Mvc.Routes.IRouteProvider,核心路由、友好路由以及Plugin等实现该接口进行路由注册。
Nop.Web.Framework.Mvc.Routes.IRoutePublisher
四、注册实现
1.核心路由注册,包括首页、部件、登录注册、购物车等,代码位置为Nop.Web.Infrastructure.RouteProvider。
public void RegisterRoutes(RouteCollection routes)
{
//We reordered our routes so the most used ones are on top. It can improve performance. //home page
routes.MapLocalizedRoute("HomePage",
"",
new { controller = "Home", action = "Index" },
new[] { "Nop.Web.Controllers" }); //widgets
//we have this route for performance optimization because named routes are MUCH faster than usual Html.Action(...)
//and this route is highly used
routes.MapRoute("WidgetsByZone",
"widgetsbyzone/",
new { controller = "Widget", action = "WidgetsByZone" },
new[] { "Nop.Web.Controllers" }); //login
routes.MapLocalizedRoute("Login",
"login/",
new { controller = "Customer", action = "Login" },
new[] { "Nop.Web.Controllers" });
//register
routes.MapLocalizedRoute("Register",
"register/",
new { controller = "Customer", action = "Register" },
new[] { "Nop.Web.Controllers" });
//logout
routes.MapLocalizedRoute("Logout",
"logout/",
new { controller = "Customer", action = "Logout" },
new[] { "Nop.Web.Controllers" }); //shopping cart
routes.MapLocalizedRoute("ShoppingCart",
"cart/",
new { controller = "ShoppingCart", action = "Cart" },
new[] { "Nop.Web.Controllers" });
//wishlist
routes.MapLocalizedRoute("Wishlist",
"wishlist/{customerGuid}",
new { controller = "ShoppingCart", action = "Wishlist", customerGuid = UrlParameter.Optional },
new[] { "Nop.Web.Controllers" }); //customer account links
routes.MapLocalizedRoute("CustomerInfo",
"customer/info",
new { controller = "Customer", action = "Info" },
new[] { "Nop.Web.Controllers" });
... //contact us
routes.MapLocalizedRoute("ContactUs",
"contactus",
new { controller = "Common", action = "ContactUs" },
new[] { "Nop.Web.Controllers" });
//sitemap
routes.MapLocalizedRoute("Sitemap",
"sitemap",
new { controller = "Common", action = "Sitemap" },
new[] { "Nop.Web.Controllers" }); //product search
routes.MapLocalizedRoute("ProductSearch",
"search/",
new { controller = "Catalog", action = "Search" },
new[] { "Nop.Web.Controllers" });
routes.MapLocalizedRoute("ProductSearchAutoComplete",
"catalog/searchtermautocomplete",
new { controller = "Catalog", action = "SearchTermAutoComplete" },
new[] { "Nop.Web.Controllers" }); //change currency (AJAX link)
routes.MapLocalizedRoute("ChangeCurrency",
"changecurrency/{customercurrency}",
new { controller = "Common", action = "SetCurrency" },
new { customercurrency = @"\d+" },
new[] { "Nop.Web.Controllers" });
//change language (AJAX link)
routes.MapLocalizedRoute("ChangeLanguage",
"changelanguage/{langid}",
new { controller = "Common", action = "SetLanguage" },
new { langid = @"\d+" },
new[] { "Nop.Web.Controllers" });
//change tax (AJAX link)
routes.MapLocalizedRoute("ChangeTaxType",
"changetaxtype/{customertaxtype}",
new { controller = "Common", action = "SetTaxType" },
new { customertaxtype = @"\d+" },
new[] { "Nop.Web.Controllers" }); //recently viewed products
routes.MapLocalizedRoute("RecentlyViewedProducts",
"recentlyviewedproducts/",
new { controller = "Product", action = "RecentlyViewedProducts" },
new[] { "Nop.Web.Controllers" });
//new products
routes.MapLocalizedRoute("NewProducts",
"newproducts/",
new { controller = "Product", action = "NewProducts" },
new[] { "Nop.Web.Controllers" });
//blog
routes.MapLocalizedRoute("Blog",
"blog",
new { controller = "Blog", action = "List" },
new[] { "Nop.Web.Controllers" });
//news
routes.MapLocalizedRoute("NewsArchive",
"news",
new { controller = "News", action = "List" },
new[] { "Nop.Web.Controllers" }); //forum
routes.MapLocalizedRoute("Boards",
"boards",
new { controller = "Boards", action = "Index" },
new[] { "Nop.Web.Controllers" }); //compare products
routes.MapLocalizedRoute("CompareProducts",
"compareproducts/",
new { controller = "Product", action = "CompareProducts" },
new[] { "Nop.Web.Controllers" }); //product tags
routes.MapLocalizedRoute("ProductTagsAll",
"producttag/all/",
new { controller = "Catalog", action = "ProductTagsAll" },
new[] { "Nop.Web.Controllers" }); //manufacturers
routes.MapLocalizedRoute("ManufacturerList",
"manufacturer/all/",
new { controller = "Catalog", action = "ManufacturerAll" },
new[] { "Nop.Web.Controllers" });
//vendors
routes.MapLocalizedRoute("VendorList",
"vendor/all/",
new { controller = "Catalog", action = "VendorAll" },
new[] { "Nop.Web.Controllers" }); //add product to cart (without any attributes and options). used on catalog pages.
routes.MapLocalizedRoute("AddProductToCart-Catalog",
"addproducttocart/catalog/{productId}/{shoppingCartTypeId}/{quantity}",
new { controller = "ShoppingCart", action = "AddProductToCart_Catalog" },
new { productId = @"\d+", shoppingCartTypeId = @"\d+", quantity = @"\d+" },
new[] { "Nop.Web.Controllers" });
//add product to cart (with attributes and options). used on the product details pages.
routes.MapLocalizedRoute("AddProductToCart-Details",
"addproducttocart/details/{productId}/{shoppingCartTypeId}",
new { controller = "ShoppingCart", action = "AddProductToCart_Details" },
new { productId = @"\d+", shoppingCartTypeId = @"\d+" },
new[] { "Nop.Web.Controllers" }); //product tags
routes.MapLocalizedRoute("ProductsByTag",
"producttag/{productTagId}/{SeName}",
new { controller = "Catalog", action = "ProductsByTag", SeName = UrlParameter.Optional },
new { productTagId = @"\d+" },
new[] { "Nop.Web.Controllers" });
//comparing products
routes.MapLocalizedRoute("AddProductToCompare",
"compareproducts/add/{productId}",
new { controller = "Product", action = "AddProductToCompareList" },
new { productId = @"\d+" },
new[] { "Nop.Web.Controllers" });
//product email a friend
routes.MapLocalizedRoute("ProductEmailAFriend",
"productemailafriend/{productId}",
new { controller = "Product", action = "ProductEmailAFriend" },
new { productId = @"\d+" },
new[] { "Nop.Web.Controllers" });
//reviews
routes.MapLocalizedRoute("ProductReviews",
"productreviews/{productId}",
new { controller = "Product", action = "ProductReviews" },
new[] { "Nop.Web.Controllers" });
//back in stock notifications
routes.MapLocalizedRoute("BackInStockSubscribePopup",
"backinstocksubscribe/{productId}",
new { controller = "BackInStockSubscription", action = "SubscribePopup" },
new { productId = @"\d+" },
new[] { "Nop.Web.Controllers" });
//downloads
routes.MapRoute("GetSampleDownload",
"download/sample/{productid}",
new { controller = "Download", action = "Sample" },
new { productid = @"\d+" },
new[] { "Nop.Web.Controllers" }); //checkout pages
routes.MapLocalizedRoute("Checkout",
"checkout/",
new { controller = "Checkout", action = "Index" },
new[] { "Nop.Web.Controllers" });
... //subscribe newsletters
routes.MapLocalizedRoute("SubscribeNewsletter",
"subscribenewsletter",
new { controller = "Newsletter", action = "SubscribeNewsletter" },
new[] { "Nop.Web.Controllers" }); //email wishlist
routes.MapLocalizedRoute("EmailWishlist",
"emailwishlist",
new { controller = "ShoppingCart", action = "EmailWishlist" },
new[] { "Nop.Web.Controllers" }); //login page for checkout as guest
routes.MapLocalizedRoute("LoginCheckoutAsGuest",
"login/checkoutasguest",
new { controller = "Customer", action = "Login", checkoutAsGuest = true },
new[] { "Nop.Web.Controllers" });
//register result page
routes.MapLocalizedRoute("RegisterResult",
"registerresult/{resultId}",
new { controller = "Customer", action = "RegisterResult" },
new { resultId = @"\d+" },
new[] { "Nop.Web.Controllers" });
//check username availability
routes.MapLocalizedRoute("CheckUsernameAvailability",
"customer/checkusernameavailability",
new { controller = "Customer", action = "CheckUsernameAvailability" },
new[] { "Nop.Web.Controllers" }); //passwordrecovery
routes.MapLocalizedRoute("PasswordRecovery",
"passwordrecovery",
new { controller = "Customer", action = "PasswordRecovery" },
new[] { "Nop.Web.Controllers" });
//password recovery confirmation
routes.MapLocalizedRoute("PasswordRecoveryConfirm",
"passwordrecovery/confirm",
new { controller = "Customer", action = "PasswordRecoveryConfirm" },
new[] { "Nop.Web.Controllers" }); //topics
routes.MapLocalizedRoute("TopicPopup",
"t-popup/{SystemName}",
new { controller = "Topic", action = "TopicDetailsPopup" },
new[] { "Nop.Web.Controllers" }); //blog
routes.MapLocalizedRoute("BlogByTag",
"blog/tag/{tag}",
new { controller = "Blog", action = "BlogByTag" },
new[] { "Nop.Web.Controllers" });
routes.MapLocalizedRoute("BlogByMonth",
"blog/month/{month}",
new { controller = "Blog", action = "BlogByMonth" },
new[] { "Nop.Web.Controllers" });
//blog RSS
routes.MapLocalizedRoute("BlogRSS",
"blog/rss/{languageId}",
new { controller = "Blog", action = "ListRss" },
new { languageId = @"\d+" },
new[] { "Nop.Web.Controllers" }); //news RSS
routes.MapLocalizedRoute("NewsRSS",
"news/rss/{languageId}",
new { controller = "News", action = "ListRss" },
new { languageId = @"\d+" },
new[] { "Nop.Web.Controllers" }); //set review helpfulness (AJAX link)
routes.MapRoute("SetProductReviewHelpfulness",
"setproductreviewhelpfulness",
new { controller = "Product", action = "SetProductReviewHelpfulness" },
new[] { "Nop.Web.Controllers" }); //customer account links
routes.MapLocalizedRoute("CustomerReturnRequests",
"returnrequest/history",
new { controller = "ReturnRequest", action = "CustomerReturnRequests" },
new[] { "Nop.Web.Controllers" });
...
//customer profile page
routes.MapLocalizedRoute("CustomerProfile",
"profile/{id}",
new { controller = "Profile", action = "Index" },
new { id = @"\d+" },
new[] { "Nop.Web.Controllers" });
routes.MapLocalizedRoute("CustomerProfilePaged",
"profile/{id}/page/{page}",
new { controller = "Profile", action = "Index" },
new { id = @"\d+", page = @"\d+" },
new[] { "Nop.Web.Controllers" }); //orders
routes.MapLocalizedRoute("OrderDetails",
"orderdetails/{orderId}",
new { controller = "Order", action = "Details" },
new { orderId = @"\d+" },
new[] { "Nop.Web.Controllers" });
...
//order downloads
routes.MapRoute("GetDownload",
"download/getdownload/{orderItemId}/{agree}",
new { controller = "Download", action = "GetDownload", agree = UrlParameter.Optional },
new { orderItemId = new GuidConstraint(false) },
new[] { "Nop.Web.Controllers" });
... //contact vendor
routes.MapLocalizedRoute("ContactVendor",
"contactvendor/{vendorId}",
new { controller = "Common", action = "ContactVendor" },
new[] { "Nop.Web.Controllers" });
//apply for vendor account
routes.MapLocalizedRoute("ApplyVendorAccount",
"vendor/apply",
new { controller = "Vendor", action = "ApplyVendor" },
new[] { "Nop.Web.Controllers" }); //poll vote AJAX link
routes.MapLocalizedRoute("PollVote",
"poll/vote",
new { controller = "Poll", action = "Vote" },
new[] { "Nop.Web.Controllers" }); //comparing products
routes.MapLocalizedRoute("RemoveProductFromCompareList",
"compareproducts/remove/{productId}",
new { controller = "Product", action = "RemoveProductFromCompareList" },
new[] { "Nop.Web.Controllers" });
routes.MapLocalizedRoute("ClearCompareList",
"clearcomparelist/",
new { controller = "Product", action = "ClearCompareList" },
new[] { "Nop.Web.Controllers" }); //new RSS
routes.MapLocalizedRoute("NewProductsRSS",
"newproducts/rss",
new { controller = "Product", action = "NewProductsRss" },
new[] { "Nop.Web.Controllers" }); //get state list by country ID (AJAX link)
routes.MapRoute("GetStatesByCountryId",
"country/getstatesbycountryid/",
new { controller = "Country", action = "GetStatesByCountryId" },
new[] { "Nop.Web.Controllers" }); //EU Cookie law accept button handler (AJAX link)
routes.MapRoute("EuCookieLawAccept",
"eucookielawaccept",
new { controller = "Common", action = "EuCookieLawAccept" },
new[] { "Nop.Web.Controllers" }); //authenticate topic AJAX link
routes.MapLocalizedRoute("TopicAuthenticate",
"topic/authenticate",
new { controller = "Topic", action = "Authenticate" },
new[] { "Nop.Web.Controllers" }); //product attributes with "upload file" type
routes.MapLocalizedRoute("UploadFileProductAttribute",
"uploadfileproductattribute/{attributeId}",
new { controller = "ShoppingCart", action = "UploadFileProductAttribute" },
new { attributeId = @"\d+" },
new[] { "Nop.Web.Controllers" });
//checkout attributes with "upload file" type
routes.MapLocalizedRoute("UploadFileCheckoutAttribute",
"uploadfilecheckoutattribute/{attributeId}",
new { controller = "ShoppingCart", action = "UploadFileCheckoutAttribute" },
new { attributeId = @"\d+" },
new[] { "Nop.Web.Controllers" }); //forums
routes.MapLocalizedRoute("ActiveDiscussions",
"boards/activediscussions",
new { controller = "Boards", action = "ActiveDiscussions" },
new[] { "Nop.Web.Controllers" });
... //private messages
routes.MapLocalizedRoute("PrivateMessages",
"privatemessages/{tab}",
new { controller = "PrivateMessages", action = "Index", tab = UrlParameter.Optional },
new[] { "Nop.Web.Controllers" });
... //activate newsletters
routes.MapLocalizedRoute("NewsletterActivation",
"newsletter/subscriptionactivation/{token}/{active}",
new { controller = "Newsletter", action = "SubscriptionActivation" },
new { token = new GuidConstraint(false) },
new[] { "Nop.Web.Controllers" }); //robots.txt
routes.MapRoute("robots.txt",
"robots.txt",
new { controller = "Common", action = "RobotsTextFile" },
new[] { "Nop.Web.Controllers" }); //sitemap (XML)
routes.MapLocalizedRoute("sitemap.xml",
"sitemap.xml",
new { controller = "Common", action = "SitemapXml" },
new[] { "Nop.Web.Controllers" }); //store closed
routes.MapLocalizedRoute("StoreClosed",
"storeclosed",
new { controller = "Common", action = "StoreClosed" },
new[] { "Nop.Web.Controllers" }); //install
routes.MapRoute("Installation",
"install",
new { controller = "Install", action = "Index" },
new[] { "Nop.Web.Controllers" }); //page not found
routes.MapLocalizedRoute("PageNotFound",
"page-not-found",
new { controller = "Common", action = "PageNotFound" },
new[] { "Nop.Web.Controllers" });
}
2.SEO友好路由注册,包括产品、种类、生产商、供应商、新闻、博客、主题等具体信息的路由,代码位置为Nop.Web.Infrastructure.GenericUrlRouteProvider。
经过优化过的友好Url为http://localhost/apple-macbook-pro-13-inch,而经过解析后访问的实际http://localhost/Product/ProductDetails/{productId}。
public void RegisterRoutes(RouteCollection routes)
{
//generic URLs
routes.MapGenericPathRoute("GenericUrl",
"{generic_se_name}",
new {controller = "Common", action = "GenericUrl"},
new[] {"Nop.Web.Controllers"}); //define this routes to use in UI views (in case if you want to customize some of them later)
routes.MapLocalizedRoute("Product",
"{SeName}",
new { controller = "Product", action = "ProductDetails" },
new[] {"Nop.Web.Controllers"}); routes.MapLocalizedRoute("Category",
"{SeName}",
new { controller = "Catalog", action = "Category" },
new[] { "Nop.Web.Controllers" }); routes.MapLocalizedRoute("Manufacturer",
"{SeName}",
new { controller = "Catalog", action = "Manufacturer" },
new[] { "Nop.Web.Controllers" }); routes.MapLocalizedRoute("Vendor",
"{SeName}",
new { controller = "Catalog", action = "Vendor" },
new[] { "Nop.Web.Controllers" }); routes.MapLocalizedRoute("NewsItem",
"{SeName}",
new { controller = "News", action = "NewsItem" },
new[] { "Nop.Web.Controllers" }); routes.MapLocalizedRoute("BlogPost",
"{SeName}",
new { controller = "Blog", action = "BlogPost" },
new[] { "Nop.Web.Controllers" }); routes.MapLocalizedRoute("Topic",
"{SeName}",
new { controller = "Topic", action = "TopicDetails" },
new[] { "Nop.Web.Controllers" }); //the last route. it's used when none of registered routes could be used for the current request
//but it this case we cannot process non-registered routes (/controller/action)
//routes.MapLocalizedRoute(
// "PageNotFound-Wildchar",
// "{*url}",
// new { controller = "Common", action = "PageNotFound" },
// new[] { "Nop.Web.Controllers" });
}
五、友好Url解析
NopCommerce中通过继承Route类,重写RouteData GetRouteData(HttpContextBase httpContext)方法来获取真正路由。代码位置为Nop.Web.Framework.Localization.LocalizedRoute和Nop.Web.Framework.Seo.GenericPathRoute。
GenericPathRoute类的GetRouteData()方法是我们要讲的重点,它实现了友好Url的解析。下面是方法代码的分析:
1.获取Url的标识值。
获取请求中generic_se_name的值。
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData data = base.GetRouteData(httpContext);
if (data != null && DataSettingsHelper.DatabaseIsInstalled())
{
var urlRecordService = EngineContext.Current.Resolve<IUrlRecordService>();
var slug = data.Values["generic_se_name"] as string;//获取标识值,如"apple-macbook-pro-13-inch" ...
}
return data;
}
2.根据标识解析实际路由信息
2.1 从缓存中读取该标识关联的值,值包括访问的controller和Id
public override RouteData GetRouteData(HttpContextBase httpContext)
{
...
var slug = data.Values["generic_se_name"] as string;
//performance optimization.
//we load a cached verion here. it reduces number of SQL requests for each page load
var urlRecord = urlRecordService.GetBySlugCached(slug);
...
}
/// <summary>
/// Find URL record (cached version).
/// This method works absolutely the same way as "GetBySlug" one but caches the results.
/// Hence, it's used only for performance optimization in public store
/// </summary>
/// <param name="slug">Slug</param>
/// <returns>Found URL record</returns>
public virtual UrlRecordForCaching GetBySlugCached(string slug)
{
if (String.IsNullOrEmpty(slug))
return null; if (_localizationSettings.LoadAllUrlRecordsOnStartup)
{
//load all records (we know they are cached)
var source = GetAllUrlRecordsCached();
var query = from ur in source
where ur.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase)
select ur;
var urlRecordForCaching = query.FirstOrDefault();
return urlRecordForCaching;
} //gradual loading
string key = string.Format(URLRECORD_BY_SLUG_KEY, slug);
return _cacheManager.Get(key, () =>
{
var urlRecord = GetBySlug(slug);//从数据库读取
if (urlRecord == null)
return null; var urlRecordForCaching = Map(urlRecord);
return urlRecordForCaching;
});
}
2.2 若缓存中不存在则读取数据库数据,数据库表为[dbo].[UrlRecord]
/// <summary>
/// Find URL record
/// </summary>
/// <param name="slug">Slug</param>
/// <returns>Found URL record</returns>
public virtual UrlRecord GetBySlug(string slug)
{
if (String.IsNullOrEmpty(slug))
return null; var query = from ur in _urlRecordRepository.Table
where ur.Slug == slug
select ur;
var urlRecord = query.FirstOrDefault();
return urlRecord;
}
2.3 根据读取的值的EntityName,返回路由信息。
//process URL
switch (urlRecord.EntityName.ToLowerInvariant())
{
case "product":
{
data.Values["controller"] = "Product";
data.Values["action"] = "ProductDetails";
data.Values["productid"] = urlRecord.EntityId;
data.Values["SeName"] = urlRecord.Slug;
...
3.访问路由信息
我的NopCommerce之旅(8): 路由分析的更多相关文章
- [转]NopCommerce之旅: 应用启动
本文转自:http://www.cnblogs.com/devilsky/p/5359881.html 我的NopCommerce之旅(6): 应用启动 一.基础介绍 Global.asax 文件 ...
- 我的NopCommerce之旅(7): 依赖注入(IOC/DI)
一.基础介绍 依赖注入,Dependency Injection,权威解释及说明请自己查阅资料. 这里简单说一下常见使用:在mvc的controller的构造方法中定义参数,如ICountryServ ...
- 我的NopCommerce之旅(2): 系统环境及技术分析
一.系统环境 IIS7.0 or above ASP.NET 4.5(MVC 5.0) .NET Framework 4.5.1 or above VS 2012 or above 二.架构设计 Pl ...
- 我的NopCommerce之旅(9): 编写Plugin实例
一.基础介绍 ——In computing, a plug-in (or plugin) is a set of software components that add specific abili ...
- 我的NopCommerce之旅(5): 缓存
一.基础介绍 1.什么是cache Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本. 2.为什么要用cache 即 ...
- 我的NopCommerce之旅(6): 应用启动
一.基础介绍 Global.asax 文件(也称为 ASP.NET 应用程序文件)是一个可选文件,该文件包含响应 ASP.NET 或 HTTP 模块所引发的应用程序级别和会话级别事件的代码. Appl ...
- Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题
一.故事背景 现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时.就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的.相比较短视频有 ...
- thinkphp 2.1代码执行及路由分析
Dispatcher.class.php这个文件中是url路由,由于第一次正式看路由那块,所以就从头开始一行一行看把. 首先是dispatch函数 是37行到140行 这个函数是做映射用,把url映射 ...
- 我的NopCommerce之旅(4): 定时任务之邮件
一.功能简介 用户购买物品生成订单后,系统将发送邮件提醒给用户 二.操作步骤 后台配置一个系统的默认发送邮箱 启动定时任务,这里包括多个任务,只需要启动邮件任务 查看邮件发送情况 三.数据库分析 [d ...
随机推荐
- OJ提交题目中的语言选项里G++与C++的区别
一.OJ提交题目中的语言选项里G++与C++的区别 http://www.th7.cn/Program/cp/201405/199001.shtml 首先更正一个概念,C++是一门计算机编程语言,G+ ...
- BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心
BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜 ...
- C/C++的const区别
1.const基础知识(用法.含义.好处) int main() { const int a; //a为const,常数型数 int const b; //b为const,常数型数 const int ...
- 华为G700电脑版Root软件-Eroot
华为G700电脑版Root软件--eroot.zip(10.5M) 查阅全文 ›
- 关于使用quartz动态增删改定时任务
1. 首先, 还是喜闻乐见的导包 <dependency> <groupId>org.springframework.boot</groupId> <arti ...
- 读取spring boot项目中resource目录下的文件
在开发中, 我们常常要将我们的配置文件或者模板文件放在我们的resource目录中. 如下 而在spring boot的项目中, 我们运行的是一个jar包, 并没有解压 所以当我们使用以下方式获取文件 ...
- QC使用常见问题
1.如果出现/qcbin/setup_a.cab this file didn’t pass singnature checking. 请下载capicom.dll文件拷贝到c:windowssyst ...
- B - School Marks
Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Description Little ...
- TypeScript完全解读(26课时)_9.TypeScript完全解读-TS中的类
9.TypeScript完全解读-TS中的类 创建class.ts文件,并在index.ts内引用 创建一个类,这个类在创建好后有好几个地方都标红了 这是tslint的一些验证规则 一保存就会自动修复 ...
- UVa 10755 Garbage Heap (暴力+前缀和)
题意:有个长方体由A*B*C组成,每个废料都有一个价值,要选一个子长方体,使得价值最大. 析:我们暴力枚举上下左右边界,然后用前缀和来快速得到另一个,然后就能得到长方体,每次维护一个最小值,然后差就是 ...