从Program开始
NetCore是一个控制台程序,Program的Main函数是程序的入口,在Main函数里创建一个主机并跑起来
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();//创建主机(kestrel)并跑起来
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)//指定kestrel
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();//通过Startup类这个控制台程序关联MVC,指定使用哪些中间件
});
}
Startup类
Startup有两个重要的方法ConfigureServices和Configure
- Configure是配置管道的,指定使用的中间件
- ConfigureServices 将服务添加到容器
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
Configure里IApplicationBuilder 的方法使用
Run
//run 是中断式中间件,终结流程,只是执行,没有去调用Next
app.Run(context=>context.Response.WriteAsync("This is Configure app.Run"));
Use
这是核心方法,传入一个RequestDelegate,返回一个RequestDelegate,通过这种链式的调用,把所有的中间件都串起来
app.Use(next =>
{
return new RequestDelegate(async context =>
{
await context.Response.WriteAsync("This is configure IApplicationBuilder Use 1 Start \r\n");
await next.Invoke(context);
await context.Response.WriteAsync("This is configure IApplicationBuilder Use 1 End \r\n");
});
});
app.Use(next =>
{
return new RequestDelegate(async context =>
{
await context.Response.WriteAsync("This is configure IApplicationBuilder Use 2 Start \r\n");
await next.Invoke(context);
await context.Response.WriteAsync("This is configure IApplicationBuilder Use 2 End \r\n");
});
});
app.Use(next =>
{
return new RequestDelegate(async context =>
{
await context.Response.WriteAsync("This is configure IApplicationBuilder Use 3 Start \r\n");
//await next.Invoke(context); 最后一个中间件没有next
await context.Response.WriteAsync("This is configure IApplicationBuilder Use 3 End \r\n");
});
});
UseWhen
可以对HttpContext检测后,增加处理环节;原来的流程还是正常执行的
app.UseWhen(context =>
{
return context.Request.Query.ContainsKey("Name");
},
appBuilder =>
{
appBuilder.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello World!");
await next();
});
});
Map和MapWhen
根据条件指定中间件 指向终结点,没有Next
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//app.Map("/Test", MapTest);//路径条件
//app.Map("/test2", a => a.Run(async context =>
//{
// await context.Response.WriteAsync($"This is test2");
//}));
app.MapWhen(context =>
{
return context.Request.Query.ContainsKey("Name");
}, MapTest);
}
private static void MapTest(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync($"Url is {context.Request.Path.Value}");
});
}
UseMiddleware
app.UseMiddleware<FirstMiddleWare>();
public class FirstMiddleWare
{
private readonly RequestDelegate _next;
public FirstMiddleWare(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await context.Response.WriteAsync($"{nameof(FirstMiddleWare)},Hello World1!<br/>");
await _next(context);
await context.Response.WriteAsync($"{nameof(FirstMiddleWare)},Hello World2!<br/>");
}
}
ConfigureServices
注入容器方法
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ITestServiceA, TestServiceA>();//瞬时
services.AddSingleton<ITestServiceB, TestServiceB>();//单例
services.AddScoped<ITestServiceC, TestServiceC>();//作用域,一次请求一个实例
}
换成Autofac
- Nuget添加依赖
Autofac.Extensions.DependencyInjection - 在Program里创建容器
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())//Autofac
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
- 在Startup注册
在Startup添加方法ConfigureContainer
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<TestServiceA>().As<ITestServiceA>().InstancePerLifetimeScope();
builder.RegisterType<TestServiceB>().As<ITestServiceB>().InstancePerLifetimeScope();
builder.RegisterType<TestServiceC>().As<ITestServiceC>().InstancePerLifetimeScope();
builder.RegisterType<TestServiceD>().As<ITestServiceD>().InstancePerLifetimeScope();
}
管道处理模型
Http请求就是一段文本,客户端Request到服务器被kestrel解析后得到HttpContext,中间经过多个步骤的加工,最后组装成Response返回客户端,这就是管理。
中间的步骤就是由中间件来完成