分析Asp.Net MVC的请求过程,我们从以下几方面看:

配置:IIS网站的配置可以分为两个块:全局 Web.Config 和本站 Web.Config 。

Asp.Net Routing属于全局性的,所以它配置在全局Web.Config 中,我们可以在如下路径中找到:“C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\Web.config“

  <?xml version="1.0" encoding="utf-8"?>
<!-- the root web configuration file -->
<configuration>
<system.web>
<httpModules>
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</httpModules>
</system.web>
</configuration>

其实我们仔细看下它的Init方法和PostResolveRequestCache,可以得到这个UrlRoutingModule是做什么的,我们看下代码:它继承自,IHttpModule ,到此我们就明白了Asp.Net MVC处理请求的HttpModule就是UrlRoutingModule。

public class UrlRoutingModule : IHttpModule {
protected virtual void Init(HttpApplication application) { application.PostResolveRequestCache += OnApplicationPostResolveRequestCache;
} private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) {
HttpContextBase context = new HttpContextWrapper(((HttpApplication)sender).Context);
PostResolveRequestCache(context);
}
public virtual void PostResolveRequestCache(HttpContextBase context) {
// Match the incoming URL against the route table
RouteData routeData = RouteCollection.GetRouteData(context);
// Do nothing if no route found
if (routeData == null) {
return;
}
// If a route was found, get an IHttpHandler from the route's RouteHandler
IRouteHandler routeHandler = routeData.RouteHandler;
RequestContext requestContext = new RequestContext(context, routeData);
// Remap IIS7 to our handler
context.RemapHandler(httpHandler);
}
}

系统启动

  1. Asp.Net MVC 入口:Application_Start() ,调用 RouteConfig.RegisterRoutes(RouteTable.Routes);

      public class MvcApplication : System.Web.HttpApplication
    {
    protected void Application_Start()
    {
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
    }
    public class RouteConfig
    {
    public static void RegisterRoutes(RouteCollection routes)
    {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}",
    defaults: new { controller = "Home", action = "Index" },
    namespaces: new string[] { "ABC.Mr.Web.Controllers" }
    );
    }
    }

2. RouteConfig.RegisterRoutes进行路由配置:根据其中代码会创建一个RouteTable(路由表)实现URL到处理程序之间的映射。

3. MapRoute会默认配置了一个MvcRouteHandler。

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
Route route = new Route(url, new MvcRouteHandler())
{
Defaults = CreateRouteValueDictionaryUncached(defaults),
Constraints = CreateRouteValueDictionaryUncached(constraints),
DataTokens = new RouteValueDictionary()
};
ConstraintValidation.Validate(route);
if ((namespaces != null) && (namespaces.Length > ))
{
route.DataTokens[RouteDataTokenKeys.Namespaces] = namespaces;
}
routes.Add(name, route);
return route;
}
public class MvcRouteHandler : IRouteHandler
{
private IControllerFactory _controllerFactory;
public MvcRouteHandler()
{
}
public MvcRouteHandler(IControllerFactory controllerFactory)
{
_controllerFactory = controllerFactory;
}
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
return new MvcHandler(requestContext);
}
protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)
{
string controllerName = (string)requestContext.RouteData.Values["controller"];
if (String.IsNullOrWhiteSpace(controllerName))
{
throw new InvalidOperationException(MvcResources.MvcRouteHandler_RouteValuesHasNoController);
}
IControllerFactory controllerFactory = _controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
}
#region IRouteHandler Members
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return GetHttpHandler(requestContext);
}
#endregion
}

4. MvcHandler实现了三个接口IHttpAsyncHandler, IHttpHandler, IRequiresSessionState4.MvcRouteHandler继承IRouteHandler,并实现了GetHttpHandler接口,返回一个IHttpHandler :MvcHandler

