热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用消息约定MessageContractz

使用消息约定.NETFramework4在生成WindowsCommunicationFoundation(WCF)应用程序时,开发人员通常会密切关注数据结构和序列化

使用消息约定
.NET Framework 4

在生成 Windows Communication Foundation (WCF) 应用程序时,开发人员通常会密切关注数据结构和序列化问题,而不必关心携带数据的消息。对于这些应用程序,为参数或返回值创建数据协定的过程很简单。(有关更多信息,请参见 在服务协定中指定数据传输.)

但是,有时完全控制 SOAP 消息的结构与控制其内容一样重要。当必须提供互操作性或需要在消息或消息部分级别特别控制安全问题时,更是如此。在这些情况下,可以创建一个消息协定,以便对参数或返回值使用一种可直接序列化为所需精确 SOAP 消息的类型。

本主题讨论如何使用各种消息协定属性为操作创建特定消息协定。

在操作中使用消息协定

WCF 支持在远程过程调用 (RPC) 样式或消息样式上建模的操作。在 RPC 样式的操作中,可以使用任何可序列化的类型并可以使用本地调用可用的功能,如多个参数以及 refout 参数。在此样式中,所选的序列化形式控制基础消息中数据的结构,但 WCF 运行时本身会创建这些消息以支持操作。这使对 SOAP 和 SOAP 消息不熟悉的开发人员能够快速容易地创建和使用服务应用程序。

下面的代码示例演示在 RPC 样式上建模的服务操作。

C#
复制

[OperationContract]
public BankingTransactionResponse PostBankingTransaction(BankingTransaction bt);

通常,定义消息的架构时使用数据协定就足够了。例如在前面的示例中,如果 BankingTransactionBankingTransactionResponse 具有定义基础 SOAP 消息内容的数据协定,则对于大多数应用程序就足够了。有关数据协定的更多信息,请参见使用数据协定

但是,有时必须精确控制如何将类型映射到通过网络传输的 SOAP 消息。对于这种情况,最常见的方案是插入自定义 SOAP 标头。另一种常见方案是定义消息头和正文的安全属性,也就是说,确定是否对这些元素进行数字签名和加密。消息样式的操作可提供这种控制。

消息样式的操作最多具有一个参数和一个返回值,其中参数和返回值的类型都是消息类型;也就是说,这两种类型可直接序列化为指定的 SOAP 消息结构。这可以是用 MessageContractAttribute 标记的任何类型或 Message 类型。下面的代码示例演示类似于前面 RPC 样式的操作,但此操作使用消息样式。

例如,如果 BankingTransactionBankingTransactionResponse 都是具有消息协定的类型,则以下操作中的代码有效。

C#
复制

[OperationContract]
BankingTransactionResponse Process(BankingTransaction bt);
[OperationContract]
void Store(BankingTransaction bt);
[OperationContract]
BankingTransactionResponse GetResponse();

但下面的代码无效。

C#
复制

[OperationContract]
bool Validate(BankingTransaction bt);
// Invalid, the return type is not a message contract.
[OperationContract]
void Reconcile(BankingTransaction bt1, BankingTransaction bt2);
// Invalid, there is more than one parameter.

对于涉及消息协定类型且不符合有效模式之一的任何操作会引发异常。当然,不涉及消息协定类型的操作不受这些限制的约束。

如果一个类型既有消息协定又有数据协定,则在操作中使用此类型时只考虑其消息协定。

定义消息协定

若要为某一类型定义消息协定(即定义该类型和 SOAP 信封之间的映射),请对该类型应用 MessageContractAttribute。然后对该类型中要成为 SOAP 标头的成员应用 MessageHeaderAttribute,并对要成为消息的 SOAP 正文部分的成员应用 MessageBodyMemberAttribute

下面的代码提供了一个使用消息协定的示例。

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader] public Operation operation;[MessageHeader] public DateTime transactionDate;[MessageBodyMember] private Account sourceAccount;[MessageBodyMember] private Account targetAccount;[MessageBodyMember] public int amount;
}

