http://msdn.microsoft.com/zh-cn/library/ms998532.aspx

背景信息

示例有助于解释如何在 ASP.NET 中实现 Front Controller,并让您看到通过单个控制器对象来集中所有控制所带来的价值,只要该示例的复杂程度足以说明您在实现该模式时将遇到的问题。

注意:因为 Page Controller 内置在 ASP.NET 中,所以,实现 Front Controller 而不是 Page Controller 就需要大量的工作。实际上,您必须为 Front Controller 构建整个框架。只有在您的应用程序具有足够高的复杂程度时,才应该这样做。否则,请阅读 Page Controller 相关内容,以确定它是否够用。

以下示例建立在 ASP.NET 中实现 Page Controller中所描述的解决方案上。该解决方案描述了两个不同的页面。这两个页面是从一个公共的基类继承而来的,该基类负责将站点头信息添加到每个页面上。当您希望让页面具有相同行为时,该实现是 Page Controller 的常见选择。下面是 Page Controller 示例中的 BasePage 类:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class BasePage : Page
{ protected Label eMail; protected Label siteName; virtual protected void PageLoadEvent(object sender, System.EventArgs e) {} protected void Page_Load(object sender, System.EventArgs e) { if(!IsPostBack) { string name = Context.User.Identity.Name; eMail.Text = DatabaseGateway.RetrieveAddress(name); siteName.Text = "Micro-site"; PageLoadEvent(sender, e); } } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } //  // 设计器支持所必需的方法 – 不要使用代码编辑器修改 // 此方法的内容。 //  private void InitializeComponent() {     this.Load += new System.EventHandler(this.Page_Load); } #endregion
}

每次加载页面时,就会调用 Page_Load 函数。该函数从 DatabaseGateway 类检索电子邮件地址(如“在 ASP.NET 中实现 Page Controller”中所示),并用数据设置某些标签,然后调用 PageLoadEvent 对每个页面进行特殊化处理。

选择 Front Controller 而不是 Page Controller 的条件之一是,基类中的条件逻辑过多。此示例不使用基类中的条件逻辑。因此,单就此条件而言,无需实现 Front Controller

更改需求

前面的示例非常适用于其预期目的。不过,该示例过于简单,无法代表大多数 Web 应用程序。为了更接近于这类应用程序的整体复杂性,按照此示例的需求,我们需要在页面上使用不同的头信息(这取决于 URL 和查询参数)。

此示例将创建两个站点:Micro 站点和 Macro 站点。每个站点都查询不同的数据,以检索头信息中包含的电子邮件地址。页面本身保持不变;只有头信息内容是不同的。在此示例中,大多数实现与前面的示例相同。唯一必须修改的类是 BasePage

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class BasePage : Page
{ protected Label eMail; protected Label siteName; virtual protected void PageLoadEvent(object sender, System.EventArgs e) {} protected void Page_Load(object sender, System.EventArgs e) { if(!IsPostBack) { string site = Request["site"]; if(site != null && site.Equals("macro")) LoadMacroHeader(); else LoadMicroHeader(); PageLoadEvent(sender, e); } } private void LoadMicroHeader() { string name = Context.User.Identity.Name; eMail.Text = WebUsersDatabase.RetrieveAddress(name);             siteName.Text = "Micro-site"; } private void LoadMacroHeader() { string name = Context.User.Identity.Name; eMail.Text = MacroUsersDatabase.RetrieveAddress(name);             siteName.Text = "Macro-site"; } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } //  // Required method for Designer support - do not modify // the contents of this method with the code editor. //  private void InitializeComponent() {     this.Load += new System.EventHandler(this.Page_Load); } #endregion
}

前面已经提到,Micro 站点和 Macro 站点各自使用不同的数据库来检索头信息中包含的电子邮件地址。LoadMacroHeaderLoadMicroHeader 这两个方法使用不同的数据库网关类,即 WebUsersDatabaseMacroUsersDatabase,来从数据库检索地址。

Page_Load 方法的职责已更改。在前面的示例中,它从数据库检索信息。在此实现中,它决定要调用哪个函数,LoadMicroHeader 还是 LoadMacroHeader,然后再调用适当的方法。如果只有两个站点,该实现就已足够了。不过,基类现在包含条件逻辑。您也许不希望看到此类中包含的逻辑。显然,大多数开发人员在看到代码中的分支较多时会觉得很麻烦,但两个分支可能不会让他们有这样的感觉。限制条件逻辑的主要原因是,条件逻辑更有可能发生更改,从而导致您修改实现。因为整个实现包含在一个文件中,因此,所做的更改会影响其他站点。