public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
private static readonly object _processRequestTag = new object();
internal static readonly string MvcVersion = GetMvcVersionString();
public static readonly string MvcVersionHeaderName = "X-AspNetMvc-Version";
private ControllerBuilder _controllerBuilder;
public MvcHandler(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
RequestContext = requestContext;
}
internal ControllerBuilder ControllerBuilder
{
get
{
if (_controllerBuilder == null)
{
_controllerBuilder = ControllerBuilder.Current;
}
return _controllerBuilder;
}
set { _controllerBuilder = value; }
}
public static bool DisableMvcResponseHeader { get; set; }
protected virtual bool IsReusable
{
get { return false; }
}
public RequestContext RequestContext { get; private set; }
protected internal virtual void AddVersionHeader(HttpContextBase httpContext)
{
if (!DisableMvcResponseHeader)
{
httpContext.Response.AppendHeader(MvcVersionHeaderName, MvcVersion);
}
}
protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
return BeginProcessRequest(httpContextBase, callback, state);
}
protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);
IAsyncController asyncController = controller as IAsyncController;
if (asyncController != null)
{
// asynchronous controller
// Ensure delegates continue to use the C# Compiler static delegate caching optimization.
BeginInvokeDelegate<ProcessRequestState> beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState, ProcessRequestState innerState)
{
try
{
return innerState.AsyncController.BeginExecute(innerState.RequestContext, asyncCallback, asyncState);
}
catch
{
innerState.ReleaseController();
throw;
}
};
EndInvokeVoidDelegate<ProcessRequestState> endDelegate = delegate(IAsyncResult asyncResult, ProcessRequestState innerState)
{
try
{
innerState.AsyncController.EndExecute(asyncResult);
}
finally
{
innerState.ReleaseController();
}
};
ProcessRequestState outerState = new ProcessRequestState()
{
AsyncController = asyncController, Factory = factory, RequestContext = RequestContext
}; SynchronizationContext callbackSyncContext = SynchronizationContextUtil.GetSynchronizationContext();
return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, outerState, _processRequestTag, callbackSyncContext: callbackSyncContext);
}
else
{
// synchronous controller
Action action = delegate
{
try
{
controller.Execute(RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
};
return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag);
}
}
protected internal virtual void EndProcessRequest(IAsyncResult asyncResult)
{
AsyncResultWrapper.End(asyncResult, _processRequestTag);
}
private static string GetMvcVersionString()
{
// DevDiv 216459:
// This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in
// medium trust. However, Assembly.FullName *is* accessible in medium trust.
return new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString();
}
protected virtual void ProcessRequest(HttpContext httpContext)
{
HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
ProcessRequest(httpContextBase);
}
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);
try
{
controller.Execute(RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
}
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
// If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
// at Request.Form) to work correctly without triggering full validation.
// Tolerate null HttpContext for testing.
HttpContext currentContext = HttpContext.Current;
if (currentContext != null)
{
bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);
if (isRequestValidationEnabled == true)
{
ValidationUtility.EnableDynamicValidation(currentContext);
}
}
AddVersionHeader(httpContext);
RemoveOptionalRoutingParameters();
// Get the controller type
string controllerName = RequestContext.RouteData.GetRequiredString("controller");
// Instantiate the controller and call Execute
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);
if (controller == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.ControllerBuilder_FactoryReturnedNull,
factory.GetType(),
controllerName));
}
}
private void RemoveOptionalRoutingParameters()
{
RouteValueDictionary rvd = RequestContext.RouteData.Values;
// Ensure delegate is stateless
rvd.RemoveFromDictionary((entry) => entry.Value == UrlParameter.Optional);
}
#region IHttpHandler Members
bool IHttpHandler.IsReusable
{
get { return IsReusable; }
}
void IHttpHandler.ProcessRequest(HttpContext httpContext)
{
ProcessRequest(httpContext);
}
#endregion
#region IHttpAsyncHandler Members
IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return BeginProcessRequest(context, cb, extraData);
}
void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
{
EndProcessRequest(result);
}
#endregion
// Keep as value type to avoid allocating
private struct ProcessRequestState
{
internal IAsyncController AsyncController;
internal IControllerFactory Factory;
internal RequestContext RequestContext;
internal void ReleaseController()
{
Factory.ReleaseController(AsyncController);
}
}
}

请求开始

1. 在IIS中 HTTP.SYS文件负责把请求传入相应的应用程序池中。(当创建一个应用程序池,该池的ID就会生成并在HTTP.SYS文件中注册)

2. 当应用程序池接收到请求,会接着传给工作进程w3wp.exe,该进程检查来请求的URL后缀以确定加载哪个ISAPI扩展。ASP.NET加载时会附带自己的ISAPI扩展(aspnet_isapi.dll),以便在IIS中映射。

注意:如果先安装了asp.net,然后再安装IIS,就需要通过aspnet_regiis命令来注册ASP.NET中的ISAPI扩展。

3. 当工作进程加载了aspnet_isapi.dll, 就会构造一个HttpRuntime类,该类是应用程序的入口,通过ProcessRequest方法处理请求。

4. 当这个方法被调用,一个HttpContext的实例就产生了。可通过HTTPContent.Current获取到这个实例,且该实例会在整个生命周期中存活,我们通过它可以获取到一些常用对象,如Request,Response,Session 等