当使用此类型作为操作参数时,会生成一个具有额外标头(名为 operationtransactionDate)的 SOAP 信封,这些标头中包含 operationtransactionDate 字段的内容。SOAP 正文由一个包装元素构成,该包装元素包含类型为 Account 数据协定类型的 sourceAccount and targetAccount 元素和类型为整数类型的 amount 元素。

可以对所有字段、属性和事件应用 MessageHeaderAttributeMessageBodyMemberAttribute,而不管这些字段、属性和事件是公用的、私有的、受保护的还是内部的。

ms730255.note(zh-cn,VS.100).gif注意:
消息协定中会忽略 KnownTypeAttribute 属性。如果需要 KnownTypeAttribute,可以将其放在使用所述消息协定的操作上。

在消息协定内部使用自定义类型

每个单独的消息头和消息正文部分均使用为消息所使用的服务协定选择的序列化引擎进行序列化(转换为 XML)。默认序列化引擎 XmlFormatter 可以显式处理(通过具有 System.Runtime.Serialization.DataContractAttribute)或隐式处理(通过作为基元类型而具有 System.SerializableAttribute 等)具有数据协定的任何类型。有关更多信息,请参见 使用数据协定.

在前面的示例中,OperationBankingTransactionData 类型必须具有数据约,定且 transactionDate 可序列化,因为 DateTime 是基元类型(因此具有隐式数据协定)。

不过,也可以切换到另一个序列化引擎 XmlSerializer。如果进行切换,应确保用于消息头和正文部分的所有类型都可以使用 XmlSerializer 进行序列化。

在消息协定内部使用数组

可以采用两种方式在消息协定中使用重复元素的数组。

第一种方式是直接在数组上使用 MessageHeaderAttributeMessageBodyMemberAttribute。在这种情况下,整个数组序列化为一个具有多个子元素的元素(即一个标头或一个正文部分)。考虑下面示例中的类。

C#
复制

[MessageContract]
public class BankingDepositLog
{[MessageHeader] public int numRecords[MessageHeader] public DepositRecord records[];[MessageHeader] public int branchID;
}

这会使 SOAP 标头类似于下面所示。

other
复制


3
Record1Record2Record3

20643

另一种方式是使用 MessageHeaderArrayAttribute。在这种情况下,每个数组元素都单独序列化,从而使每个数组元素都具有一个标头,类似于下面所示。

other
复制

3
Record1
Record2
Record3
20643

数组项的默认名称是对其应用 MessageHeaderArrayAttribute 属性的成员的名称。

MessageHeaderArrayAttribute 属性继承自 MessageHeaderAttribute。它具有与非数组属性相同的一组功能,例如,可以像设置单一标头的顺序、名称和命名空间那样设置标头数组的顺序、名称和命名空间。在对数组使用 Order 属性时,该属性将应用于整个数组。

可以将 MessageHeaderArrayAttribute 只应用于数组,而不应用于集合。

在消息协定中使用字节数组

与非数组属性(MessageBodyMemberAttributeMessageHeaderAttribute)一起使用时,字节数组不被视为数组,而被视为一种特殊的基元类型,在生成的 XML 中表示为 Base64 编码的数据。

在将字节数组与数组属性 MessageHeaderArrayAttribute 一起使用时,结果取决于正在使用的序列化程序。如果使用默认序列化程序,会将数组表示为每个字节一个单独项。但如果选择 XmlSerializer(在服务协定上使用 XmlSerializerFormatAttribute),则会将字节数组视为 Base64 数据,而不管是使用数组属性还是非数组属性。

对消息部分进行签名和加密

消息协定可以指示消息头和/或正文是否应进行数字签名和加密。