实现策略

Front Controller 通常分为两个部分来实现。Handler 对象从 Web 服务器接收各个请求(HTTP Get 和 Post),并检索相关参数,然后根据参数选择适当的命令。控制器的第二个部分是 Command Processor,该部分执行特定操作或命令来满足请求。命令完成后转到视图,以便显示页面。

注意:此实现策略解决了前面的示例中出现的问题。虽然此示例可能不足以证明对 Front Controller 的更改是合理的,但它说明了为什么会使用 Front Controller ,并且该实现解决了这种复杂性高得多的问题。另外,与大多数实现一样,实现此模式的方式不止一种,这只是其中的一个选择。

处理程序

ASP.NET 提供低级请求/响应 API 来处理传入的 HTTP 请求。ASP.NET 所接收的每个传入 HTTP 请求最终由实现 IHTTPHandler 接口的类的具体实例来处理。这种低级 API 非常适用于实现 Front Controller 的处理程序部分。

注意:Microsoft? .NET Framework 为 HTTP 处理程序提供了多个实现选择。例如,在高容量环境中,您可以通过实现了 IHttpAsyncHandler 接口的异步 HTTP 处理程序来提高响应速度。为简单起见,此解决方案使用同步处理程序。有关如何实现异步 HTTP 处理程序的详细信息,请访问 Microsoft Developer Network (MSDN?) 网站 (http://msdn.microsoft.com)。

图 1 显示了控制器的处理程序部分的结构。

1 Front Controller 的处理程序部分

此解决方案完美地划分了职责。Handler 类负责处理各个 Web 请求,并将确定正确的 Command 对象这一职责委派给 CommandFactory 类。当 CommandFactory 返回Command 对象后,Handler 将调用 Command 上的 Execute 方法来执行请求。

Handler.cs

下面的代码示例显示了如何实现 Handler 类:

using System;
using System.Web;
public class Handler : IHttpHandler
{ public void ProcessRequest(HttpContext context)  { Command command =  CommandFactory.Make(context.Request.Params); command.Execute(context); } public bool IsReusable  {  get { return true;}  }
}

Command.cs

Command 类是 Command 模式 [Gamma95] 的一个示例。Command 模式在此解决方案中非常有用,因为您不希望 Handler 类直接依赖于命令。一般来说,可以从CommandFactory 返回命令对象。

using System;
using System.Web;
public interface Command
{ void Execute(HttpContext context);
}

CommandFactory.cs

CommandFactory 类对于实现至关重要。它根据查询字符串中的参数来判断将创建哪个命令。在此示例中,如果 site 查询参数被设置为 micro 或根本没有设置,工厂将创建MicroSite 命令对象。如果 site 被设置为 macro,工厂将创建 MacroSite 命令对象。如果该值被设置为任何其他值,工厂将返回 UnknownCommand 对象,以便进行默认错误处理。这是 Special Case 模式 [Fowler03] 的一个示例。

using System;
using System.Collections.Specialized;
public class CommandFactory
{ public static Command Make(NameValueCollection parms) { string siteName = parms["site"]; Command command = new UnknownCommand(); if(siteName == null || siteName.Equals("micro")) command = new MicroSite(); else if(siteName.Equals("macro")) command = new MacroSite(); return command; }
} 
配置处理程序

HTTP 处理程序在 ASP.NET 配置中被声明为 web.config 文件。ASP.NET 定义了一个可以在其中添加和删除处理程序的 <httphandlers> 配置段。例如,ASP.NET 将 Page*.aspx 文件的所有请求映射到应用程序的 web.config 文件中的 Handler 类:

<httpHandlers> <add verb="*" path="Page*.aspx" type="Handler,FrontController" />
</httpHandlers> 
 
命令

命令代表了网站中的可变性。在此示例中,从每个站点的数据库中检索数据的功能包含在它自己的类中,并且该类是从名为 RedirectingCommand 的基类继承而来的。RedirectingCommand 类实现了 Command 接口。调用 RedirectingCommand 类的 Execute 时,它首先调用名为 OnExecute 的抽象方法,然后转到视图。该特定视图是从名为 UrlMap 的类检索而来的。UrlMap 类从应用程序的 web.config 文件中检索映射关系。图 2 显示了该解决方案的命令部分的结构。

2 front controller 的命令部分

RedirectingCommand.cs

RedirectingCommand 是一个抽象基类,它调用名为 OnExecute 的抽象方法来执行特定命令,然后转到从 UrlMap 检索到的视图。

using System;
using System.Web;
public abstract class RedirectingCommand : Command
{ private UrlMap map = UrlMap.SoleInstance; protected abstract void OnExecute(HttpContext context); public void Execute(HttpContext context) { OnExecute(context); string url = String.Format("{0}?{1}", map.Map[context.Request.Url.AbsolutePath], context.Request.Url.Query); context.Server.Transfer(url); }
}

UrlMap.cs

UrlMap 类从应用程序的 web.config 文件加载配置信息。配置信息将所请求的 URL 的绝对路径关联到该文件所指定的另一个 URL。这样,就可以更改当请求外部页面时要将用户转到哪个实际页面。这个过程为更改视图提供了很高的灵活性,因为用户永远不会引用实际页面。下面是 UrlMap 类:

using System;
using System.Web;
using System.Xml;
using System.Configuration;
using System.Collections.Specialized;
public class UrlMap : IConfigurationSectionHandler
{ private readonly NameValueCollection _commands = new NameValueCollection(); public const string SECTION_NAME="controller.mapping"; public static UrlMap SoleInstance  { get {return (UrlMap) ConfigurationSettings.GetConfig(SECTION_NAME);} } object IConfigurationSectionHandler.Create(object parent,object configContext, XmlNode section)  { return (object) new UrlMap(parent,configContext, section);    } private UrlMap() {/*no-op*/} public UrlMap(object parent,object configContext, XmlNode section)  { try  { XmlElement entriesElement = section["entries"]; foreach(XmlElement element in entriesElement)  { _commands.Add(element.Attributes["key"].Value,element.Attributes["url"].Value); } }  catch (Exception ex)  { throw new ConfigurationException("Error while parsing configuration section.",ex,section); } }    public NameValueCollection Map { get { return _commands; } }
}

下面的代码是从显示配置的 web.config 文件中摘录的:

<controller.mapping> <entries> <entry key="/patterns/frontc/3/Page1.aspx" url="ActualPage1.aspx" /> <entry key="/patterns/frontc/3/Page2.aspx" url="ActualPage2.aspx" /> </entries>
</controller.mapping>  
 

MicroSite.cs

MicroSite 类与此模式前面的 LoadMicroHeader 中的代码类似。主要区别是,无法再访问页面中包含的标签。而必须将信息添加到 HttpContext 对象。下面的示例显示了MicroSite 代码:

using System;
using System.Web;
public class MicroSite : RedirectingCommand
{ protected override void OnExecute(HttpContext context) { string name = context.User.Identity.Name; context.Items["address"] =  WebUsersDatabase.RetrieveAddress(name); context.Items["site"] = "Micro-Site"; }
}

MacroSite.cs

MacroSite 类与 MicroSite 类似,但它使用的是不同的数据库网关类 MacroUsersDatabase。这两个类都将信息存储在传递进来的 HttpContext 中,以便让视图可以检索它。下面的示例显示了 MacroSite 代码:

using System;
using System.Web;
public class MacroSite : RedirectingCommand
{ protected override void OnExecute(HttpContext context) { string name = context.User.Identity.Name; context.Items["address"] =  MacroUsersDatabase.RetrieveAddress(name); context.Items["site"] = "Macro-Site"; }
}

WebUsersDatabase.cs

WebUsersDatabase 类负责从“webusers”数据库中检索电子邮件地址。它是 Table Data Gateway [Fowler03] 模式的一个示例。

using System;
using System.Data;
using System.Data.SqlClient;
public class WebUsersDatabase
{ public static string RetrieveAddress(string name) { string address = null; String selectCmd =  String.Format("select * from webuser where (id = '{0}')", name); SqlConnection myConnection =  new SqlConnection("server=(local);database=webusers;Trusted_Connection=yes"); SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection); DataSet ds = new DataSet(); myCommand.Fill(ds,"webuser"); if(ds.Tables["webuser"].Rows.Count == 1) { DataRow row = ds.Tables["webuser"].Rows[0]; address = row["address"].ToString(); } return address; }
}