5. HttpRuntime会通过HttpApplicationFactory类加载一个HttpApplication对象。每一次请求都要穿过UrlRoutingModule到达HttpHandler,以便被响应.

6. 上面已经讲到了UrlRoutingModule,当PostResolveRequestCache事件得到响应后,首先就要在路由中进匹配。

    public virtual void PostResolveRequestCache(HttpContextBase context) {
// Match the incoming URL against the route table
RouteData routeData = RouteCollection.GetRouteData(context);
// Do nothing if no route found
if (routeData == null) {
return;
}
// If a route was found, get an IHttpHandler from the route's RouteHandler
IRouteHandler routeHandler = routeData.RouteHandler;
RequestContext requestContext = new RequestContext(context, routeData);
// Remap IIS7 to our handler
context.RemapHandler(httpHandler);
}

7. UrlRoutingModule在RouteCollection中查找Request匹配的RouteHandler,默认是MvcRouteHandler。

8. MvcRouteHandler 创建 MvcHandler实例. 这就是我们得到的routeHandler,其实就是 MvcHandler

9. MvcHandler执行 ProcessRequest.

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);
try
{
controller.Execute(RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
}
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
// If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
// at Request.Form) to work correctly without triggering full validation.
// Tolerate null HttpContext for testing.
HttpContext currentContext = HttpContext.Current;
if (currentContext != null)
{
bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);
if (isRequestValidationEnabled == true)
{
ValidationUtility.EnableDynamicValidation(currentContext);
}
} AddVersionHeader(httpContext);
RemoveOptionalRoutingParameters(); // Get the controller type
string controllerName = RequestContext.RouteData.GetRequiredString("controller"); // Instantiate the controller and call Execute
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);
if (controller == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.ControllerBuilder_FactoryReturnedNull,
factory.GetType(),
controllerName));
}
}

10. MvcHandler 使用 IControllerFactory 获得实现了IController接口的实例,找到对应的业务controller

11. 根据Request触发业务controller的和Action方法   获取Controller与Action的描述信息和过滤器信息

public abstract class ControllerBase : IController
{
protected virtual void Execute(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
if (requestContext.HttpContext == null)
{
throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext");
} VerifyExecuteCalledOnce();
Initialize(requestContext); using (ScopeStorage.CreateTransientScope())
{
ExecuteCore();
}
}
     // 抽象方法-让Controller去具体实现
protected abstract void ExecuteCore();
}
public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer
{
protected override void ExecuteCore()
{
PossiblyLoadTempData();
try
{
string actionName = GetActionName(RouteData);
if (!ActionInvoker.InvokeAction(ControllerContext, actionName))
{
HandleUnknownAction(actionName);
}
}
finally
{
PossiblySaveTempData();
}
}
}
private static string GetActionName(RouteData routeData)
{
Contract.Assert(routeData != null); // If this is an attribute routing match then the 'RouteData' has a list of sub-matches rather than
// the traditional controller and action values. When the match is an attribute routing match
// we'll pass null to the action selector, and let it choose a sub-match to use.
if (routeData.HasDirectRouteMatch())
{
return null;
}
else
{
return routeData.GetRequiredString("action");
}
}
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
} Contract.Assert(controllerContext.RouteData != null);
if (String.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch())
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
} ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName); if (actionDescriptor != null)
{
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor); try
{
AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor); if (authenticationContext.Result != null)
{
// An authentication filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
authenticationContext.Result);
InvokeActionResult(controllerContext, challengeContext.Result ?? authenticationContext.Result);
}
else
{
AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
if (authorizationContext.Result != null)
{
// An authorization filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
authorizationContext.Result);
InvokeActionResult(controllerContext, challengeContext.Result ?? authorizationContext.Result);
}
else
{
if (controllerContext.Controller.ValidateRequest)
{
ValidateRequest(controllerContext);
} IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters); // The action succeeded. Let all authentication filters contribute to an action result (to
// combine authentication challenges; some authentication filters need to do negotiation
// even on a successful result). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
postActionContext.Result);
InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,
challengeContext.Result ?? postActionContext.Result);
}
}
}
catch (ThreadAbortException)
{
// This type of exception occurs as a result of Response.Redirect(), but we special-case so that
// the filters don't see this as an error.
throw;
}
catch (Exception ex)
{
// something blew up, so execute the exception filters
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
if (!exceptionContext.ExceptionHandled)
{
throw;
}
InvokeActionResult(controllerContext, exceptionContext.Result);
} return true;
} // notify controller that no method matched
return false;
}