这可以通过在 MessageHeaderAttributeMessageBodyMemberAttribute 特性上设置 System.ServiceModel.MessageContractMemberAttribute.ProtectionLevel 属性来完成。该属性是 System.Net.Security.ProtectionLevel 类型的枚举,可以设置为 None(不加密或签名)、Sign(仅数字签名)或 EncryptAndSign(加密并数字签名)。默认值为 EncryptAndSign

若要让这些安全功能起作用,必须正确配置绑定和行为。如果在没有正确配置的情况下使用这些安全功能(例如,在不提供凭据的情况下试图对消息进行签名),则会在验证时引发异常。

对于消息头,会分别为每个消息头确定其保护级别。

对于消息正文部分,保护级别可理解为“最低保护级别”。无论包含几个正文部分,正文都只有一个保护级别。正文的保护级别由所有正文部分的最高 ProtectionLevel 属性设置确定。不过,您应该将每个正文部分的保护级别设置为实际要求的最低保护级别。

考虑下面代码示例中的类。

C#
复制

[MessageContract]
public class PatientRecord
{[MessageHeader(ProtectionLevel=None)] public int recordID;[MessageHeader(ProtectionLevel=Sign)] public string patientName;[MessageHeader(ProtectionLevel=EncryptAndSign)] public string SSN;[MessageBodyMember(ProtectionLevel=None)] public string comments;[MessageBodyMember(ProtectionLevel=Sign)] public string diagnosis;[MessageBodyMember(ProtectionLevel=EncryptAndSign)] public string medicalHistory;
}

在此示例中,recordID 标头未受保护,patientNamesigned,SSN 进行了加密和签名。至少有一个正文部分 medicalHistory 已应用 EncryptAndSign,因此将对整个消息正文进行加密和签名,即使 comments 和 diagnosis 正文部分指定了较低的保护级别。

控制标头和正文部分的名称和命名空间

在消息协定的 SOAP 表示形式中,每个标头和正文部分都映射为一个具有名称和命名空间的 XML 元素。

默认情况下,命名空间与消息加入的服务协定的命名空间相同,名称由应用 MessageHeaderAttributeMessageBodyMemberAttribute 属性的成员名称确定。

通过操作 System.ServiceModel.MessageContractMemberAttribute.NameSystem.ServiceModel.MessageContractMemberAttribute.Namespace(在 MessageHeaderAttributeMessageBodyMemberAttribute 特性的父类上)可以更改这些默认值。

考虑下面代码示例中的类。

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader] public Operation operation;[MessageHeader(Namespace="http://schemas.contoso.com/auditing/2005")] public bool IsAudited;[MessageBodyMember(Name="transactionData")] public BankingTransactionData theData;
}

在此示例中,IsAudited 标头位于代码中指定的命名空间中,表示 theData 成员的正文部分由名为 transactionData 的 XML 元素表示。

控制是否包装 SOAP 正文部分

默认情况下,SOAP 正文部分会在包装元素内部进行序列化。例如,下面的代码演示从 HelloGreetingMessage 消息的消息协定中的 MessageContractAttribute 类型的名称生成的 HelloGreetingMessage 包装元素。

C#
VB
复制

[MessageContract]
public class HelloGreetingMessage
{private string localGreeting;[MessageBodyMember(Name = "Salutations", Namespace = "http://www.examples.com")]public string Greeting{get { return localGreeting; }set { localGreeting = value; }}
}/*The following is the request message, edited for clarity.http://GreetingMessage/Action Hello.*/

若要取消包装元素,请将 IsWrapped 属性设置为 false。若要控制包装元素的名称和命名空间,请使用 WrapperNameWrapperNamespace 属性。

ms730255.note(zh-cn,VS.100).gif注意:
消息中具有多个未包装的消息正文部分不符合 WS-I 基本配置文件 1.1 的规定,在设计新消息协定时不建议这样做。但是,在某些特定的互操作性方案中,必需要具有多个未包装的消息正文部分。如果要在消息正文中传输多段数据,则建议使用默认(包装)模式。未包装的消息中具有多个消息头是完全可以的。

SOAP 操作