MacroUsersDatabase.cs

MacroUsersDatabase 类负责从“macrousers”数据库中检索电子邮件地址。它是 Table Data Gateway 模式的一个示例。

using System;
using System.Data;
using System.Data.SqlClient;
public class MacroUsersDatabase
{ public static string RetrieveAddress(string name) { string address = null; String selectCmd =  String.Format("select * from customer where (id = '{0}')", name); SqlConnection myConnection =  new SqlConnection("server=(local);database=macrousers;Trusted_Connection=yes"); SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection); DataSet ds = new DataSet(); myCommand.Fill(ds,"customer"); if(ds.Tables["customer"].Rows.Count == 1) { DataRow row = ds.Tables["customer"].Rows[0]; address = row["email"].ToString(); } return address; }
} 
 
视图

视图最后实现。“更改需求”中的示例视图负责根据用户访问哪个站点从数据库中检索信息,然后向用户显示所产生的页面。因为数据库访问代码已移到命令,所以视图现在从ttpContext 对象检索数据。图 3 显示了代码隐藏类的结构。

3 视图的代码隐藏类的结构

由于仍然存在公共行为,因此仍然需要 BasePage 类以避免代码重复。

BasePage.cs

与“更改需要”中的示例相比,BasePage 类已有大幅更改。它不再负责确定要加载哪个站点头信息。它只检索由命令存储在 HttpContext 对象中的数据,并将它们分配给适当的标签:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class BasePage : Page
{ protected Label eMail; protected Label siteName; virtual protected void PageLoadEvent(object sender, System.EventArgs e) {} protected void Page_Load(object sender, System.EventArgs e) { if(!IsPostBack) { eMail.Text = (string)Context.Items["address"]; siteName.Text = (string)Context.Items["site"]; PageLoadEvent(sender, e); } } #region Web Form Designer generated code #endregion
}

