나는 한동안 WebService를 작성해 왔으며 WebService의 작동 원리에 대해 수집하고 이해한 내용을 요약하겠습니다.
WebService는 주로 응용 프로그램 계층 프로토콜인 Http 프로토콜을 사용합니다. Tcp/Ip: ( 참고: 현재 WebService 개발의 대부분은 이미 소켓 실시간 통신을 매우 잘 지원할 수 있습니다. 그러나 http는 여전히 핵심입니다.)
Http는 "요청----응답"을 채택합니다. mode;
Http 통신은 XML 직렬화 통신을 통해...
Http 통신 프로세스: .asmx 핸들 호출, XML, XSD, SOAP 및 WSDL 처리,
있습니다. XML에서 제공되는 세 가지 주요 측면: (다음 기사 인용: http://dev.csdn.net/article/19/19185.shtm)
개인적으로 마스터해야 할 주요 사항은 다음과 같습니다. SOAP 요청 메시지 및 응답 메시지의 xml 형식...
메시지 디스패치
HTTP 파이프라인에서 .asmx 핸들이 호출되면 어떤 .NET 클래스가 확인되는지 확인하여 확인하세요. .asmx 파일의 WebService 선언에서. 그런 다음 들어오는 HTTP 메시지의 정보를 관찰하고 참조된 클래스에서 호출할 메서드를 결정합니다. 이전 예에서 Add 메소드를 호출하려면 HTTP 요청 메시지가 다음과 같아야 합니다.
위 HTTP 요청 메시지에는 두 가지 정보가 있습니다. 호출 클래스를 결정하는 데 사용할 수 있습니다. 어떤 메소드: SOAPAction 헤더 또는 SOAP 본문에 있는 요청 요소의 이름입니다. 이 예에서 각 메서드는 보낸 사람이 호출하려는 메서드의 이름을 나타냅니다.
.asmx 핸들은 SOAPAction 헤더의 값을 사용하여 메시지 발송을 구현합니다. 따라서 .asmx 핸들은 메시지의 SOAPAction 헤더를 보고 .NET 매핑을 사용하여 참조된 클래스의 메서드를 확인합니다. [WebMethod] 특성으로 표시된 메서드만 고려하지만 각 메서드의 SOAPAction 값을 확인하여 호출할 메서드를 구체적으로 결정합니다. 클래스에서 SOAPAction 값을 명시적으로 지정하지 않았기 때문에 .asmx 핸들은 SOAPAction 값이 웹 서비스의 네임스페이스에 메서드 이름을 더한 것이라고 가정합니다. 그리고 네임스페이스를 지정하지 않았으므로 핸들러의 기본값은 http://tempuri.org입니다. 이런 방식으로 Add 메서드의 기본 SOAPAction 값은 http://tempuri.org/Add입니다.
다음과 같이 웹 서비스의 네임스페이스를 사용자 정의할 수 있습니다. 클래스를 [WebService] 특성으로 표시하고 WebMethods를 [SoapDocumentMethod] 특성으로 표시하여 특정 SOAPAction 값을 지정합니다. 예는 다음과 같습니다.
using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace="http://example.org/math")] public class MathService { [WebMethod] public double Add(double x, double y) { return x + y; } [WebMethod] [SoapDocumentMethod(Action="urn:math:subtract")] public double Subtract(double x, double y) { return x - y; } ... }
이제 .asmx 핸들은 Add 메서드의 SOAPAction 값이 http://example.org/math/Add이고 SubTract 메서드의 SOAPAction 값이 다음과 같다고 생각합니다. urn:math:subtract (클래스에 명확하게 정의되어 있기 때문입니다). 예를 들어, 다음 HTTP 요청 메시지는 Subtract를 호출합니다.
.asmx 핸들이 HTTP 요청 메시지에 대한 SOAPAction 일치를 찾지 못하면 예외가 발생합니다. SOAPAction 헤더를 사용하여 메시지를 전달하지 않으려면 .asmx 핸들에 요청 요소 이름을 사용하도록 지시할 수 있습니다. 이 접근 방식을 사용하려면 [SoapDocumentService] 속성의 RoutingStyle 속성을 사용하여 클래스를 표시해야 합니다. 또한 WebMethod에는 SOAPAction 값이 필요하지 않습니다(클래스에서 해당 값을 비어 있음으로 설정). 아래와 같이:
using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace="http://example.org/math")] [SoapDocumentService( RoutingStyle=SoapServiceRoutingStyle.RequestElement)] public class MathService { [WebMethod] [SoapDocumentMethod(Action="")] public double Add(double x, double y) { return x + y; } [WebMethod] [SoapDocumentMethod(Action="")] public double Subtract(double x, double y) { return x - y; } ... }
이 경우 핸들러는 SOAPAction의 값에도 신경 쓰지 않고 요청 요소의 이름을 사용하여 호출 방법을 결정합니다. 예를 들어 다음 HTTP 요청 메시지에서는 Add 메서드를 호출하는 요청 요소의 이름이 Add가 되기를 바랍니다.
따라서 .asmx 핸들이 HTTP 메시지를 수신하면 가장 먼저 하는 일은 다음과 같습니다. 해당 WebMethod에 메시지를 디스패치하는 방법을 결정합니다. 실제로 메서드를 호출하려면 먼저 들어오는 XML을 .NET 개체에 매핑해야 합니다.
XML을 개체에 매핑
WebMethod 핸들이 호출할 메서드를 결정하고 나면 XML 메시지를 .NET 개체로 역직렬화합니다. 메시지가 전달되면 핸들러는 리플렉션을 통해 클래스를 확인한 다음 XML 메시지를 처리하는 방법을 결정합니다. XmlSerializer 클래스는 System.Xml.Serialization 네임스페이스의 클래스에 대한 XML 매핑을 자동으로 완료합니다.
XmlSerializer는 모든 .NET 공개 유형을 XML 스키마 유형에 매핑할 수 있으며, 이 적절한 매핑을 통해 .NET 개체를 XML 인스턴스 문서에 자동으로 매핑할 수 있습니다(그림 4 참조). XmlSerializer는 XML 스키마에서 지원하는 기능에 의해 제한됩니다. 비록 모든 복잡한 최신 개체 모델(예: 트리가 아닌 개체 그래프)을 처리할 수는 없지만 개발자가 일반적으로 사용하는 복잡한 형식은 처리할 수 있습니다.
이전 Add 예제를 보면 XmlSerializer는 x 및 y 요소를 .NET double 값(Add 메서드 호출 시 제공해야 함)에 매핑합니다. Add 메서드는 SOAP 응답 메시지의 XML 요소로 직렬화되어야 하는 double 형식 값을 호출자에게 반환합니다.
그림 4. XML을 개체에 매핑
XmlSerializer也能自动处理一些复杂类型(除了上面说到的一些限制)。比如,下面的WebMethod计算两个点结构之间的距离。
using System; using System.Web.Services; public class Point { public double x; public double y; } [WebService(Namespace="urn:geometry")] public class Geometry { [WebMethod] public double Distance(Point orig, Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } }
请求此操作的SOAP消息将包含一个Distance元素,它包含了两个子元素,一个称作orig,另一个是dest,每一个都包括了x和y元素,如下所示:
这种情况下SOAP应答消息将包含一个DistanceResponse元素,它包含一个double 类型的DistanceResult子元素。
缺省的XML映射使用方法名作为请求元素名,参数名作为子元素名。每个参数的结构依赖于类型的结构。公共字段和属性的名字简单映射为子元素,如Point类中的x和y。应答元素的名字缺省为请求元素的名字后面附加上“Response”,应答元素也包含一个子元素,是请求元素名字后面附加“Result”。也有可能使用一些固定的映射属性来打破标准的XML映射。比如,你可以使用[XmlType]属性来定制类型的名字和名称空间,使用[XmlElement]和[XmlAttribute]属性来控制如何将参数或类成员分别映射为元素或属性,也可以使用[SoapDocumentMethod]属性控制怎样把方法本身映射为请求/响应消息中的元素名。比如,检查下面重新定义的Distance。
using System; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml.Serialization; public class Point { [XmlAttribute] public double x; [XmlAttribute] public double y; } [WebService(Namespace="urn:geometry")] public class Geometry { [WebMethod] [SoapDocumentMethod(RequestElementName="CalcDistance", ResponseElementName="CalculatedDistance")] [return: XmlElement("result")] public double Distance( [XmlElement("o")]Point orig, [XmlElement("d")]Point dest) { return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) + Math.Pow(orig.y-dest.y, 2)); } }
它所期望的SOAP请求消息如下:
.asmx句柄使用SOAP document/literal风格来实现和描述上面显示的默认映射。意思上说WSDL定义将包含literal XML schema定义,它描述了SOAP消息中用到的请求和响应元素。
.asmx句柄也能使用SOAP rpc/encoded风格。这意味着SOAP体中包含一个RPC调用的XML代表(representation),参数用SOAP编码规则来串行化。实现这些仅需将[SoapDocumentService] and [SoapDocumentMethod]替换为[SoapRpcService] and [SoapRpcMethod]属性。
正如你所看到的,我们可能完全定制一个从给定方法到SOAP消息的映射。XmlSerializer提供了一个强大的串行化引擎。
除了处理参数的反串行化,.asmx句柄也能串行化/反串行化SOAP头。SOAP头的处理不同于参数,因为它们被认为是典型的无法控制的信息,和具体的方法没有直接的联系。由于这些,头处理主要是通过中间层(interception layers),完全为WebMethods屏蔽了头处理。
然而如果想涉足于WebMethod中的头信息,你必须提供一个.NET类,从SoapHeader派生而来,它代表了头的XML schema类型。然后定义一个此类型的成员变量作为每一个头实例的占位符。最后标记每个要访问头的WebMethod,指定你想要到达的域名。
比如,下面的SOAP请求包括一个用来进行身份验证的UsernameToken头。
更多WebService 작동 원리相关文章请关注PHP中文网!