ASP.NET Core Web 應用程序系列(一)- 使用ASP.NET Core內置的IoC容器DI進行批量依賴注入(MVC當中應用)...

在正式進入主題之前我們來看下幾個概念:

一、依賴倒置

依賴倒置是編程五大原則之一,即:

1、上層模塊不應該依賴于下層模塊,它們共同依賴于一個抽象。

2、抽象不能依賴于具體,具體依賴于抽象。

其中上層就是指使用者,下層就是指被使用者。

二、IoC控制反轉

控制反轉(IoC,全稱Inversion of Control)是一種思想,所謂“控制反轉”,就是反轉獲得依賴對象的過程。

三、依賴注入(DI)

依賴注入設計模式是一種在類及其依賴對象之間實現控制反轉(IoC)思想的技術。

所謂依賴注入(DI,全稱Dependency Injection),就是由IoC容器在運行期間,動態地將某種依賴關系注入到對象之中。

依賴注入主要分為3種:構造函數注入、屬性注入、方法注入。

?

這里就不做過多的描述,如果有機會會通過具體例子再和大家分享,下面我們正式進入本章主題。

PS:ASP.NET Core 內置的IoC容器目前只支持構造函數注入,以下我們也主要講解構造函數注入的方式。

話不多說,直入主題看我們的解決方案結構:

分別對上面的工程進行簡單的說明:

1、TianYa.DotNetShare.Model:為demo的實體層

2、TianYa.DotNetShare.Repository:為demo的倉儲層即數據訪問層

3、TianYa.DotNetShare.Service:為demo的服務層即業務邏輯層

4、TianYa.DotNetShare.CommTool:為demo的公共工具類庫

5、TianYa.DotNetShare.SharpCore:為demo的Sharp核心類庫

6、TianYa.DotNetShare.CoreMvcDemo:為demo的web層項目,MVC框架

約定:

1、公共的類庫,我們選擇.NET Standard 2.0作為目標框架,可與Framework進行共享。

2、本demo的web項目為ASP.NET Core Web 應用程序(.NET Core 2.2) MVC框架。

一、實體層

1、新建一個學生實體?Student

using System;
using System.Collections.Generic;
using System.Text;namespace TianYa.DotNetShare.Model
{/// <summary>/// 學生類/// </summary>public class Student{/// <summary>/// 學號/// </summary>public string StuNo { get; set; }/// <summary>/// 姓名/// </summary>public string Name { get; set; }/// <summary>/// 年齡/// </summary>public int Age { get; set; }/// <summary>/// 性別/// </summary>public string Sex { get; set; }}
}

demo中的實體就這樣了

二、倉儲層

本demo的倉儲層需要引用我們的實體層TianYa.DotNetShare.Model

為什么選擇用倉儲,原因很簡單,方便我們進行個性化擴展。在數據操作的底層進行其他個性化邏輯處理。

約定:

1、接口的定義放在根目錄下,接口的實現類,統一放到Impl文件夾,表示實現類目錄。

2、每個實體,對應一個倉儲的接口和實現類,即有多少個實體,就對應創建多少個接口和實現類。

3、倉儲層接口都以“I”開頭,以“Repository”結尾。倉儲層實現都以“Repository”結尾。

我們新建一個Student的倉儲接口IStudentRepository.cs

using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Repository
{/// <summary>/// 學生類倉儲層接口/// </summary>public interface IStudentRepository{/// <summary>/// 根據學號獲取學生信息/// </summary>/// <param name="stuNo">學號</param>/// <returns>學生信息</returns>Student GetStuInfo(string stuNo);}
}

接著在Impl中新建一個Student的倉儲實現StudentRepository.cs