ActualPage1.aspx.cs ActualPage2.aspx

ActualPage1ActualPage2 是针对具体页面的代码隐藏类。它们都是从 BasePage 继承而来的,以确保在屏幕的顶部填入头信息:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class ActualPage1 : BasePage
{ protected System.Web.UI.WebControls.Label pageNumber; protected override void PageLoadEvent(object sender, System.EventArgs e) { pageNumber.Text = "1"; } #region Web Form Designer generated code #endregion
}
using System;
using System.Web.UI.WebControls;
public class ActualPage2 : BasePage
{ protected Label pageNumber; protected override void PageLoadEvent(object sender, System.EventArgs e) { pageNumber.Text = "2"; } #region Web Form Designer generated code #endregion
}

在从 Page Controller 实现转移到 Front Controller 实现时,不必更改这些页面。

测试考虑事项

实现对 ASP.NET 运行库的依赖性使测试变得很困难。您无法将通过继承 System.Web.UI.Page System.Web.UI.IHTTPHandler 或 ASP.NET 运行库中所包含的其他各种类而得到的类进行实例化。这就无法对应用程序的大多数组成部分分别进行单元测试。自动测试此实现的所选方法是,生成 HTTP 请求,然后检索 HTTP 响应,并确定响应是否正确。此方法容易产生错误,因为这是在将响应文本与预期文本进行比较。

CommandFixture.cs