SOAP 和相关 Web 服务标准定义了一个名为 Action 的属性,该属性可用于发送的每个 SOAP 消息。操作的 System.ServiceModel.OperationContractAttribute.ActionSystem.ServiceModel.OperationContractAttribute.ReplyAction 属性控制此属性的值。

SOAP 标头属性

SOAP 标准定义了下列可存在于标头上的属性:

  • Actor/Role(在 SOAP 1.1 中为 Actor,在 SOAP 1.2 中为 Role)

  • MustUnderstand

  • Relay

ActorRole 属性指定要使用给定标头的节点的统一资源标识符 (URI)。MustUnderstand 属性指定处理标头的节点是否必须理解该标头。Relay 属性指定要将标头中继到下游节点。WCF 不会对传入消息的这些属性执行任何处理,但 MustUnderstand 属性除外,该属性将在本主题后面的“消息协定版本管理”部分中说明。但它允许您根据需要读取和写入这些属性,如下所述。

发送消息时,默认情况下不会发出这些属性。您可以采取两种方式更改这一行为。第一种方式是通过更改 System.ServiceModel.MessageHeaderAttribute.ActorSystem.ServiceModel.MessageHeaderAttribute.MustUnderstandSystem.ServiceModel.MessageHeaderAttribute.Relay 属性,以静态方式将这些特性设置为任何需要的值,如下面的代码示例所示。(请注意,没有 Role 属性;如果使用 SOAP 1.2,则设置 Actor 属性会发出 Role 特性)。

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader(Actor="http://auditingservice.contoso.com", MustUnderstand=true)] public bool IsAudited;[MessageHeader] public Operation operation;[MessageBodyMember] public BankingTransactionData theData;
}

第二种方式是通过代码以动态方式控制这些属性。为此,您可以将所需的标头包装在 MessageHeader 类型中(切勿将此类型与非泛型版本混淆),并与 MessageHeaderAttribute 一起使用该类型。然后,可以在 MessageHeader 上使用属性来设置 SOAP 特性,如下面的代码示例所示。

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader] public MessageHeader<bool> IsAudited;[MessageHeader] public Operation operation;[MessageBodyMember] public BankingTransactionData theData;
}
// application code:
BankingTransaction bt &#61; new BankingTransaction();
bt.IsAudited &#61; new MessageHeader<bool>();
bt.IsAudited.Content &#61; false; // Set IsAudited header value to "false"
bt.IsAudited.Actor&#61;"http://auditingservice.contoso.com";
bt.IsAudited.MustUnderstand&#61;true;

如果同时使用动态和静态控制机制&#xff0c;则静态设置用作默认设置&#xff0c;但可以在以后使用动态机制重写&#xff0c;如下面的代码所示。

other
复制