using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Repository.Impl
{/// <summary>/// 學生類倉儲層/// </summary>public class StudentRepository : IStudentRepository{/// <summary>/// 根據學號獲取學生信息/// </summary>/// <param name="stuNo">學號</param>/// <returns>學生信息</returns>public Student GetStuInfo(string stuNo){//數據訪問邏輯,此處為了演示就簡單些var student = new Student();switch (stuNo){case "10000":student = new Student() { StuNo = "10000", Name = "張三", Sex = "", Age = 20 };break;case "10001":student = new Student() { StuNo = "10001", Name = "錢七七", Sex = "", Age = 18 };break;case "10002":student = new Student() { StuNo = "10002", Name = "李四", Sex = "", Age = 21 };break;default:student = new Student() { StuNo = "10003", Name = "王五", Sex = "", Age = 25 };break;}return student;}}
}

該類實現了IStudentRepository接口

三、服務層

本demo的服務層需要引用我們的實體層TianYa.DotNetShare.Model和我們的倉儲層TianYa.DotNetShare.Repository

服務層與倉儲層類似,它屬于倉儲層的使用者。定義的方式也與倉儲層類似,有接口和Impl實現目錄。

但服務層不需要一個實體對應一個,服務層更多的是按照功能模塊進行劃分,比如一個登錄模塊,創建一個LoginService。

約定:

1、服務層接口都以“I”開頭,以“Service”結尾。服務層實現都以“Service”結尾。

為了演示,我們新建一個Student的服務層接口IStudentService.cs

using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Service
{/// <summary>/// 學生類服務層接口/// </summary>public interface IStudentService{/// <summary>/// 根據學號獲取學生信息/// </summary>/// <param name="stuNo">學號</param>/// <returns>學生信息</returns>Student GetStuInfo(string stuNo);}
}

接著我們同樣在Impl中新建一個Student的服務層實現StudentService.cs

using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Repository;namespace TianYa.DotNetShare.Service.Impl
{/// <summary>/// 學生類服務層/// </summary>public class StudentService : IStudentService{/// <summary>/// 定義倉儲層學生抽象類對象/// </summary>protected IStudentRepository StuRepository;/// <summary>/// 空構造函數/// </summary>public StudentService() { }/// <summary>/// 構造函數/// </summary>/// <param name="stuRepository">倉儲層學生抽象類對象</param>public StudentService(IStudentRepository stuRepository){this.StuRepository = stuRepository;}/// <summary>/// 根據學號獲取學生信息/// </summary>/// <param name="stuNo">學號</param>/// <returns>學生信息</returns>public Student GetStuInfo(string stuNo){var stu = StuRepository.GetStuInfo(stuNo);return stu;}}
}

該類實現了IStudentService接口

四、公共工具類庫

公共工具類庫就是將來我們要在里面寫各種各樣的幫助類以提高程序的可復用性,此處就不做贅述。

五、Sharp核心類庫

需要從NuGet上引用以下幾個程序集:

Sharp核心類庫為公共的基礎類,最底層。

其中Model文件夾為實體目錄,主要存放數據庫連接相關的實體。Extensions文件夾為擴展目錄,主要存放最底層的擴展類,我們底層的批量依賴注入就放在這里面。

在Model實體目錄中我們新建一個用于數據庫連接的接口IDataBaseSetting.cs

