Serveis Web i Mashups a PHP
Contingut
Què són els Serveis Web?
Els serveis web són aplicacions client i servidor que es comuniquen sobre (WWW) Protocol de transferència d'hipertext de la World Wide Web (HTTP). Segons el descrit pel World Wide Web Consortium (W3C), serveis web proporcionen un mitjà estàndard d'interoperabilitat entre aplicacions de programari que s'executen en una varietat de plataformes i marcs. Els serveis web es caracteritzen per la seva gran interoperabilitat i extensibilitat, així com les seves descripcions processable per màquina, gràcies a la utilització de XML. Els serveis web es poden combinar d'una manera precisa per aconseguir operacions complexes.
Tipus de Serveis Web
En el pla conceptual, un servei és un component de programari que es proporciona de la xarxa.
A nivell tècnic, els serveis web es poden implementar de diverses maneres. Els dos tipus de serveis web analitzats en aquesta secció es poden distingir com a Big Web Services i serveis web RESTful.
Big Web Services En Java EE 6, JAX-WS proporciona la funcionalitat de Big Web Services. Serveis web Grans utilitzen missatges XML que segueixen el protocol d'accés a objectes estàndard (SOAP), un llenguatge XML que defineix una arquitectura de missatges i formats de missatges. Aquests sistemes sovint contenen una descripció llegible per les màquines de les operacions que ofereix el servei, escrit en la Web Services Description Language (WSDL), un llenguatge XML per a definir sintàcticament interfícies.
El format del missatge SOAP i WSDL llenguatge de definició d'interfície han guanyat l'adopció generalitzada. Moltes de les eines de desenvolupament, com NetBeans IDE, poden reduir la complexitat del desenvolupament d'aplicacions de serveis web.
Serveis Web REST En Java EE 6, JAX-RS proporciona la funcionalitat per a la Transferència d'estat representacional (REST Web Services). REST és molt adequat per a escenaris bàsics. Serveis web RESTful sovint estan millor integrats amb HTTP que els serveis basats en SOAP ja que no requereixen de missatges XML o definicions servei API WSDL.
Projecte Jersey és la implementació de referència de l'especificació JAX-RS. Jersei implementa suport per a les anotacions definides en l'especificació JAX-RS, el que facilita als desenvolupadors crear serveis web RESTful amb Java i la màquina virtual de Java (JVM).
SOAP Web Services
Simple Object Access Protocol (SOAP)és un protocol estàndard per l'intercanvi de missatges XML. La comunicació entre el client i el servei succeeix utilitzant missatges XML.
Què és el WSDL?
WSDL: Web Service Description Language. És un arxiu XML que descriu els detalls tècnics de com s'implementa un servei web, més específicament la URI, port, nom dels mètodes, els paràmetres i els tipus de dades. Llegint el WSDL poden veure:
- Ports / EndPoint - URL del servei web
- Format del missatge d'entrada
- Format del missatge de sortida
- Protocol de seguretat que s'ha de seguir
- El protocol de servei web utilitzat
Exemple:
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2-hudson-740-. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2-hudson-740-. --><definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws/" name="Hola">
<wsp:Policy wsu:Id="HolaPortBindingPolicy" />
<types>
<xsd:schema>
<xsd:import namespace="http://ws/" schemaLocation="http://localhost:8084/webServiceProject/Hola?xsd=1" />
</xsd:schema>
</types>
<message name="hello">
<part name="parameters" element="tns:hello" />
</message>
<message name="helloResponse">
<part name="parameters" element="tns:helloResponse" />
</message>
<message name="adeu">
<part name="parameters" element="tns:adeu" />
</message>
<message name="adeuResponse">
<part name="parameters" element="tns:adeuResponse" />
</message>
<portType name="Hola">
<operation name="hello">
<input wsam:Action="http://ws/Hola/helloRequest" message="tns:hello" />
<output wsam:Action="http://ws/Hola/helloResponse" message="tns:helloResponse" />
</operation>
<operation name="adeu">
<input wsam:Action="http://ws/Hola/adeuRequest" message="tns:adeu" />
<output wsam:Action="http://ws/Hola/adeuResponse" message="tns:adeuResponse" />
</operation>
</portType>
<binding name="HolaPortBinding" type="tns:Hola">
<wsp:PolicyReference URI="#HolaPortBindingPolicy" />
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<operation name="hello">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
<operation name="adeu">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="Hola">
<port name="HolaPort" binding="tns:HolaPortBinding">
<soap:address location="http://localhost:8084/webServiceProject/Hola" />
</port>
</service>
</definitions>
Existeixen dues maneres per accedir a un servei web:
- 'El proveïdor de serveis web coneix al client:El proveïdor de serveis web proporcionarà el WSDL al client i el client podrà accedir als serveis web.
- El proveïdor de serveis registri la WSDL com a UDDI. UUID (Universal Description, Discover and Integration). Els WSDL es poden convertir a un UDDI i així, poden estar disponibles mitjançant un directori de serveis per a la seva utilització.
SOAP Message
SOAP està basat en XML i, per això, està considerat llegible per alguns éssers humans, però està basat en un esquema XSD específic que se li ha d'afegir. Veiem un petit missatge SOAP treient tota la informació i agafant només les etiquetes que fan que sigui un missatge SOAP:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
...
</soap:Header>
<soap:Body>
...
<soap:Fault>
...
</soap:Fault>
</soap:Body>
</soap:Envelope>
Sembla només un altre arxiu XML però, el que fa que sigui un missatge SOAP és l'element root anomenat Envelope que té l'espai de noms soap a http://www.w3.org/2001/12/soap-envelope. L'atribut soap:encodingStyle determina el tipus de dades que s'utilitza en el fitxer per que SOAP no té una codificació per defecte.
L'element soap:Envelope és obligatori però l'elemenmt següent soap:Header és opcional i normalment conté informació rellevant a l'autenticació i la sessió. El protocol SOAP no ofereix autenticació però ofereix als desenvolupadors aquesta etiqueta per a incloure-ho.
El següent element es tracta de soap:Body que és obligatori. Conté el missatge RPC (Remote Procedure Call) on s'inclou els mètodes i si és un missatge de resposta, també el valor retornat pel mètode. L'etiqueta soap:Fault és opcional. Si està present al missatge conté els erros i el missatges dels errors.
Donem un cop d'ull a un missatge SOAP de petició:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.yourwebroot.com/stock">
<m:GetStockPrice>
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
El missatge anterior és una petició per obtenir el preu d'estoc d'una empresa en concret. Dintre de l'etiqueta soap:Body veuràs l'element GetStockPrice que No correspon a SOAP, si no, que aquest element fa referència a un mètode particular de l'aplicació de servidor que es cridarà al rebre aquest missatge. L'element StockName també és específic de l'aplicació servidora i correspon a un paràmetre de la funció anterior.
El missatge de resposta és molt semblant:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.yourwebroot.com/stock">
<m:GetStockPriceResponse>
<m:Price>183.08</m:Price>
</m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>
Dintre de l'element soap:Body veuràs l'element GetStockPriceRespomse que conté l'element Price amb la dada de resposta. Ambdós elements son específics de l'aplicació de servidor.
NuSOAP server
És molt senzill crear un servei web utilitzant la llibreria NuSOAP de PHP. Pots descarregar-la des d'aquest | enllaç. Baixa't-ho i descomprimeix-lo en el directori principal de l'aplicació. Per utilitzar-ho només has d'incloure la llibreria nusoap.php en el codi de l'aplicació.
Veiem un exemple d'utilització de la llibreria nusoap per crear un servei web.
<?php
require_once "nusoap.php";
function getProd($category) {
if ($category == "books") {
return join(",", array(
"The WordPress Anthology",
"PHP Master: Write Cutting Edge Code",
"Build Your Own Website the Right Way"));
}
else {
return "No products listed under that category";
}
}
$server = new soap_server();
$server->register("getProd");
$server->service($HTTP_RAW_POST_DATA);
Primer s'inclou el fitxer nusoap.php per poder accedir a la llibreria NuSOAP. Després es defineix la funció getProd() i s'instancia un objecte de la classe soap_server. Immediatament després s'utilitza el mètode register per afegir la funció getProd al servidor sopa i poder accedir a ella des de un client. És a dir, convertim la funció getProd en un servei web.
Segurament, en un escenari real, la funció getProd hauria de cercar en una Base de Dades la informació que s'ha d'enviar a l'usuari. Ara mateix, no volem complicar el codi en coses externes a SOAP.
Es poden registrar funcions addicionals en el servidor per per donar més funcionalitats a l'aplicació. El procés seria idèntic del descrit anteriorment.
NuSOAP Client
Crearem una pàgina php que utilitzarà el servei web anterior:
<?php
require_once "nusoap.php";
$client = new nusoap_client("http://localhost/nusoap/productlist.php");
$error = $client->getError();
if ($error) {
echo "<h2>Constructor error</h2><pre>" . $error . "</pre>";
}
$result = $client->call("getProd", array("category" => "books"));
if ($client->fault) {
echo "<h2>Fault</h2><pre>";
print_r($result);
echo "</pre>";
}
else {
$error = $client->getError();
if ($error) {
echo "<h2>Error</h2><pre>" . $error . "</pre>";
}
else {
echo "<h2>Books</h2><pre>";
echo $result;
echo "</pre>";
}
}
Com va passar en el servidor, primer s'ha d'incloure la llibreria nusoap.php amb la directiva required_once. Seguidament, es crea un nova instància d'un client soap amb la classe: nusoap_client. El constructor necessita la localització del servidor soap al que s'ha de connectar. És a dir, del fitxer on es troba la creació del soap_server amb les funcions registrades.
La funció getError comprova si el client SOAP s'ha creat correctament i si no ha estat així, mostra un missatge d'error.
El mètode call() genera i envia un missatge SOAP de tipus petició (Request) a la funció o el mètode definit com a primer paràmetre. El segon paràmetre de la funció call() és un array associatiu del paràmetres que necessita el mètode servidor.
La propietat fault i el mètode getError() son utilitzat per comprovar i mostrar cualsevol error produït en la comunicació.
Creació d'un arxiu WSDL
Escriure un fitxer WSDL a mà pot ser de bojos. Una utilitat molt interessant de nusoap és que pot crear un fitxer WSDL automàticament. Veurem un exemple modificant una mica l'exemple anterior:
<?php
require_once "nusoap.php";
function getProd($category) {
if ($category == "books") {
return join(",", array(
"The WordPress Anthology",
"PHP Master: Write Cutting Edge Code",
"Build Your Own Website the Right Way"));
}
else {
return "No products listed under that category";
}
}
$server = new soap_server();
$server->configureWSDL("productlist", "urn:productlist");
$server->register("getProd",
array("category" => "xsd:string"),
array("return" => "xsd:string"),
"urn:productlist",
"urn:productlist#getProd",
"rpc",
"encoded",
"Get a listing of products by category");
$server->service($HTTP_RAW_POST_DATA);
Bàsicament és el mateix codi amb quatre canvis. El primer canvi que s'ha afegit és la crida a la funció configureWSDL(). Aquest mètode prepara al servidor per a que pugui generar un fitxer WSDL dels nostres serveis registrats. El primer paràmetre d'aquesta funció, és el nom del servei i el segon correspon a l'espai de noms del servei.