对于可测试的实现来说,导致其可测试的一个因素是 CommandFactory,因为它是独立于 ASP.NET 运行库的。因此,您可以通过编写测试步骤来验证是否获得了正确的Command 对象。下面是 CommandFactory 类的 NUnit (http://nunit.org) 测试:

using System;
using System.Collections.Specialized;
using NUnit.Framework;
[TestFixture]
public class CommandFixture
{ private static readonly string microKey = "micro"; private static readonly string macroKey = "macro"; [SetUp] public void BuildCommandFactory() { NameValueCollection map = new NameValueCollection(); map.Add(microKey, "MicroSite"); map.Add(macroKey, "MacroSite"); } [Test] public void DefaultToMicro() { NameValueCollection map = new NameValueCollection(); Command command = CommandFactory.Make(map); Assertion.AssertNotNull(command); Assertion.Assert(command is MicroSite); } [Test] public void MicroSiteCommand() { NameValueCollection map = new NameValueCollection(); map.Add("site", "micro"); Command command = CommandFactory.Make(map); Assertion.AssertNotNull(command); Assertion.Assert(command is MicroSite); } [Test] public void MacroSiteCommand() { NameValueCollection map = new NameValueCollection(); map.Add("site", "macro"); Command command = CommandFactory.Make(map); Assertion.AssertNotNull(command); Assertion.Assert(command is MacroSite); } [Test] public void Error() { NameValueCollection map = new NameValueCollection(); map.Add("site", "xyzcommand"); Command command = CommandFactory.Make(map); Assertion.AssertNotNull(command); Assertion.Assert(command is UnknownCommand); }
}

可以通过进一步的工作来隔离 Command 类。Execute 方法的一个参数是 HttpContext 对象。您可以更改此参数,使该对象独立于 ASP.NET 环境。这样,您就可以在 ASP.NET 运行库之外对命令进行单元测试。

实现 Front Controller 增加了复杂性,并导致了许多优缺点:

优点

  • 提高了灵活性。该实现展示了如何通过 Handler 类集中和协调所有请求。Handler 使用 CommandFactory 来确定要执行的具体操作。这样,就可以在不更改 Handler类的情况下修改和扩展功能。例如,要添加另一个站点,则必须创建特定命令,并且唯一必须更改的类是 CommandFactory

  • 简化了视图。Page Controller 示例中的视图从数据库检索数据,然后产生页面。在 Front Controller 中,视图不必再依赖数据库,因为这项工作是由各个命令来完成的。

  • 可以扩展,但不能修改。该实现为进行多种形式的调度提供了许多机会。例如,无论执行什么方法和对象,Handler 只调用 Command 对象的 Execute 方法。因此,您可以在不修改 Handler 的情况下添加额外的命令。通过用其他工厂代替 CommandFactory,可以对该实现进行进一步扩展。

  • URL 映射UrlMap 允许让用户看不到实际的页面名。用户输入一个 URL,然后系统将使用 web.config 文件将它映射到特定的 URL。这可以让程序员有更大的灵活性,因为这样做可以获得 Page Controller 实现中所没有的一个间接操作层。

  • 线程安全。命令对象(MicroSite 和 MacroSite)是针对每个请求分别创建的。这意味着,您不必担心这些对象中的线程安全问题。

缺点

  • 性能降低。您必须检查是否有这样的可能。所有请求都是通过 Handler 对象处理的。它使用 CommandFactory 来确定要创建哪个命令。虽然在本示例中没有性能问题,但应该仔细检查这两个类,看看是否存在任何潜在的性能问题。

  • 其他方面的问题。该实现比 Page Controller 复杂得多。该实现的确提供了更多选择,但它的代价是复杂性和许多类。您必须权衡是否值得采用该实现。在您采用该实现并构建了框架后,可以很容易地添加新的命令和视图。不过,由于 Page Controller 是在 ASP.NET 中实现的,与在其他平台上相比,Front Controller 的实现不会同样多。

  • 测试考虑事项。由于 Front Controller 是在 ASP.NET 中实现的,因此很难单独测试。要提高可测试性,应该将要测试的功能从依赖于 ASP.NET 的代码中分离到不依赖于 ASP.NET 的类中。然后,您不必启动 ASP.NET 运行库就可以测试这些类。

  • 无效的 URL。因为 Front Controller 根据输入参数和应用程序的其他当前状态来决定要转到哪个视图,因此,URL 可能不会总是转到同一个页面。这样就会让用户无法保存 URL,也就无法随后再访问该页面。

相关模式

有关详细信息,请参阅以下相关模式:

  • Template Method [Gamma95] BasePage 类的 PageLoadEvent 方法是 Template Method 的实现示例。

  • Intercepting Filter.

  • Page Controller.

  • Command [Gamma95].

  • Factory。此模式前面所描述的工厂将来自 Factory Method [Gamma95] Abstract Factory [Gamma95] 的元素组合在一起。

致谢

[Fowler03] Fowler, Martin. Patterns of Enterprise Application Architecture. Addison-Wesley, 2003.

[Gamma95] Gamma, Helm, Johnson, and Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.

转载于:https://www.cnblogs.com/luqingfei/archive/2013/03/20/2971218.html

在 ASP.NET 中使用 HTTPHandler 实现 Front Controller相关推荐

  1. 在ASP.NET中实现Url Rewriting(非常的有价值!)

    在ASP.NET中实现Url Rewriting 作者:Scott Mitchell 翻译:Janssen 1.0.请一定要抱着批评的态度来看该文章 1.1. 概要 分析如何使用微软提供的ASP.NE ...

  2. webconfig中注册HttpHandler报错:检测到在集成的托管管道模式下不适用的 ASP.NET 设置。...

    webconfig中注册HttpHandler报错:检测到在集成的托管管道模式下不适用的 ASP.NET 设置. 为什么会出现以上错误? 在IIS7的应用程序池有两种模式,一种是"集成模式& ...

  3. Asp.net中的HttpModule和HttpHandler的简单用法

    在Asp.net中,HttpModule和HttpHandler均可以截取IIS消息进行处理,这使得我们制作人员能够非常方便的进行诸如图片水印添加,图片盗链检查等功能. 下面先就HttpModule的 ...

  4. 在ASP.NET中跟踪和恢复大文件下载

    在Web应用程序中处理大文件下载的问题一直出了名的困难,因此对于大多数站点来说,如果用户的下载被中断了,它们只能说悲哀降临到用户的身上了.但是我们现在不必这样了,因为你可以使自己的ASP.NET应用程 ...

  5. ASP.NET的(HttpModule,HttpHandler)

    在以前的ASP时候,当请求一个*.asp页面文件的时候,这个HTTP请求首先会被一个名为inetinfo.exe进程所截获,这个进程实际上就是www服务.截获之后它会将这个请求转交给asp.dll进程 ...

  6. ASP.Net中自定义Http处理及应用之HttpModule篇

    HttpHandler实现了类似于ISAPI Extention的功能,他处理请求(Request)的信息和发送响应(Response).HttpHandler功能的实现通过实现IHttpHandle ...

  7. Asp.net中的web.config配置

    Asp.net中的web.config配置 Asp.net中的web.config配置... 1 一. 配置文件保存位置... 2 二. 配置文件加载顺序... 2 三. 配置文件节点介绍... 3 ...

  8. ASP.NET中常用的文件上传下载方法

    ASP.NET中常用的文件上传下载方法 文件的上传下载是我们在实际项目开发过程中经常需要用到的技术,这里给出几种常见的方法,本文主要内容包括: 1.如何解决文件上传大小的限制 2.以文件形式保存到服务 ...

  9. 在ASP.NET中实现Url Rewriting

    概要 分析如何使用微软提供的ASP.NET来对动态产生的URL地址进行网址重写. 网址重写是实现一种截取网址请求并将其进行处理后重新指向到一个指定的网址的过程.作者本人在对各种实现网址重写的技术进行研 ...

最新文章

  1. 《信息学奥赛一本通》 高精度乘法。输入两个正整数,求它们的积。
  2. 直接插入排序,折半插入排序,希尔排序,简单选择排序,冒泡排序,快速排序模板以及比较次数与移动次数的分析,折半搜索算法模板
  3. 根据年月日判断第多少天,星期几
  4. python使用logging捕获异常后继续执行函数
  5. linux命令th,Linux 第13天 文本操作命令
  6. C++ - 派生类访问模板基类(templatized base class)命名
  7. 计算机毕业设计——选题参考
  8. 基于Flink建设流批一体实时数仓
  9. Photoshop CC 2019暂存盘不足无法打开
  10. 一招教你解决Rational rose画时序图(Sequence diagram)时找不到参与者(Actor)的尴尬现场
  11. 去中心化的联邦学习专栏
  12. 专访李智慧:架构是最高层次的规划和难以改变的决定
  13. c++win32项目 如何显示后再删除一个绘图_CAD提高绘图效率的秘诀在这里
  14. [转载] 花了三个月终于把所有的Python库全部整理了!祝你早日拿到高薪!
  15. php 连接sqlserver数据库(一)
  16. 巨噬细胞膜包裹载HCPT-PLGA纳米粒(HCPT-MCNP)|生物膜包载去氧氟尿苷
  17. flex的align属性:交叉轴的对齐方式
  18. 亚马逊ERP系统是什么?他有什么用
  19. 大型ERP系统在线体验账号
  20. 【程序设计】日期和时间

热门文章

  1. php中的构造函数和析构函数,php 中构造函数和析构函数
  2. 非线性振动 matlab,用MATLAB分析非线性弹簧振子的振动
  3. sql 将多个括号及内容删除_新浪微博将对逝者账号设置保护:不能登录、新发和删除内容...
  4. python 驱动级鼠标_Python介绍、安装
  5. java -c_java% c
  6. bs架构与cs架构的区别_Oracle vs Mysql--架构、sql查询执行流程及SQL解析顺序区别说明...
  7. mysql 不同的文件系统_文件系统,数据库管理系统,操作系统之间有什么联系?...
  8. 基于linux的netfilter处理数据包的过程分析,基于Linux的Netfilter处理数据包的过程分析...
  9. pythongui登录界面密码显示_用python写一个带有gui界面的密码生成器
  10. python开发环境和运行环境的区别_Django 开发环境与生产环境的区分详解