Apache CXF với WSDL First
Ứng dụng CXF-POJO mà bạn đã phát triển dẫn đến sự kết hợp rất chặt chẽ giữa máy khách và máy chủ. Việc cấp quyền truy cập trực tiếp vào giao diện dịch vụ cũng có thể gây ra các mối đe dọa bảo mật nghiêm trọng. Vì vậy, việc tách giữa máy khách và máy chủ thường được mong muốn, điều này đạt được bằng cách sử dụng WSDL (Ngôn ngữ mô tả dịch vụ web).
Chúng tôi viết giao diện dịch vụ web trong tài liệu WSDL dựa trên XML. Chúng tôi sẽ sử dụng một công cụ để ánh xạ WSDL này sang các giao diện Apache CXF, sau đó được triển khai và sử dụng bởi các ứng dụng máy khách và máy chủ của chúng tôi. Để cung cấp khả năng tách, bắt đầu với WSDL là một cách ưu tiên. Đối với điều này, trước tiên bạn cần học một ngôn ngữ mới - WSDL. Viết WSDL cần một cách tiếp cận cẩn thận và sẽ tốt hơn nếu bạn có thể hiểu một số về điều này trước khi bắt đầu làm việc với nó.
Trong bài học này, chúng ta sẽ bắt đầu bằng cách xác định giao diện dịch vụ web trong tài liệu WSDL. Chúng ta sẽ học cách sử dụng CXF để tạo cả ứng dụng máy chủ và ứng dụng khách bắt đầu bằng WSDL. Chúng tôi sẽ giữ cho ứng dụng đơn giản để duy trì sự tập trung vào việc sử dụng CXF. Sau khi ứng dụng máy chủ được tạo, chúng tôi sẽ xuất bản nó lên một URL mong muốn bằng cách sử dụng lớp CXF được tích hợp sẵn.
Đầu tiên, hãy mô tả WSDL mà chúng tôi sẽ sử dụng.
WSDL cho HelloWorld
Dịch vụ web mà chúng tôi sẽ triển khai sẽ có một webmethod duy nhất được gọi là greetings chấp nhận một stringtham số giữ tên người dùng và trả về một thông điệp chuỗi cho người gọi sau khi thêm một thông điệp chào mừng vào tên người dùng. Wsdl hoàn chỉnh được hiển thị bên dưới:
//Hello.wsdl
<?xml version = "1.0" encoding = "UTF-8"?>
<wsdl:definitions xmlns:soap = "http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns = "http://helloworld.tutorialspoint.com/"
xmlns:wsdl = "http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
name = "HelloWorld"
targetNamespace = "http://helloworld.tutorialspoint.com/">
<wsdl:types>
<xsd:schema attributeFormDefault = "unqualified"
elementFormDefault = "qualified"
targetNamespace = "http://helloworld.tutorialspoint.com/">
<xsd:element name = "greetings" type = "tns:greetings"/>
<xsd:complexType name = "greetings">
<xsd:sequence>
<xsd:element minOccurs = "0" name = "arg0" type = "xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name = "greetingsResponse"
type = "tns:greetingsResponse"/>
<xsd:complexType name = "greetingsResponse">
<xsd:sequence>
<xsd:element minOccurs = "0" name = "return" type = "xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name = "greetings">
<wsdl:part element = "tns:greetings" name = "parameters"> </wsdl:part>
</wsdl:message>
<wsdl:message name = "greetingsResponse">
<wsdl:part element = "tns:greetingsResponse" name = "parameters"> </wsdl:part>
</wsdl:message>
<wsdl:portType name = "HelloWorldPortType">
<wsdl:operation name = "greetings">
<wsdl:input message = "tns:greetings" name = "greetings"> </wsdl:input>
<wsdl:output message = "tns:greetingsResponse" name = "greetingsResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name = "HelloWorldSoapBinding" type = "tns:HelloWorldPortType">
<soap:binding style = "document"
transport = "http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name = "greetings">
<soap:operation soapAction = "" style = "document"/>
<wsdl:input name = "greetings"></wsdl:input>
<wsdl:output name = "greetingsResponse">
<soap:body use = "literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name = "HelloWorldService">
<wsdl:port binding = "tns:HelloWorldSoapBinding" name = "HelloWorldPort">
<soap:address location = "http://localhost:9090/HelloServerPort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Lưu ý rằng viết một wsdl chính xác về mặt cú pháp luôn là một thách thức đối với các nhà phát triển; có rất nhiều công cụ và trình chỉnh sửa trực tuyến có sẵn để tạo wsdl. Các trình soạn thảo này yêu cầu tên của các thông báo mà bạn muốn triển khai cùng với các tham số mà bạn muốn chuyển trong một thông báo và loại thông báo trả lại mà bạn muốn ứng dụng khách của mình nhận được. Nếu bạn biết cú pháp wsdl, bạn có thể viết tay mã toàn bộ tài liệu hoặc sử dụng một trong các trình chỉnh sửa để tạo tài liệu của riêng bạn.
Trong wsdl ở trên, chúng tôi đã xác định một thông báo duy nhất được gọi là greetings. Tin nhắn được chuyển đến dịch vụ được gọi làHelloWorldService nó đang chạy ở http://localhost:9090/HelloServerPort.
Với điều này, bây giờ chúng ta sẽ tiến hành phát triển máy chủ. Trước khi phát triển máy chủ, chúng ta cần tạo giao diện Apache CXF cho dịch vụ web của mình. Điều này sẽ được thực hiện từ wsdl đã cho. Để làm điều này, bạn sử dụng một công cụ có tênwsdl2java.
Plugin wsdl2java
Vì chúng tôi sẽ sử dụng maven để xây dựng dự án, bạn sẽ cần thêm plugin sau vào pom.xml tập tin.
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/hello.wsdl</wsdl>
<faultSerialVersionUID> 1 </faultSerialVersionUID>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Lưu ý rằng chúng tôi chỉ định vị trí của wsdl nộp hồ sơ như src/main/resources/Hello.wsdl. Bạn sẽ phải đảm bảo rằng bạn tạo cấu trúc thư mục thích hợp cho dự án của mình và thêmhello.wsdl tập tin vào thư mục được chỉ định.
Các wsdl2javaplugin sẽ biên dịch wsdl này và tạo các lớp Apache CXF trong một thư mục được xác định trước. Cấu trúc dự án đầy đủ được hiển thị ở đây để bạn sẵn sàng tham khảo.
Bây giờ, bạn đã sẵn sàng tạo một máy chủ bằng cách sử dụng wsdl2javacác lớp được tạo. Các lớp mà wsdl2java đã tạo được hiển thị trong hình bên dưới:
Giao diện dịch vụ đã tạo
Trong danh sách các lớp được tạo, bạn phải nhận thấy một trong số chúng là giao diện Apache CXF - đây là HelloWorldPortType.java. Kiểm tra tệp này trong trình soạn thảo mã của bạn. Nội dung tệp được hiển thị ở đây để bạn sẵn sàng tham khảo -
//HelloWorldPortType.java
package com.tutorialspoint.helloworld;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by Apache CXF 3.3.0
* 2019-02-11T12:05:55.220+05:30
* Generated source version: 3.3.0
*
*/
@WebService(targetNamespace = "http://helloworld.tutorialspoint.com/",
name = "HelloWorldPortType")
@XmlSeeAlso({ObjectFactory.class})
public interface HelloWorldPortType {
@WebMethod
@RequestWrapper(localName = "greetings", targetNamespace =
"http://helloworld.tutorialspoint.com/", className =
"com.tutorialspoint.helloworld.Greetings")
@ResponseWrapper(localName = "greetingsResponse", targetNamespace =
"http://helloworld.tutorialspoint.com/", className =
"com.tutorialspoint.helloworld.GreetingsResponse")
@WebResult(name = "return", targetNamespace =
"http://helloworld.tutorialspoint.com/")
public java.lang.String greetings(
@WebParam(name = "arg0", targetNamespace =
"http://helloworld.tutorialspoint.com/")
java.lang.String arg0
);
}
Lưu ý rằng giao diện chứa một phương thức được gọi là greetings. Đây là một loại tin nhắn trong wsdl của chúng tôi. Cácwsdl2javacông cụ đã thêm phương thức này vào giao diện được tạo. Bây giờ, bạn có thể hiểu rằng bất kỳ thông báo nào bạn viết trong wsdl của mình, một phương thức tương ứng sẽ được tạo trong giao diện.
Bây giờ, nhiệm vụ của bạn sẽ là thực hiện tất cả các phương thức này tương ứng với các thông báo khác nhau mà bạn đã xác định trong wsdl của mình. Lưu ý rằng trong ví dụ trước về Apache CXF-First, chúng tôi đã bắt đầu với giao diện Apache CXF cho dịch vụ web của chúng tôi. Trong trường hợp này, giao diện Apache CXF được tạo từ wsdl.
Triển khai giao diện dịch vụ
Việc triển khai giao diện dịch vụ là không đáng kể. Việc triển khai đầy đủ được hiển thị trong danh sách bên dưới -
//HelloWorldImpl.java
package com.tutorialspoint.helloworld;
public class HelloWorldImpl implements HelloWorldPortType {
@Override
public String greetings(String name) {
return ("hi " + name);
}
}
Mã triển khai phương thức giao diện duy nhất được gọi là greetings. Phương thức nhận một tham số làstring gõ, thêm trước thông báo "hi" vào nó và trả về chuỗi kết quả cho người gọi.
Tiếp theo, chúng ta sẽ viết ứng dụng máy chủ.
Máy chủ đang phát triển
Việc phát triển ứng dụng máy chủ một lần nữa lại trở nên tầm thường. Ở đây, chúng tôi sẽ sử dụng CXF được cung cấpEndpointlớp để xuất bản dịch vụ của chúng tôi. Điều này được thực hiện trong hai dòng mã sau:
HelloWorldPortType implementor = new HelloWorldImpl();
Endpoint.publish("http://localhost:9090/HelloServerPort",
implementor,
new LoggingFeature());
Đầu tiên, chúng tôi tạo một đối tượng của lớp trình triển khai dịch vụ của chúng tôi - HelloWorldImpl. Sau đó, chúng tôi chuyển tham chiếu này làm tham số thứ hai chopublishphương pháp. Tham số đầu tiên là địa chỉ mà dịch vụ được xuất bản - khách hàng sẽ sử dụng URL này để truy cập dịch vụ. Toàn bộ nguồn cho ứng dụng máy chủ được cung cấp ở đây -
//Server.java
package com.tutorialspoint.helloworld;
import javax.xml.ws.Endpoint;
import org.apache.cxf.ext.logging.LoggingFeature;
public class Server {
public static void main(String[] args) throws Exception {
HelloWorldPortType implementor = new HelloWorldImpl();
Endpoint.publish("http://localhost:9090/HelloServerPort",
implementor,
new LoggingFeature());
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
Để xây dựng lớp máy chủ này, bạn sẽ cần thêm cấu hình xây dựng trong pom.xml. Điều này được hiển thị bên dưới -
<profile>
<id>server</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>
com.tutorialspoint.helloworld.Server
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</profile>
Lưu ý rằng tên đủ điều kiện của Serverlớp được chỉ định trong cấu hình. Ngoài ra, thẻ phụ thuộc chỉ định rằng chúng tôi sẽ sử dụng máy chủ web cầu cảng được nhúng để triển khai ứng dụng máy chủ của chúng tôi.
Triển khai máy chủ
Cuối cùng, để triển khai ứng dụng máy chủ, bạn sẽ cần thực hiện thêm một sửa đổi nữa trong pom.xml để thiết lập ứng dụng của mình dưới dạng ứng dụng web. Mã mà bạn cần thêm vàopom.xml được đưa ra dưới đây -
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>*.wsdl</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
Trước khi triển khai ứng dụng, bạn cần thêm hai tệp nữa vào dự án của mình. Chúng được hiển thị trong ảnh chụp màn hình bên dưới -
Các tệp này là tệp tiêu chuẩn CXF xác định ánh xạ cho CXFServlet. Mã trongweb.xml tệp được hiển thị ở đây để bạn tham khảo nhanh -
//cxf-servlet.xml
<web-app xmlns = "http://java.sun.com/xml/ns/javaee"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>cxf</display-name>
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
bên trong cxf-servlet.xmlbạn khai báo các thuộc tính cho điểm cuối dịch vụ của bạn. Điều này được hiển thị trong đoạn mã bên dưới -
<beans ...>
<jaxws:endpoint xmlns:helloworld = "http://tutorialspoint.com/"
id="helloHTTP"
address = "http://localhost:9090/HelloServerPort"
serviceName = "helloworld:HelloServiceService"
endpointName = "helloworld:HelloServicePort">
</jaxws:endpoint>
</beans>
Ở đây chúng tôi xác định id cho điểm cuối dịch vụ của chúng tôi, địa chỉ mà dịch vụ sẽ khả dụng, tên dịch vụ và tên điểm cuối. Bây giờ, bạn đã hiểu cách dịch vụ của bạn được định tuyến và xử lý bởi một servlet CXF.
Pom.xml cuối cùng
Các pom.xmlbao gồm một số phụ thuộc khác. Thay vì mô tả tất cả các phụ thuộc, chúng tôi đã đưa vào phiên bản cuối cùng của pom.xml bên dưới:
<?xml version="1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tutorialspoint</groupId>
<artifactId>cxf-wsdl</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>*.wsdl</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/Hello.wsdl</wsdl>
<faultSerialVersionUID>1</faultSerialVersionUID>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>server</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>
com.tutorialspoint.helloworld.Server
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>client</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>
com.tutorialspoint.helloworld.Client
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-management</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-metrics</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf.xjc-utils</groupId>
<artifactId>cxf-xjc-runtime</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-features-logging</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.8.0-beta2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</project>
Lưu ý rằng nó cũng bao gồm một hồ sơ để xây dựng khách hàng mà chúng ta sẽ sớm tìm hiểu trong các phần sau.
Chạy dịch vụ HelloWorld
Bây giờ, bạn đã sẵn sàng để chạy ứng dụng web. Trong cửa sổ lệnh, chạy tập lệnh xây dựng bằng lệnh sau.
mvn clean install
Thao tác này sẽ tạo các lớp Apache CXF thích hợp từ wsdl của bạn, biên dịch các lớp Apache CXF của bạn, triển khai máy chủ trên máy chủ cầu cảng được nhúng và chạy ứng dụng của bạn.
Bạn sẽ thấy thông báo sau trên bảng điều khiển -
INFO: Setting the server's publish address to be
http://localhost:9090/HelloServerPort
Server ready...
Như trước đây, bạn có thể kiểm tra máy chủ bằng cách mở URL máy chủ trong trình duyệt của mình.
Vì chúng tôi không chỉ định bất kỳ thao tác nào, chỉ một thông báo lỗi được ứng dụng của chúng tôi trả lại cho trình duyệt. Bây giờ, hãy thử thêm?wsdl vào URL của bạn và bạn sẽ thấy kết quả sau:
Vì vậy, ứng dụng máy chủ của chúng tôi đang chạy như mong đợi. Bạn có thể sử dụng Ứng dụng khách SOAP chẳng hạn nhưPostman được mô tả trước đó để kiểm tra thêm dịch vụ của bạn.
Phần tiếp theo của hướng dẫn này là viết một ứng dụng khách sử dụng dịch vụ của chúng tôi.
Đang phát triển khách hàng
Viết máy khách trong ứng dụng CXF cũng quan trọng như viết máy chủ. Đây là mã hoàn chỉnh cho máy khách về cơ bản chỉ bao gồm ba dòng, phần còn lại của các dòng chỉ in thông tin dịch vụ cho người dùng.
//Client.java
package com.tutorialspoint.helloworld;
public class Client {
public static void main(String[] args) throws Exception {
//Create the service client with its default wsdlurl
HelloWorldService helloServiceService = new HelloWorldService();
System.out.println("service: " +
helloServiceService.getServiceName());
System.out.println("wsdl location: " +
helloServiceService.getWSDLDocumentLocation());
HelloWorldPortType helloService =
helloServiceService.getHelloWorldPort();
System.out.println(helloService.greetings
(System.getProperty("user.name")));
}
}
Ở đây, chúng tôi chỉ cần tạo một phiên bản dịch vụ của chúng tôi HelloWorldService, lấy cổng của nó bằng cách gọi getHelloWorldPort và sau đó vượt qua greetingsnhắn cho nó. Chạy ứng dụng khách và bạn sẽ thấy kết quả sau:
service: {http://helloworld.tutorialspoint.com/}HelloWorldService
wsdl location: file:/Users/drsarang/Desktop/tutorialpoint/cxf-
wsdl/src/main/resources/Hello.wsdl
hi drsarang
Cho đến nay, bạn đã học cách sử dụng CXF với các kiến trúc Apache CXF-First và WSDL-First. Trong cách tiếp cận Apache CXF-First, bạn đã sử dụng POJO vớiServerFactoryBeanlớp từ các thư viện CXF để tạo một máy chủ. Để tạo một khách hàng bạn đã sử dụngClientProxyFactoryBeanlớp từ thư viện CXF. Trong phương pháp WSDL-First, bạn đã sử dụngEndpointlớp để xuất bản dịch vụ tại URL mong muốn và một trình triển khai được chỉ định. Bây giờ bạn có thể mở rộng các kỹ thuật này để tích hợp các giao thức và phương tiện truyền tải khác nhau.