using System;
using System.Collections.Generic;
using System.Text;namespace TianYa.DotNetShare.SharpCore.Model
{public interface IDataBaseSetting{/// <summary>/// 訪問數據庫連接串/// </summary>string ConnectionString { get; set; }/// <summary>/// 數據庫名稱,當是關系型數據庫時,DatabaseName屬性沒用到/// </summary>string DatabaseName { get; set; }}
}

接著添加一個用于數據庫連接的實現類DataBaseSetting.cs

using System;
using System.Collections.Generic;
using System.Text;namespace TianYa.DotNetShare.SharpCore.Model
{public class DataBaseSetting : IDataBaseSetting{/// <summary>/// 訪問數據庫連接串/// </summary>public string ConnectionString { get; set; }/// <summary>/// 數據庫名稱,當是關系型數據庫時,DatabaseName屬性沒用到/// </summary>public string DatabaseName { get; set; }}
}

該類實現了IDataBaseSetting.cs接口

Model實體目錄主要用于以后涉及到數據庫訪問的時候使用,本demo主要為了簡單介紹下如何使用ASP.NET Core內置的IoC容器DI進行批量依賴注入,故沒有對該實體目錄進行詳細的講解。

接下來就是重頭戲了,我們在Extensions擴展目錄中添加一個用于批量依賴注入的擴展類ServiceCollectionExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;using TianYa.DotNetShare.SharpCore.Model;namespace TianYa.DotNetShare.SharpCore.Extensions
{/// <summary>/// ServiceCollection擴展/// </summary>public static class ServiceCollectionExtensions{#region 通過反射批量注入指定的程序集/// <summary>/// 通過反射批量注入指定的程序集/// </summary>/// <param name="services">服務</param>/// <param name="assemblyNames">程序集數組 如:["TianYa.DotNetShare.Repository","TianYa.DotNetShare.Service"],無需寫dll</param>public static void RegisterTianYaSharpService(this IServiceCollection services, params string[] assemblyNames){foreach (string assemblyName in assemblyNames){foreach (var itemClass in GetClassInterfacePairs(assemblyName)){foreach (var itemInterface in itemClass.Value){if (itemInterface != typeof(DataBaseSetting)){services.AddTransient(itemInterface, itemClass.Key); //DI依賴注入
                        }}}}}#endregion#region DI依賴注入輔助方法/// <summary>/// 獲取類以及類實現的接口鍵值對/// </summary>/// <param name="assemblyName">程序集名稱</param>/// <returns>類以及類實現的接口鍵值對</returns>private static Dictionary<Type, List<Type>> GetClassInterfacePairs(string assemblyName){//存儲 實現類 以及 對應接口Dictionary<Type, List<Type>> dic = new Dictionary<Type, List<Type>>();Assembly assembly = GetAssembly(assemblyName);if (assembly != null){Type[] types = assembly.GetTypes();foreach (var item in types.AsEnumerable().Where(x => !x.IsAbstract && !x.IsInterface && !x.IsGenericType)){dic.Add(item, item.GetInterfaces().Where(x => !x.IsGenericType).ToList());}}return dic;}/// <summary>/// 獲取所有的程序集/// </summary>/// <returns>程序集集合</returns>private static List<Assembly> GetAllAssemblies(){var list = new List<Assembly>();var deps = DependencyContext.Default;var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系統程序集、Nuget下載包foreach (var lib in libs){try{var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));list.Add(assembly);}catch (Exception){// ignored
                }}return list;}/// <summary>/// 獲取指定的程序集/// </summary>/// <param name="assemblyName">程序集名稱</param>/// <returns>程序集</returns>private static Assembly GetAssembly(string assemblyName){return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));}#endregion}
}