[C#]
[MessageHeader(MustUnderstand&#61;true)] public MessageHeader documentApprover;
// later on in the code:
BankingTransaction bt &#61; new BankingTransaction();
bt.documentApprover &#61; new MessageHeader();
bt.documentApprover.MustUnderstand &#61; false; // override the static default of &#39;true&#39;

允许创建具有动态属性控制的重复标头&#xff0c;如下面的代码所示。

C#
复制

[MessageHeaderArray] public MessageHeader documentApprovers[];

在接收端&#xff0c;仅当对类型中的标头使用 MessageHeader 类时才能读取这些 SOAP 属性。请检查 MessageHeader 类型的标头的 ActorRelayMustUnderstand 属性 (Property) 以发现所接收消息的属性 (Attribute) 设置。

当接收到消息然后发回该消息时&#xff0c;SOAP 属性设置仅对 MessageHeader 类型的标头往返一次。

SOAP 正文部分的顺序

在某些情况下&#xff0c;可能需要控制正文部分的顺序。默认情况下&#xff0c;正文元素采用字母顺序&#xff0c;但可以通过 System.ServiceModel.MessageBodyMemberAttribute.Order 属性进行控制。此属性具有与 System.Runtime.Serialization.DataMemberAttribute.Order 属性相同的语义&#xff0c;但在继承方案中的行为除外&#xff08;在消息协定中&#xff0c;基类型正文成员不排列在派生类型正文成员之前&#xff09;。有关更多信息&#xff0c;请参见 数据成员顺序.

在下面的示例中&#xff0c;amount 通常排在第一位&#xff0c;因为按字母顺序它排在第一位。但 Order 属性将它放在了第三位。

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader] public Operation operation;[MessageBodyMember(Order&#61;1)] public Account sourceAccount;[MessageBodyMember(Order&#61;2)] public Account targetAccount;[MessageBodyMember(Order&#61;3)] public int amount;
}

消息协定版本管理

有时&#xff0c;您可能需要更改消息协定。例如&#xff0c;应用程序的新版本可能会向消息中添加额外的标头。在从新版本应用程序向旧版本应用程序发送消息时&#xff0c;系统必须处理额外的标头&#xff1b;同样&#xff0c;反方向操作时系统必须处理缺少的标头。

下面的规则适用于标头的版本管理&#xff1a;

  • WCF 不反对缺少标头&#xff0c;相应的成员将保留其默认值。

  • WCF 还忽略意外的额外标头。此规则的一种例外情况是在传入的 SOAP 消息中&#xff0c;额外标头的 MustUnderstand 属性设置为 true。在这种情况下&#xff0c;由于存在一个无法处理但必须理解的标头&#xff0c;因此会引发异常。

消息正文具有类似的版本管理规则&#xff0c;即忽略缺少和附加的消息正文部分。

继承注意事项

消息协定类型可以继承自另一个类型&#xff0c;前提是基类型也具有消息协定。

在使用继承自其他消息协定类型的消息协定类型创建或访问消息时&#xff0c;下面的规则适用&#xff1a;

  • 继承层次结构中的所有消息头集合在一起构成消息头的完整集合。

  • 继承层次结构中的所有消息正文部分集合在一起构成消息正文的完整集合。正文部分按照通常排序规则排列&#xff08;按 System.ServiceModel.MessageBodyMemberAttribute.Order 属性&#xff0c;然后按字母顺序排序&#xff09;&#xff0c;与它们在继承层次结构中的位置无关。在使用消息协定继承时&#xff0c;强烈建议消息正文部分不要出现在继承树的多个级别上。如果基类和派生类用相同的名称定义标头或正文部分&#xff0c;则使用最基础的类中的成员来存储该标头或正文部分的值。

考虑下面代码示例中的类。

C#
复制

[MessageContract]
public class PersonRecord
{[MessageHeader(Name&#61;"ID")] public int personID;[MessageBodyMember] public string patientName;
}[MessageContract]
public class PatientRecord : PersonRecord
{[MessageHeader(Name&#61;"ID")] public int patientID;[MessageBodyMember] public string diagnosis;
}

PatientRecord 类描述了一个消息&#xff0c;该消息具有一个名为 ID 的标头。该标头对应于 personID 而不对应于 patientID 成员&#xff0c;因为选择了最基础的成员。因此&#xff0c;在这种情况下&#xff0c;patientID 字段无用。消息正文包含 diagnosis 元素&#xff0c;后面跟随 patientName 元素&#xff0c;因为这是这些元素的字母顺序。表注意&#xff0c;该示例演示了一种强烈建议不要使用的模式&#xff1a;基消息协定和派生消息协定都具有消息正文部分。

WSDL 注意事项

在从使用消息协定的服务生成 Web 服务描述语言 (WSDL) 协定时&#xff0c;必须记住生成的 WSDL 中并不会反映所有的消息协定功能。请考虑以下几点&#xff1a;

  • WSDL 无法表示标头数组的概念。使用 MessageHeaderArrayAttribute 创建具有标头数组的消息时&#xff0c;生成的 WSDL 只反映一个标头而不是该数组。

  • 生成的 WSDL 文档可能不反映某些保护级别信息。

  • 在 WSDL 中生成的消息类型的名称与消息协定类型的类名称相同。

  • 在多个操作中使用同一个消息协定时&#xff0c;会在 WSDL 文档中生成多个消息类型。对于后续使用&#xff0c;会在名称中添加数字“2”、“3”等以使名称唯一。在导回 WSDL 时&#xff0c;会创建多个消息协定类型&#xff0c;除了名称不同外&#xff0c;这些消息协定类型完全相同。

SOAP 编码注意事项

WCF 允许但不推荐使用 XML 的旧式 SOAP 编码样式。使用这种样式时&#xff08;在应用于服务协定的 System.ServiceModel.XmlSerializerFormatAttribute 上将 Use 属性设置为 Encoded&#xff09;&#xff0c;下面的附加注意事项适用&#xff1a;

  • 不支持消息头&#xff1b;这意味着属性 MessageHeaderAttribute 和数组属性 MessageHeaderArrayAttribute 与 SOAP 编码不兼容。

  • 如果未包装消息协定&#xff0c;即如果属性 IsWrapped 设置为 false&#xff0c;则消息协定只能具有一个正文部分。

  • 请求消息协定的包装元素的名称必须与操作名称匹配。为此请使用消息协定的 WrapperName 属性。

  • 响应消息协定的包装元素的名称必须与具有“Response”后缀的操作名称相同。为此请使用消息协定的 WrapperName 属性。

  • SOAP 编码保留对象引用。例如&#xff0c;请考虑下面的代码。

    C#
    复制

    [MessageContract(WrapperName&#61;"updateChangeRecord")]
    public class ChangeRecordRequest
    {[MessageBodyMember] Person changedBy;[MessageBodyMember] Person changedFrom;[MessageBodyMember] Person changedTo;
    }[MessageContract(WrapperName&#61;"updateChangeRecordResponse")]
    public class ChangeRecordResponse
    {[MessageBodyMember] Person changedBy;[MessageBodyMember] Person changedFrom;[MessageBodyMember] Person changedTo;
    }// application code:
    ChangeRecordRequest cr &#61; new ChangeRecordRequest();
    Person p &#61; new Person("John Doe");
    cr.changedBy&#61;p;
    cr.changedFrom&#61;p;
    cr.changedTo&#61;p;

使用 SOAP 编码序列化消息后&#xff0c;changedFromchangedTo 不包含其自己的 p 副本&#xff0c;而是指向 changedBy 元素内的副本。

性能注意事项

每个消息头和消息正文部分相互独立地进行序列化。因此&#xff0c;可以为每个标头和正文部分重新声明相同的命名空间。为了提高性能&#xff0c;特别是对于消息在网络上的大小&#xff0c;请将多个标头和正文部分合并成一个标头或正文部分。例如&#xff0c;不要使用下面代码&#xff1a;

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader] public Operation operation;[MessageBodyMember] public Account sourceAccount;[MessageBodyMember] public Account targetAccount;[MessageBodyMember] public int amount;
}

请使用此代码。

C#
复制

[MessageContract]
public class BankingTransaction
{[MessageHeader] public Operation operation;[MessageBodyMember] public OperationDetails details;
}[DataContract]
public class OperationDetails
{[DataMember] public Account sourceAccount;[DataMember] public Account targetAccount;[DataMember] public int amount;
}

基于事件的异步协定和消息协定

基于事件的异步模型设计准则规定&#xff0c;如果返回了多个值&#xff0c;则一个值会作为 Result 属性返回&#xff0c;其他值会作为 EventArgs 对象上的属性返回。因此产生的结果之一是&#xff0c;如果客户端使用基于事件的异步命令选项导入元数据&#xff0c;且该操作返回多个值&#xff0c;则默认的 EventArgs 对象将返回一个值作为 Result 属性&#xff0c;返回的其余值是 EventArgs 对象的属性。

如果要将消息对象作为 Result 属性来接收并要使返回的值作为该对象上的属性&#xff0c;请使用 /messageContract 命令选项。这会生成一个签名&#xff0c;该签名会将响应消息作为 EventArgs 对象上的 Result 属性返回。然后&#xff0c;所有内部返回值就都是响应消息对象的属性了。

 


转:https://www.cnblogs.com/EasyLive2006/archive/2011/10/05/2199270.html



推荐阅读
  • 本文详细介绍了如何利用go-zero框架从需求分析到最终部署至Kubernetes的全过程,特别聚焦于微服务架构中的网关设计与实现。项目采用了go-zero及其生态组件,涵盖了从API设计到RPC调用,再到生产环境下的监控与维护等多方面内容。 ... [详细]
  • mybatis相关面试题 ... [详细]
  • 本文旨在探讨计算机机房的有效管理与维护方法,包括合理的机房布局设计、高效的操作系统安装与恢复技术以及数据保护措施。随着信息技术教育的发展,计算机机房作为教学的重要组成部分,其稳定性和安全性直接影响到教学质量。文章分析了当前机房管理中存在的问题,并提出了针对性的解决方案。 ... [详细]
  • 本文详细介绍了Python的multiprocessing模块,该模块不仅支持本地并发操作,还支持远程操作。通过使用multiprocessing模块,开发者可以利用多核处理器的优势,提高程序的执行效率。 ... [详细]
  • 深入解析 Zend Guard 4 功能与配置
    本文旨在通过图文并茂的方式详细介绍 Zend Guard 4 的核心功能及其配置方法,特别适合英文阅读能力有限的技术人员。文中不仅提供了详细的步骤说明,还附带了实际操作中的注意事项,帮助读者更好地理解和应用这一工具。 ... [详细]
  • 本文档提供了详细的MySQL安装步骤,包括解压安装文件、选择安装类型、配置MySQL服务以及设置管理员密码等关键环节,帮助用户顺利完成MySQL的安装。 ... [详细]
  • 本文详细探讨了在Python开发中遇到的ImportError: 无法找到名为Crypto.Cipher的模块的问题,并提供了多种解决方案,包括环境配置、库安装和代码调整等方法。 ... [详细]
  • 探讨如何利用Visual Basic (VB) 将十六进制或二进制字符串写入Windows注册表的方法。 ... [详细]
  • 2023年PHP处理请求超时的全面指南
    本文详细介绍了在PHP中处理请求超时的各种方法,包括设置脚本执行时间、处理file_get_contents函数超时以及优化AJAX请求等,适合开发者参考学习。 ... [详细]
  • Cortex-M3处理器核心解析
    本文详细介绍了Cortex-M3处理器的常见术语及其核心特点,包括其架构、寄存器组、操作模式、中断处理机制、存储器映射、总线接口和存储器保护单元(MPU)。此外,还探讨了Cortex-M3在性能和中断处理方面的优势。 ... [详细]
  • Web3隐私协议Manta Network与区块链互操作性平台Axelar达成战略合作,共同推进跨链资产的隐私保护。 ... [详细]
  • 提升接口测试效率的关键:用例与工具的综合应用
    本文将探讨如何通过有效的接口测试用例设计和工具选择,显著提高接口测试的效率和质量。 ... [详细]
  • 本文探讨了Flutter和Angular这两个流行框架的主要区别,包括它们的设计理念、适用场景及技术实现。 ... [详细]
  • PHP网站部署指南:从零开始搭建PHP网站
    本文提供了详细的步骤指导,帮助开发者在不同环境下成功部署PHP网站,包括在IIS和Apache服务器上的具体操作。 ... [详细]
  • 设计模式系列-原型模式
    一、上篇回顾上篇创建者模式中,我们主要讲述了创建者的几类实现方案,和创建者模式的应用的场景和特点,创建者模式适合创建复杂的对象,并且这些对象的每个组成部分的详细创建步骤可以是动态的变化的,但 ... [详细]
author-avatar
111
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有