热门标签 | 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



推荐阅读
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
  • 本文是关于C#类型系统、值类型和引用类型的概念性笔记。介绍了C#1系统类型的三个特性,静态类型的含义,显式类型和隐式类型的区别。还讨论了类、结构、数组类型、枚举、委托类型和接口类型属于哪一种类型。同时纠正了关于结构、引用类型和对象传递的错误表述。最后提到了C#4中使用动态类型的关键字。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • Unity3D引擎的体系结构和功能详解
    本文详细介绍了Unity3D引擎的体系结构和功能。Unity3D是一个屡获殊荣的工具,用于创建交互式3D应用程序。它由游戏引擎和编辑器组成,支持C#、Boo和JavaScript脚本编程。该引擎涵盖了声音、图形、物理和网络功能等主题。Unity编辑器具有多语言脚本编辑器和预制装配系统等特点。本文还介绍了Unity的许可证情况。Unity基本功能有限的免费,适用于PC、MAC和Web开发。其他平台或完整的功能集需要购买许可证。 ... [详细]
  • 项目需要将音视频文件上传服务器,考虑并发要求高,通过七牛来实现。直接上代码usingQiniu.IO;usingQiniu.IO.Resumable;usingQiniu.RPC; ... [详细]
  • java布尔字段用is前缀_POJO类中布尔类型的变量都不要加is前缀详解
    前言对应阿里巴巴开发手册第一章的命名风格的第八条。【强制】POJO类中布尔类型的变量都不要加is前缀,否则部分框架解析会引起序列化错误。反例:定义为基本 ... [详细]
  • SOA架构理解理解SOA架构,了解ESB概念,明白SOA与微服务的区别和联系,了解SOA与热门技术的结合与应用。1、面向服务的架构SOASOA(ServiceOrien ... [详细]
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社区 版权所有