并且添加一個Dynamic的擴展類DynamicExtensions.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Xml;namespace TianYa.DotNetShare.SharpCore.Extensions
{/// <summary>/// Dynamic的擴展方法/// </summary>public static class DynamicExtensions{#region 匿名對象處理#region 將對象[主要是匿名對象]轉換為dynamic/// <summary>/// 將對象[主要是匿名對象]轉換為dynamic/// </summary>public static dynamic ToDynamic(this object value){IDictionary<string, object> expando = new ExpandoObject();var type = value.GetType();var properties = TypeDescriptor.GetProperties(type);foreach (PropertyDescriptor property in properties){var val = property.GetValue(value);if (property.PropertyType.FullName.StartsWith("<>f__AnonymousType")){dynamic dval = val.ToDynamic();expando.Add(property.Name, dval);}else{expando.Add(property.Name, val);}}return expando as ExpandoObject;}#endregion#region 將對象[主要是匿名對象]轉換為List<dynamic>/// <summary>/// 將對象[主要是匿名對象]轉換為List<dynamic>/// </summary>public static List<dynamic> ToDynamicList(this IEnumerable<dynamic> values){var list = new List<dynamic>();if (values != null){if (values.Any()){list.AddRange(values.Select(v => ((object)v).ToDynamic()));}}return list;}#endregion#region 將匿名對象集合轉換為XML/// <summary>/// 將匿名對象集合轉換為XML/// </summary>public static XmlDocument ListObjertToXML(this IEnumerable<dynamic> values){var xmlDoc = new XmlDocument();var xmlElem = xmlDoc.CreateElement("DocumentElement");xmlDoc.AppendChild(xmlElem);if (values != null){if (values.Any()){var node = xmlDoc.SelectSingleNode("DocumentElement");foreach (var item in values){var xmlRow = xmlDoc.CreateElement("Row");ObjectToXML(item, xmlDoc, xmlRow);node.AppendChild(xmlRow);}}}return xmlDoc;}#endregion#region 將匿名對象填充XML節點/// <summary>/// 將匿名對象填充XML節點/// </summary>private static void ObjectToXML(object value, XmlDocument xmlDoc, XmlElement xmlRow){IDictionary<string, object> expando = new ExpandoObject();var type = value.GetType();var properties = TypeDescriptor.GetProperties(type);foreach (PropertyDescriptor property in properties){var val = property.GetValue(value);xmlRow.CloneNode(false);var xmlTemp = xmlDoc.CreateElement(property.Name);XmlText xmlText;if (property.PropertyType.FullName.StartsWith("<>f__AnonymousType")){dynamic dval = val.ToDynamic();xmlText = xmlDoc.CreateTextNode(dval.ObjectToString());}else{xmlText = xmlDoc.CreateTextNode(val.ToString());}xmlTemp.AppendChild(xmlText);xmlRow.AppendChild(xmlTemp);}}#endregion#endregion}
}

該擴展類主要在我們的Action向視圖傳遞匿名類型值的時候使用

六、Web層

本demo的web項目需要引用以下幾個程序集:

1、TianYa.DotNetShare.Model 我們的實體層

2、TianYa.DotNetShare.Service 我們的服務層

3、TianYa.DotNetShare.Repository 我們的倉儲層,正常我們的web項目是不應該使用倉儲層的,此處我們引用是為了演示IoC依賴注入

4、TianYa.DotNetShare.CommTool 我們的公共工具類庫

5、TianYa.DotNetShare.SharpCore 我們的Sharp核心類庫

到了這里我們所有的工作都已經準備好了,接下來就是開始做注入工作了。

