Nini .NET配置库(http://nini.sourceforge.net/)
VB代码的注释我保留了原文注释,它和C#注释的内容是一样的,下载链接在文章末尾。
作为开发人员,您始终需要处理应用程序配置数据。常见的示例是INI 文件,XML文件, .NET配置文件(也称为“ .config”),Windows注册表和命令行(argv)参数。配置文件的优点是它们加载速度快,不占用大量空间且易于编辑。
尝试创建配置文件访问方案不能满足程序员或最终用户的需求。为了给出真实的生活场景,我为一个使用Windows注册表API(应用程序编程接口)配置其原始程序的组织工作。后来,他们开发了自己的ASP配置类。大约在同一时间,另一个小组开发了一个API,该API可从数据库中获取数据。然后,当ASP.NET出现时,他们开始使用Web.config。在短短的几年之内,配置数据源的数量就从一增加到了四个!不用说,获取配置数据通常成为一项艰巨的任务。以下是可以改进配置管理的三个主要方面:
Nini是一个功能强大的 .NET配置库,旨在帮助快速构建高度可配置的应用程序。Nini提供了一种解决方案,试图消除上述问题。它提供了一个大型功能集,可为您提供从概念到成熟产品的每个阶段都将使用的功能。这是通过简单但灵活的API实现的,该API提供了对基础配置源的抽象。它解决了我上面描述的所有问题。我们将在下面的示例中看到如何完成此操作。
为了向您展示Nini如何解决这些问题,让我们来看一个示例。首先,让我们看一个示例配置文件。对于本手册中的大多数示例,我将选择INI 格式。INI文件是一种久经考验的真实配置文件类型,用于诸如MySQL,PHP和Samba之类的著名开源项目 。实际上,Nini支持多种INI文件类型。它们非常简单且易于编辑,因此仍然是非常受欢迎的选择。Nini包含它自己的INI解析器类(IniDocument),该类 完全用C#编写,没有 Windows API代码,因此它是跨平台的。这是此示例的MyApp.ini文本:
; MyApp.ini
[Logging]
File Name = MyApp.log
MessageColumns = 5
MaxFileSize = 40000000000000
以下是一段C#示例代码,它描述了如何从上述文件中的INI文件访问配置数据:
using Nini.Config;
IConfigSource source = new IniConfigSource("MyApp.ini");
string fileName = source.Configs["Logging"].Get("File Name");
int columns = source.Configs["Logging"].GetInt("MessageColumns");
long fileSize = source.Configs["Logging"].GetLong("MaxFileSize");
这是VB中的示例:
Imports Nini.Config
Dim source As New IniConfigSource("MyApp.ini")
Dim fileName As String = source.Configs("Logging").Get("File Name")
Dim columns As Integer = source.Configs("Logging").GetInt("MessageColumns")
Dim fileSize As Long = source.Configs("Logging").GetLong("MaxFileSize")
好的,那个例子给您带来了一些麻烦。首先,我们使用Nini.Config将Nini的配置名称空间包含在虚构的应用程序中。接下来,我们使用IniConfigSource 类加载INI文件。在Nini中,每种配置文件类型都有其自己的“ Source”类。此类知道如何加载和保存文件。这些类中的每一个都实现IConfigSource 接口,因此您可以更轻松地抽象地使用多种配置类型。加载文件后,所有部分(在本例中为[Logging]部分)都将转换为接口IConfig。 并添加到Source类的集合中。IConfig类提供了非常快速的访问权限,以检索,添加或删除配置密钥(例如上述INI文件中的“文件名”)。IConfig类的方法包括 Get, GetString, GetInt, GetFloat, GetDouble和GetLong 方法。所有以“ Get”为前缀的方法都将重载以提供更多数据。接下来的几节描述了如何使用这些重载。
有时,配置文件中不会出现选项。这可能是因为尚未将其添加到项目的主版本中,或者应将其对用户保密。对于这些情况,Nini提供了重载的方法,这些方法允许程序员定义默认值。
这是C#中的示例:
// 将缺少默认值设置为 "Default result".
string missing = config.Get("Missing Config", "Default result");
// 设置smallNumber为默认值,50
int smallNumber = config.GetInt("Not Present", 50);
这是VB中的相同示例:
' Sets missing to the default value, "Default result".
Dim missing As String = config.Get("Missing Config", "Default result")
' Sets smallNumber to the default value, 50.
Dim smallNumber As Integer = config.GetInt("Not Present", 50)
也可以设置新值并将其保存到配置文件中。调用Set方法将更改现有值,或者如果不存在则将其添加。这是一个例子:
config.Set("File Name", "MyNewFile.log");
config.Set("MessageColumns", 45);
config.Remove("File Name");
source.Save();
但是,有必要调用Save方法来保存文件,但是,您还可以在IConfigSource上设置AutoSave属性,并且每次调用Set方法时,该属性都会自动保存文件。如果要将文档保存到其他路径或对象,则IniConfigSource, XmlConfigSource和DotNetConfigSource 类都保存重载的Save方法,这些方法使您可以保存到新路径或TextWriter:
这是C#中的示例:
using System.IO;
IniConfigSource source = new IniConfigSource("Test.ini");
StringWriter writer = new StringWriter();
source.Save(writer); // 保存到StringWriter(TextWriter)
source.Save("some/new/path.ini"); // 保存到新路径
这是VB中的示例:
Imports System.IO
Dim source As IniConfigSource = new IniConfigSource("Test.ini")
Dim writer As New StringWriter()
source.Save(writer) ' Save to StringWriter(TextWriter)
source.Save("some/new/path.ini") ' Save to new path
在特定情况下,您将需要自己添加和删除IConfigs。Nini具有完成这两项操作的简单方法。这是我创建新配置然后立即将其删除的示例。
这是C#中的示例:
IConfig newConfig = source.AddConfig("NewConfig");
source.Configs.Remove(newConfig);
这是VB中的示例:
Dim newConfig As IConfig = source.AddConfig("NewConfig")
source.Configs.Remove(newConfig)
在许多情况下,您会发现您的键值取决于其他键的值。例如,您有一个根路径配置值,以及使用此路径的文件的多个值,例如以下示例:
[File Path]
RootPath = C:\Program Files\My Program
Logging = MyApp.log
WebPage = index.html
如果没有Nini,则如果要将“ RootPath”的值与“ Logging”和“ WebPage”结合使用,则必须执行难看的字符串连接才能获得“ C:\ Program Files \ My Program \ index.html”。在Nini中,您不需要这样做:
[File Path]
RootPath = C:\Program Files\My Program
Logging = ${
RootPath}\MyApp.log
WebPage = ${
RootPath}\index.html
这可以为您自己串联它们省去很多麻烦,并使您的代码更整洁。如果要从其他部分获取值,则可以执行上述操作,但是要在部分名称后添加一个横条(“ |”),如下所示:$ {section | key}。当您准备执行替换时,请调用ExpandKeyValues(注意:以前称为ReplaceKeyValues)
这是C#中的示例:
IConfigSource source = new IniConfigSource("MyApp.ini");
source.ExpandKeyValues();
这是VB中的示例:
Dim source As New IConfigSource("MyApp.ini")
source.ExpandKeyValues()
调用ExpandKeyValues时,它会一次更改配置文件中的所有键。这使代码执行更快,因为它不需要替换每个Get / GetString / GetInt / etc调用上的键值。但是,这意味着如果要使用保存配置文件,它将用扩展值覆盖以前的值。如果您不希望发生这种情况,则可以使用GetExpanded方法。
; 这会将日志记录设置为 "C:\Program Files\My Program\MyApp.log"
IConfigSource source = new IniConfigSource("MyApp.ini");
string logging = source.Configs["File Path"].GetExpanded("Logging");
这就是创建第一个Nini配置的应用程序很容易。以下各节将介绍Nini的一些更高级的功能。
合并是一项非常强大的功能,允许开发人员将来自多个源的配置数据组合到一个对象中。您可以将无数种不同的配置类型组合到一个IConfigSource中!您可以将多个INI,XML和注册表文件添加到同一对象中。你觉得很酷吗?这是一个如何将INI文件与XML文件合并的示例。
这是C#中的示例:
IConfigSource mainSource = new IniConfigSource("MyApp.ini");
IConfigSource xmlSource = new XmlConfigSource("MyApp.xml");
mainSource.Merge(xmlSource);
// 现在,您可以从mainSource和xmlSource访问任何IConfig
string xmlValue = mainSource.Configs["SomeXmlSection"].Get("AnOption");
这是VB中的示例:
Dim mainSource As New IniConfigSource("MyApp.ini")
Dim xmlSource As New XmlConfigSource("MyApp.xml")
mainSource.Merge(xmlSource)
' Now you can access any IConfig from mainSource and xmlSource
Dim xmlValue As String = mainSource.Configs("SomeXmlSection").Get("AnOption")
当数据在文件之间合并时,任何同名的IConfig或包含相同密钥的IConfig都将覆盖之前的文件。对于具有不同配置需求的客户端的用户来说,这非常重要。您可以在一个文件中创建默认配置设置,并具有特定于客户端的文件,如果需要,该文件将覆盖主文件的设置。这将节省您大量的工作。它对我有用。
许多配置文件的选项对于程序员来说是清楚的,但对非程序员来说却很混乱。为了使非程序员更容易理解配置文件,一种常见的做法是使键和值更像普通的人类对话框那样读取。让我们看一个示例,说明如何使用易于理解的字符串值返回布尔值。首先,让我们从AliasExample INI文件开始:
; AliasExample.ini
[Web Browser]
Block Popups = ON
Check For Default Browser = Off
Error Level = warn
如您所见,我不是使用每个键的值都使用“ 1”或“ true”之类的值,而是使用了“ On”和“ Off”,希望它们可以使用户更容易理解。您还将注意到,每个值之间的大小写不完全是大写或小写。我这样做是为了提出观点。用户很难记住要在特定键值中放置什么值,因此要使它们变得更容易一点也不 要使他们也记住要使用哪种情况!忽略大小写的问题是您的代码看起来很丑陋,如以下示例所示:
bool blockPopUps = (config.Get("Block Popups").ToLower() == "on");
让我们为该文件定义一些规则,使它们成为规则。我们希望 BlockPopUps部分的 值在值设置为“ On”时返回布尔值true,而在值设置为“ Off”时返回false值。此外,我希望错误级别将整数值设置为“ Warn”时返回100,而将值设置为“ Error”时返回200。下面的代码显示如何向IConfigSource的Alias属性添加规则,该属性定义了我在上一段中刚刚定义的规则。
这是C#中的示例:
IConfigSource source = new IniConfigSource("AliasExample.ini");
// 创建两个布尔别名。
source.Alias.AddAlias("On", true);
source.Alias.AddAlias("Off", false);
// 设置两个整数别名。
source.Alias.AddAlias("Error Level", "Warn", 100);
source.Alias.AddAlias("Error Level", "Error", 200);
IConfig config = source.Configs["Web Browser"];
bool blockPopUps = config.GetBoolean("BlockPopUps");
int errorCode = config.GetInt("Error Code", true);
这是VB中的示例:
Dim source As New IniConfigSource("AliasExample.ini")
' Creates two Boolean aliases.
source.Alias.AddAlias("On", True)
source.Alias.AddAlias("Off", False)
' Sets two integer aliases.
source.Alias.AddAlias("Error Level", "Warn", 100)
source.Alias.AddAlias("Error Level", "Error", 200)
Dim config As IConfig = source.Configs("Web Browser")
Dim blockPopUps = config.GetBoolean("BlockPopUps")
int errorCode = config.GetInt("Error Code", True)
对AddAlias的前两个调用 将布尔值添加到文本“ On”和“ Off”。此方法的接下来的两个调用将别名文本添加到“错误级别”配置中,并将文本分别为“警告”和“错误”以及数字值100和200。接下来,我获取了关键数据。GetInt方法已重载,因此,如果参数设置为true,则它将以别名而不是文字整数值加载数据。
Nini没有用于返回信息列表的专用方法。这是因为 .NET Framework 的String.Split方法已经有了使用小技巧的 方法。这是一个INI文件,其中服务器列表由竖线(“ |”)分隔符分隔:
[MailServers]
ServerList = "http://mail.yahoo.com/|http://www.hotmail.com/|http://www.mail.com/"
现在,使用Split方法,我们将服务器列表作为字符串数组返回:
string[] serverList = source.Configs["MailServers"].Get("ServerList").Split('|');
这是VB中的示例:
Dim serverList() As String = source.Configs("MailServers").Get("ServerList").Split('|')
您可以使用Split方法使用任意数量的分度器。要有创造力。只需选择一个不会用作键值的分度符即可。
Nini允许开发人员以非连接方式执行操作,从而使事情变得容易。通常,第一个对象可以只使用IConfig,而不必担心其他对象如何使用它。但是,有时候知道更改配置数据的时间很有用。Nini添加了许多事件来帮助处理这些情况。
在以下情况下,类需要在保存IConfigSource时通知。
这是一个C#示例:
void SourceLoad()
{
source = new IniConfigSource();
source.Saved += new EventHandler(this.source_Saved);
}
void source_Saved(object sender, EventArgs e)
{
// 在这里执行保存操作
}
这是一个VB示例:
Sub SourceLoad()
{
source = New IniConfigSource()
source.Saved += New EventHandler(Me.source_Saved)
}
Sub source_Saved(sender As object, e As EventArgs) Handles source.Saved
{
' perform save actions here
}
还有更多事件,例如Load,KeySet,KeyRemoved,ConfigAdded和ConfigRemoved。
Nini具有使用100%C#编写的内置INI解析器。这意味着,与其他INI解析器不同,它将在任何.NET平台上运行,而不仅仅是运行Windows的平台。另外,解析器的编写旨在提高灵活性,这就是为什么它支持多种INI文件类型的原因。当前支持的文件类型如下:
; 注意,load方法只是将文件名传递给构造函数的替代方法。
IConfigSource source = new IniConfigSource();
source.Load("MyApp.ini");
source.CaseSensitive = false;
Nini拥有自己的XML配置文件结构。与.NET配置文件格式相比,它提供了更大的灵活性。它的主要优点是您可以拥有多个XML配置文件,并且格式更加简洁。这是格式的示例。您会发现它非常类似于INI文件。配置值与先前示例中的INI相同:
<!-- MyApp.xml -->
<Nini>
<Section Name="Logging">
<Key Name="File Name" Value="MyApp.log" />
<Key Name="MessageColumns" Value="5" />
<Key Name="MaxFileSize" Value="40000000000000" />
</Section>
</Nini>
加载文件非常简单:
// 加载XML文件
XmlConfigSource source = new XmlConfigSource("MyApp.xml");
// 检索值
long maxFileSize = source.Configs["Logging"].GetLong("MaxFileSize");
这是VB中的示例:
' Loads the XML file
Dim source As New XmlConfigSource("MyApp.xml")
' Retrieves a value
Dim maxFileSize As Long = source.Configs("Logging").GetLong("MaxFileSize")
如果您使用的是许多Microsoft Windows操作系统之一,则可以从Windows注册表访问数据。这是注册表项的示例键路径:
HKEY_LOCAL_MACHINE\Sofware\MyApp\Logging
"File Name" "MyApp.log" REG_SZ
"MessageColumns" "5" REG_DWORD
"MaxFileSize" "40000000" REG_DWORD
要访问此代码,该方法比其他方法要复杂一些。您必须创建到注册表项的映射。此功能还将使您能够将许多注册表项合并到一个IConfigSource中。这是一些访问它的示例代码。
这是C#中的示例:
using Microsoft.Win32;
RegistryConfigSource source = new RegistryConfigSource();
// 加载注册表树
source.AddMapping(Registry.LocalMachine, "Software\\MyApp\\Logging");
// 检索值
long maxFileSize = source.Configs["Logging"].GetLong("MaxFileSize");
这是VB中的示例:
Imports Microsoft.Win32
Dim source As New RegistryConfigSource()
' Loads the registry tree
source.AddMapping(Registry.LocalMachine, "Software\\MyApp\\Logging")
' Retrieves a value
Dim maxFileSize As Long = source.Configs("Logging").GetLong("MaxFileSize")
如果您想递归地检索指定注册表项下的所有数据,也可以使用一种方法来完成。
如果要使所有子键位于具有统一名称的键下,则可以执行以下操作:
using Microsoft.Win32;
// 加载注册表树及其下的所有节点
RegistryConfigSource source = new RegistryConfigSource();
source.AddMapping(Registry.LocalMachine, "Software\\MyApp", RegistryRecurse.Flattened);
string maxFileSize = source.Configs["MyApp"].GetString("SomeConfig");
long maxFileSize = source.Configs["Logging"].GetLong("MaxFileSize");
这是VB中的示例:
Imports Microsoft.Win32
' Loads the registry tree and all nodes beneath it without
Dim source As New RegistryConfigSource()
source.AddMapping(Registry.LocalMachine, "Software\\MyApp", RegistryRecurse.Flattened)
Dim maxFileSize As String = source.Configs("MyApp").GetString("SomeConfig");
Dim maxFileSize As Long = source.Configs("Logging").GetLong("MaxFileSize")
.NET Framework具有使用特定XML格式的自己的配置文件机制 。您可能在ASP.NET中以web.config 文件的形式熟悉它们。如果将它们与Windows窗体,控制台应用程序或服务一起使用,则将它们称为[APP NAME] .exe.config文件。为了支持仍在其应用程序中使用此配置文件格式的用户,Nini也支持这些文件。
<!-- ExampleApp.exe.config -->
<configuration>
<configSections>
<section name="Logging" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<Logging>
<add key="File Name" value="MyApp.log" />
<add key="MessageColumns" value="5" />
<add key="MaxFileSize" value="40000000000000" />
</Logging>
</configuration>
访问数据与加载INI或XML文件非常相似:
IConfigSource source = new DotNetConfigSource(DotNetConfigSource.GetFullConfigPath());
string fileName = source.Configs["Logging"].Get("File Name");
int columns = source.Configs["Logging"].GetInt("MessageColumns");
long fileSize = source.Configs["Logging"].GetLong("MaxFileSize");
这是VB中的示例:
Dim source As New DotNetConfigSource(DotNetConfigSource.GetFullConfigPath())
Dim fileName As String = source.Configs("Logging").Get("File Name")
Dim columns As Integer = source.Configs("Logging").GetInt("MessageColumns")
Dim fileSize As Long = source.Configs("Logging").GetLong("MaxFileSize")
自从编程开始以来,应用程序就具有接受命令行开关的能力。这些开关只是在应用程序首次启动时传递给应用程序的字符串。Windows程序Xcopy具有许多命令行 开关 ,而出色的下载应用程序wget也具有其自己的 开关 。如果您想更多地了解.NET中命令行参数的工作方式, 请单击此处(链接无效)。我们的第一个示例与您迄今为止看到的其他示例非常相似。区别在于 AddSwitch 需要为每个键配置调用方法。有一个短键和一个长键可用于获取配置数据。
这是C#中的示例:
public static int Main(string[] args)
{
ArgvConfigSource source = new ArgvConfigSource(args);
source.AddSwitch("Logging", "file-name", "f");
source.AddSwitch("Logging", "columns", "c");
source.AddSwitch("Logging", "max-file-size", "m");
if(args.Length > 0)
{
string fileName = source.Configs["Logging"].Get("file-name");
int columns = source.Configs["Logging"].GetInt("columns");
long fileSize = source.Configs["Logging"].GetLong("max-file-size");
}
}
这是VB中的示例:
Public Static Function Main(args() As String) As Integer
Dim source As New ArgvConfigSource(args)
source.AddSwitch("Logging", "file-name", "f")
source.AddSwitch("Logging", "columns", "c")
source.AddSwitch("Logging", "max-file-size", "m")
If (args.Length > 0) Then
Dim fileName As String = source.Configs("Logging").Get("file-name")
Dim columns As Integer = source.Configs("Logging").GetInt("columns")
Dim fileSize As Long = source.Configs("Logging").GetLong("max-file-size")
End If
End Function
您可能会注意到,.NET 1.0和1.1的ConfigurationSettings类仅提供检索配置值的方法。这是因为对于程序员来说,以编程方式更改整个应用程序的配置值通常是一个坏主意。全局配置应用程序的方式由管理员决定。因此,我建议您不要更改应用程序级别设置。
但是,至关重要的是,您必须允许用户根据自己的个人喜好配置应用程序。Nini允许您创建许多不同的配置文件源,因此只需将配置文件放在正确的目录中即可。Windows程序的标准是应用程序数据目录:
C:\Documents and Settings[username]\Local Settings\Application Data[Application Name]\Settings.ini
您可以通过以下路径以编程方式获取此路径:
string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
如果您正在运行ASP.NET应用程序,则每个系统中可能会有多个用户。您可能还需要编辑许多用户设置。大多数Web应用程序都完全配置有数据库,因此以下是将Nini与数据库一起使用的示例。
这是一个带有SQL Server表的非常简单的示例。这可以很容易地适应任何其他数据库。这是数据库表的结构:
CREATE TABLE UserSettings
(
UserId ID,
Settings TEXT
);
ConfigSettings字段存储Nini配置值。现在,您可以像这样加载Nini配置值:
string userId = GetUserId(); // retrieve the user id somehow
SqlCommand command = new SqlCommand("SELECT Settings FROM UserSettings WHERE ID = "
+ userId, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if(reader.HasRows) {
reader.Read();
IConfigSource source = new XmlConfigSource(new StringReader(reader.GetString(0)));
}
reader.Close();
connection.Close();
对于任何开发项目而言,能够自动创建构建都是必不可少的。有几种工具可以完成此任务,例如批处理(.bat)脚本,但是.NET Framework最受欢迎的选择可能是 NAnt。您可能会发现自己需要使用构建管理系统来创建配置文件。为了使这些工作更轻松,Nini项目提供了NiniEdit(Nini命令行配置编辑器)。使用此应用程序,您可以创建和编辑任何基于文件的配置数据。NiniEditor包含在Examples目录中的每个Nini版本中。
让我们添加一个示例,说明如何在构建中使用NiniEdit。在第一个示例中,假设您的构建是一个批处理文件,并且您需要以编程方式创建以下INI文件:
[General]
Debug = false
Logging = On
[Logging]
FilePath = C:\temp\MyApp.log
以下调用将自动创建配置文件:
:: Create the new configuration file
niniedit --new --set-type=ini MyApp.ini
niniedit --add=General MyApp.ini
niniedit --add=Logging MyApp.ini
niniedit --config=General --set-key=Debug,false MyApp.ini
niniedit --config=General --set-key=Logging,On MyApp.ini
niniedit --config=Logging --set-key=FilePath,C:\temp\MyApp.log MyApp.ini
如果您在NAnt中执行相同的操作,则可以执行以下操作:
<exec program="niniedit" commandline="-n -s INI MyApp.ini" />
<exec program="niniedit" commandline="-a General MyApp.ini" />
<exec program="niniedit" commandline="-a Logging MyApp.ini" />
<exec program="niniedit" commandline="-c General -k Debug,false MyApp.ini" />
<exec program="niniedit" commandline="-c General -k Logging,On MyApp.ini" />
<exec program="niniedit" commandline="-c Logging -k FilePath,C:\temp\MyApp.log MyApp.ini" />
这里的所有都是它的。NiniEdit具有其他功能,例如列出配置,键,键值和删除键的功能。如果没有其他问题,请以NiniEdit为例,说明如何使用Nini编写自己的命令行应用程序。
有时,使用应用程序以编程方式创建配置文件可能会很有用。使用Nini进行此操作非常容易。
假设您要创建在任一示例中创建的相同INI文件:
[General]
Debug = false
Logging = On
[Logging]
FilePath = C:\temp\MyApp.log
在代码中创建代码的方法如下:
IniConfigSource source = new IniConfigSource();
IConfig config = source.AddConfig("General");
config.Set("Debug", "false");
config.Set("Logging", "On");
config = source.AddConfig("Logging");
config.Set("FilePath", "C:\\temp\\MyApp.log");
source.Save("MyApp.ini");
Nini的编写旨在使所有配置文件类型都成为一流公民。这是因为每种配置文件类型都有其自身的优点和缺点。下面的列表包含一些基本准则:
INI
XML
.NET配置文件
Windows注册表
本教程就是这样。希望对您有所帮助!如果您有任何关于改进本手册的问题或建议,请访问Nini主页,并使用论坛,错误跟踪器或功能请求工具来表达自己的意见。
如果在一个的javascript代码块中定义 函数fun(),而在该代码块的下一个代码块中应用该函数,则成功;而在该代码块的上一个代码块中应用该函数,则失败。如: fun();//出错,找不到该函数 var fun= function() { alert(666); }
自动发帖对于有大量的转发情况时是很好玩的一件事情,本文的目的就是通过通用正文抽取的办法,把外文网站中相关的文章通过翻译后自动转发到国内网站。 请朋友们以学习的角度来使用此代码,不要给网站本身带来麻烦!!
<?phpnamespace App\Service;use Illuminate\Support\Facades\Redis;class RedisLockService{ public static function lock($key, $expire = 10) { if(!$key) { return false; } do { if($acquired = (
Flutter系列 - 引入本地图1. 大致文件结构├── image│ ├── myIcon.png│ └── myIcon2.png├── lib└── pubspec.yaml2. 步骤在flutter中引入本地图片, 我们先在项目根目录建立一个images文件夹, 把本地图片资源拖进去在pubspec.yaml中配置, 特别注意, 一定要注意缩进, 否则无法读取图片路径flutter: uses-material-design: true assets:
PCI 总线架构主要被分成三部分: 1.PCI 设备。 符合 PCI 总线标准的设备就被称为 PCI 设备,PCI 总线架构中可以包含多个 PCI 设备。Audio 、LAN 都是一个 PCI 设备。PCI 设备同时也分为主设备和目标设备两种,主设备是一次访问操作的发起者,而目标设备则是被访问者。2.PCI 总线。 PCI 总线在系统中可以有多条,类似于树状结构进行扩展,每条 P
SSM实战之商品信息管理系统《一》1.前言本系统属于SSM的常用功能整合使用练习。 涉及到SSM框架整合+前端框Bootstrap+Ajax校验+登录拦截器+图片文件上传+日期类型转换器+json格式传参等常用功能的使用。使用技术: spring4.0 springmvc4.0.2 mybatis3.2.7 bootstrap3 Ajax Jquery 拦截器 文件上...
问题最近在使用Word时, 发现右下角弹广告, 一阵排查, 最后确认是Office助手搞的鬼.处理完后有点纳闷, 按理来说弹窗会被火绒主动拦截才对, 去任务栏一看, 弹窗拦截没启动.于是又去排查自动启动的问题, 如文章头图所示, 点了没反应.排查这里点名表扬下火绒的技术团队, 出现问题后, 我去火绒社区发了咨询帖, 10分钟内便有管理员回复, 半小时内联系上技术团队进行问题排查.版本升级应该不是问题根本原因首先, 技术专员询问我是否可以升级后, 我同意了升级....
输入命令后报错:[[email protected] mysql]# bin/mysqld_safe --user=mysql &[1] 15325[[email protected] mysql]# 091217 22:22:53 mysqld_safe Logging to '/var/lib/mysql/dev1.sccl.cn.err'.091217 22:22:53 mysqld_safe Starti
tomcat8 优化tomcat可以说是比较常用的了,所以tomcat优化在生产环境也是比较重要的。对于tomcat优化,主要从2个方面,一是tomcat自身的配置,另外一个就是利用jvm虚拟机的调优。随便找个web项目(不想找的可以私信或者评论找我要我测试的),打成war包丢到tomcat ROOT下,去mysql官网找点测试数据。保证请求访问能成功。然后利用 Jmeter 做压力测试。先...
如果管理多个esxi服务器没有,装一个vcenter吧,可以集中管理,多台服务器之间还可以做双机热备等功能,很好用。至于注册序列号,你漫天都是,你可以把分数拉高一点,我送给你一个。哈哈如何给esxi搭建ntp服务器提在ESX/ESXi主机上vSphere Client启络时间协NTP)的步骤。经验:jingyan.baidu.com使用vSphereClient连接到ESX/ESXi主机在清单...
1,要想调用摄像头首先要打开摄像头驱动,如果用户允许则可以使用。2,定义WebCamTexture的变量用于捕获单张照片。3,连续捕获须启用线程。4.建个空文件夹用于储存捕获到的照片源码展示: using UnityEngine;using System.Collections;using System.IO;using System.Runtime.Seriali...
1、什么是完全二叉树对于一颗具有N个节点的二叉树按层序编号,如果编号I的节点与同样深度的满二叉树中编号为I的节点在二叉树中位置完全相同,则这棵树被称为完全二叉树。另一种定义:完全二叉树是由满二叉树而引出来的, 若设二叉树的深度为h,除第 h 层外, 其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。2、不是二叉树的情况:1)在二叉树中有右孩子没有却左孩子,则一定不是完全二叉树。如下图:2)一个节点有左孩子没