12. 上面的代码显示,执行action之前 ,会对controller和action的filter做判断 ,并且进行认证和授权的判断。

13,验证全部通过后会通过GetParameterValues获取方法的参数信息,执行方法InvokeActionResultWithFilters:

        protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
Func<ActionExecutedContext> continuation = () =>
new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
}; // need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
(next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
return thunk();
}
        protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
object returnValue = actionDescriptor.Execute(controllerContext, parameters);
ActionResult result = CreateActionResult(controllerContext, actionDescriptor, returnValue);
return result;
}
        protected virtual ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
{
if (actionReturnValue == null)
{
return new EmptyResult();
} ActionResult actionResult = (actionReturnValue as ActionResult) ??
new ContentResult { Content = Convert.ToString(actionReturnValue, CultureInfo.InvariantCulture) };
return actionResult;
}

14 到此已经返回了我们熟悉的ActoinResult.

Asp.Net MVC 请求原理分析的更多相关文章

  1. ASP.NET MVC源码分析

    MVC4 源码分析(Visual studio 2012/2013) HttpModule中重要的UrlRoutingModule 9:this.OnApplicationPostResolveReq ...

  2. ASP.NET MVC 源码分析(一)

    ASP.NET MVC 源码分析(一) 直接上图: 我们先来看Core的设计: 从项目结构来看,asp.net.mvc.core有以下目录: ActionConstraints:action限制相关 ...

  3. asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证

    原文:asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证 在前面的文章中我们曾经涉及到ControllerActionInvoker类GetPara ...

  4. asp.net mvc源码分析-ModelValidatorProviders 客户端的验证

    几年写过asp.net mvc源码分析-ModelValidatorProviders 当时主要是考虑mvc的流程对,客户端的验证也只是简单的提及了一下,现在我们来仔细看一下客户端的验证. 如图所示, ...

  5. Tomcat源码分析——请求原理分析(下)

    前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在& ...

  6. Tomcat源码分析——请求原理分析(中)

    前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...

  7. Tomcat源码分析——请求原理分析(上)

    前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程 ...

  8. Asp.net Mvc 请求是如何到达 MvcHandler的——UrlRoutingModule、MvcRouteHandler分析,并造个轮子

    这个是转载自:http://www.cnblogs.com/keyindex/archive/2012/08/11/2634005.html(那个比较容易忘记,希望博主不要生气的) 前言 本文假定读者 ...

  9. 窥探ASP.Net MVC底层原理 实现跨越Session的分布式TempData

    1.问题的引出 我相信大家在项目中都使用过TempData,TempData是一个字典集合,一般用于两个请求之间临时缓存数据或者页面之间传递消息.也都知道TempData是用Session来实现的,既 ...

随机推荐

  1. ssh登录服务器

    ssh -i /home/zhangsuosheng/mykey.pub myusername@111.111.111.111

  2. 解决hung_task_timeout_secs问题【方法待校验】

    问题描述:   kernel: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this messag ...

  3. var 声明变量的变量提升问题(let/const)

    在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.既全局变量. <scrip ...

  4. 深入浅出MySQL-DDL语句

    DDL语句 DDL是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建.删除.修改等操作的语言.它和DML(数据操纵语言)的最大区别是DML知识对表内部的数据操作,而不涉及表的定义.结构的修 ...

  5. 使用selenium

    1.安装谷歌浏览器 2.安装谷歌浏览器驱动 3.安装selenium包 4.测试     1.安装谷歌浏览器   2.安装谷歌浏览器驱动 打开 http://blog.csdn.net/huilan_ ...

  6. XTU1198:Candy(背包)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/libin56842/article/details/26182519 题目描写叙述 Henry和Le ...

  7. 利用ssh的私钥登录Linux server

    [https://blog.csdn.net/hello0370/article/details/41650513] 1.创建一个private key的文件,我使用vim编辑器,创建vi my_pr ...

  8. 生信-序列比较dp[未完成]

    来自:生物信息学-陈铭第二版的一个例题. 题目: 目前的代码,运行不正确,关键就是不知道怎么回溯啊,回溯怎么标记呢? #include <iostream> #include<vec ...

  9. 我与前端之间不得不说的三天两夜之jQuery

    前端基础之jquery 一 jQuery是什么? [1] jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入其team. [2] jQuery是 ...

  10. 安装memcached扩展

    1.wget http://pecl.php.net/package/memcache  下载相对应的扩展包 2. tar -zxvf memcache-2.2.7.tgz 3.  cd memcac ...