打開我們的Startup.cs文件進行注入工作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;using TianYa.DotNetShare.SharpCore.Extensions;namespace TianYa.DotNetShare.CoreMvcDemo
{public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.Configure<CookiePolicyOptions>(options =>{// This lambda determines whether user consent for non-essential cookies is needed for a given request.options.CheckConsentNeeded = context => true;options.MinimumSameSitePolicy = SameSiteMode.None;});services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);//DI依賴注入,批量注入指定的程序集services.RegisterTianYaSharpService(new string[] { "TianYa.DotNetShare.Repository", "TianYa.DotNetShare.Service" });}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();app.UseCookiePolicy();app.UseMvc(routes =>{routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});}}
}

其中用來實現批量依賴注入的只要一句話就搞定了,如下所示:

//DI依賴注入,批量注入指定的程序集
services.RegisterTianYaSharpService(new string[] { "TianYa.DotNetShare.Repository", "TianYa.DotNetShare.Service" });

Sharp核心類庫在底層實現了批量注入的邏輯,程序集的注入必須按照先后順序進行,先進行倉儲層注入然后再進行服務層注入。

接下來我們來看看控制器里面怎么弄:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;using TianYa.DotNetShare.CoreMvcDemo.Models;
using TianYa.DotNetShare.Service;
using TianYa.DotNetShare.Repository;namespace TianYa.DotNetShare.CoreMvcDemo.Controllers
{public class HomeController : Controller{/// <summary>/// 定義倉儲層學生抽象類對象/// </summary>protected IStudentRepository StuRepository;/// <summary>/// 定義服務層學生抽象類對象/// </summary>protected IStudentService StuService;/// <summary>/// 通過構造函數進行注入/// 注意:參數是抽象類,而非實現類,因為已經在Startup.cs中將實現類映射給了抽象類/// </summary>/// <param name="stuRepository">倉儲層學生抽象類對象</param>/// <param name="stuService">服務層學生抽象類對象</param>public HomeController(IStudentRepository stuRepository, IStudentService stuService){this.StuRepository = stuRepository;this.StuService = stuService;}public IActionResult Index(){var stu1 = StuRepository.GetStuInfo("10000");var stu2 = StuService.GetStuInfo("10001");string msg = $"學號:10000,姓名:{stu1.Name},性別:{stu1.Sex},年齡:{stu1.Age}<br />";msg += $"學號:10001,姓名:{stu2.Name},性別:{stu2.Sex},年齡:{stu2.Age}";return Content(msg, "text/html", System.Text.Encoding.UTF8);}public IActionResult Privacy(){return View();}[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]public IActionResult Error(){return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });}}
}

至此,完成處理,接下來就是見證奇跡的時刻了,我們來訪問一下/home/index,看看是否能返回學生信息。

我們可以發現,返回了學生的信息,說明我們注入成功了。

另外通過這個例子我們可以發現在注入倉儲層對象StudentRepository時,不僅控制器中注入成功了,而且在服務層中也注入成功了,說明我們ASP.NET Core內置的IoC容器DI依賴注入是全局的。

總結:

1、采用的是構造函數注入的方式,在構造函數中初始化賦值。

2、ASP.NET Core內置的IoC容器DI依賴注入是全局的。

3、DI批量依賴注入的核心思想就是根據程序集的名稱通過反射獲取類以及類實現的接口鍵值對字典,然后通過循環進行批量注入。

?

擴展:DI生命周期

生命周期是依賴注入設計原則里一個非常重要的概念,ASP.NET Core 一共有3種生命周期。

1、暫時(Transient):顧名思義,這種生命周期的對象是暫時的,每次請求都會創建一個新的實例。

services.AddTransient<IStudentRepository, StudentRepository>();
services.AddTransient<IStudentService, StudentService>();

2、作用域(Scoped):每次請求使用的是同一個實例。

services.AddScoped<IStudentRepository, StudentRepository>();
services.AddScoped<IStudentService, StudentService>();

3、單例(Singleton):第一次請求時就創建,以后每次請求都是使用相同的實例。

services.AddSingleton<IStudentRepository, StudentRepository>();
services.AddSingleton<IStudentService, StudentService>();

官方文檔建議:依賴注入是靜態/全局對象訪問模式的替代方法,如果將其與靜態對象訪問混合使用,則可能無法實現依賴關系注入的優點。

至此,本章就介紹完了,如果你覺得這篇文章對你有所幫助請記得點贊哦,謝謝!!!

demo源碼:

鏈接:https://pan.baidu.com/s/17GIgvp0JWy8BaNOE8l6p9A 
提取碼:i9hh

?

參考博文:https://www.cnblogs.com/fei686868/p/11077997.html

版權聲明:如有雷同純屬巧合,如有侵權請及時聯系本人修改,謝謝!!!

轉載于:https://www.cnblogs.com/xyh9039/p/11373269.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247123.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247123.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247123.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iOS中XML解析

iOS中XML解析分為兩種實現方式&#xff1a;SAX與DOM SAX方式&#xff1a;主要是事件驅動的解析方式&#xff0c;是逐行讀取XML數據&#xff0c;不斷回調代理&#xff0c;告訴代理當前解析的元素開始或者結束。 DOM解析方式&#xff1a;是講整個XML數據全部讀入內存&#xff0…

蘋果電腦基本設置+Linux 命令+Android 實戰集錦

本文微信公眾號「AndroidTraveler」首發。 背景 大多數應屆畢業生在大學期間使用的比較多的是 windows 電腦&#xff0c;因此初入職場如果拿到一臺蘋果電腦&#xff0c;可能一時間不能夠很快的上手。基于此&#xff0c;這邊出了系列視頻&#xff0c;通過實際的演示讓沒使用過蘋…

iOS中POST請求

iOS中POST請求的發送需要使用NSMutableURLRequest可以設置URL request的頭字段&#xff0c;比如超時時間&#xff0c;請求類型&#xff1a;GET POST等一些關鍵頭字段&#xff1a; - (IBAction)login { // 1.用戶名 NSString *usernameText self.username.text; if (userna…

發送JSON數據給服務器

需要將JSON格式的數據傳送給服務器&#xff0c;注意需要設置&#xff1a; [request setValue:”application/json” forHTTPHeaderField:”Content-Type”]; Content-Type類型為&#xff1a;application/json // 1.URL NSURL *url [NSURL URLWithString:"http://localh…

Mac中AndroidStudio沒有找到Plugins的問題

我們在windows中都可以正常找到plugins 但是在Mac上AndroidStudio里 setting打開卻沒有plugins 正準備在Mac上搞一下flutter呢 我感覺智商受到了侮辱&#xff01; 這里其實是mac版本給我開了個玩笑 你可以按快捷鍵&#xff0c;你就可以找到 快捷鍵 command ‘,’ 沒錯就是comm…

進程和操作系統概述

進程和操作系統概述 進程的基礎 程序和進程&#xff1a; 程序是一對靜態的代碼文件 進程是一個正在運行著的程序&#xff0c;抽象概念 進程由操作系統操控調用交于CPU運行 操作系統 1.管理控制協調計算機硬件和軟件的關系 2.操作系統的作用&#xff1f; ? 第一個作用&#xff…

iOS手勢操作簡介(一)

iOS中能夠響應手勢操作的類必須要繼承自UIResponder&#xff0c;才能夠處理手勢響應操作。 默認繼承了UIResponder的類有&#xff1a;UIApplication UIViewController UIView都繼承自UIResponder. UIView是UIResponder的子類&#xff0c;可以實現下列4個方法處理不同的觸摸事…

iOS開發中手勢處理簡介(二)

iOS中手勢操作事件的產生于傳遞 發生觸摸事件后&#xff0c;系統會將該事件加入到一個由UIApplication管理的事件隊列中 UIApplication會從事件隊列中取出最前面的事件&#xff0c;并將事件分發下去以便處理&#xff0c;通常&#xff0c;先發送事件給應用程序的主窗口&#x…

對前端Jenkins自動化部署的研究

1. 安裝 安裝 Nginx 1.1去官網下直接下載&#xff0c;解壓縮 start nginx就可以使了&#xff0c;常用命令&#xff1a; start nginx # 啟動 nginx -s reload # 修改配置后重新加載生效 nginx -s reopen # 重新打開日志文件 nginx -t # 配置文件檢測是否正確 1.2 安裝Jenkins…

python超神之路:Python3 列表list合并的4種方法

Python3 列表list合并的4種方法 方法1: 直接使用""號合并列表 aList [1,2,3] bList [www, pythontab.com] cList aList bList dList bList aList print(cList) print(dList) # 結果&#xff1a; [1, 2, 3, www, pythontab.com] [www, pythontab.com, 1, 2, 3] …

iOS手勢操作簡介(三)

監聽觸摸事件的做法 如果想監聽一個view上面的觸摸事件&#xff0c;之前的做法是 自定義一個view 實現view的touches方法&#xff0c;在方法內部實現具體處理代碼 通過touches方法監聽view觸摸事件&#xff0c;有很明顯的幾個缺點 必須得自定義view 由于是在view內部的to…

iOS手勢操作簡介(四)

當事件傳遞到相應的UIResponder后&#xff0c;會首先調用&#xff1a; hitTest:withEvent: return (UIView *) UIApplication -> UIWindow 什么時候調用&#xff1a;當事件傳遞給一個控件的時候就會調用 作用&#xff1a;找最合適的viewhitTest:withEvent: return (UIView…

ASP.NET Core Web 應用程序系列(二)- 在ASP.NET Core中使用Autofac替換自帶DI進行批量依賴注入(MVC當中應用)...

在上一章中主要和大家分享在MVC當中如何使用ASP.NET Core內置的DI進行批量依賴注入&#xff0c;本章將繼續和大家分享在ASP.NET Core中如何使用Autofac替換自帶DI進行批量依賴注入。 PS&#xff1a;本章將主要采用構造函數注入的方式&#xff0c;下一章將繼續分享如何使之能夠同…

iOS手勢操作簡介(五)

利用手勢操作實現抽屜效果&#xff1a; 第一步&#xff1a;搭建UI (void)addChildView { // left UIView *leftView [[UIView alloc] initWithFrame:self.view.bounds]; leftView.backgroundColor [UIColor greenColor]; [self.view addSubview:leftView]; _leftView…

Java過濾器與SpringMVC攔截器之間的關系與區別

今天學習和認識了一下&#xff0c;過濾器和SpringMVC的攔截器的區別&#xff0c;學到了不少的東西&#xff0c;以前一直以為攔截器就是過濾器實現的&#xff0c;現在想想還真是一種錯誤啊&#xff0c;而且看的比較粗淺&#xff0c;沒有一個全局而又細致的認識&#xff0c;由于已…

iOS手勢操作簡介(六)

利用UIGestureRecognizer來對手勢進行處理&#xff1a; interface HMViewController () property (weak, nonatomic) IBOutlet UIImageView *imagView; end implementation HMViewController (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup aft…

iOS并行程序開發- GCD NSOperationQueue(1)

import UIKit let imageURLs [“http://www.planetware.com/photos-large/F/france-paris-eiffel-tower.jpg“, “http://adriatic-lines.com/wp-content/uploads/2015/04/canal-of-Venice.jpg“, “http://algoos.com/wp-content/uploads/2015/08/ireland-02.jpg“, “http:…

二次冪權限設計

設置含有的權限如增刪改查減為1,2,4,8,16 如果A包含增刪改這5個權限&#xff0c;那A的值為1247 如果B包含增改查這5個權限&#xff0c;那A的值為14813 如果C包含增刪改查減這5個權限&#xff0c;那A的值為12481631 7二進制為111,13的二進制為1101,31二進制為11111 1二進制為1&a…

最好用的koa2+mysql的RESTful API腳手架,mvc架構,支持node調試,pm2部署。

#基于webpack構建的 Koa2 restful API 服務器腳手架這是一個基于 Koa2 的輕量級 RESTful API Server 腳手架&#xff0c;支持 ES6, 支持使用TypeScript編寫。GIT地址&#xff1a;https://github.com/Allenzihan/koa2-mysql-framework.git此腳手架只安裝了一些配合koa2使用的必要…

使用putty在linux主機和windows主機之間拷貝文件(已測試可執行)

轉載于&#xff0c;請點擊 首先下載putty&#xff0c;putty下載地址zip&#xff0c; 解壓zip發現里面有plink.exe pscp.exe psftp.exe putty.exe puttygen.exe puttytel.exe等可執行文件&#xff0c;如果只是想要鏈接主機做一些操作那么使用putty.exe&#xff0c;要想要上傳 …