Hva er SOAP? Hva med IBM SOAP4J

Hva er SOAP? Hva med IBM SOAP4J

Brett McLaughlin Oversettelse av Ilya Chekmenev

SOAP er Simple Object Access Protocol. Hvis du aldri har hørt om det før, må du bo midt i ingensteds, langt fra sivilisasjonen. Det har blitt den siste moten innen webprogrammering, og en integrert del av webtjenester, som brukes med en slik fanatisme i nettutvikling av den siste generasjonen. Hvis du har hørt om Microsofts .NET, eller peer-to-peer "revolusjon", så har du hørt om teknologier som er avhengige av SOAP (selv om du ikke vet hva det er). Det er ikke en, men to SOAP-implementeringer fra Apache og Microsoft, som har tusenvis av sider dedikert til dem på deres MSDN-støtteside (http://msdn.microsoft.com/).

I denne artikkelen vil jeg fortelle deg hva SOAP er og hvorfor det er en så viktig del i utviklingen av webprogrammeringsparadigmet. Dette vil hjelpe deg å hoppe over det grunnleggende og komme rett i gang med SOAP-verktøysettet. Deretter vil jeg gi en rask oversikt over eksisterende SOAP-prosjekter og dykke ned i Apaches implementering. Denne artikkelen er ikke ment å gi et fullstendig bilde av SOAP boken min, Java & XML, 2nd Edition, fyller ut mange av hullene. Du finner svar på mange av spørsmålene som dukket opp etter å ha lest denne artikkelen i boken.

Introduksjon

Først må du forstå hva SOAP er. Du kan lese hele (og ganske lange) W3C-uttalelsen på http://www.w3.org/TR/SOAP. Så, etter å ha funnet ut av det og kastet alt skallet, vil du forstå at SOAP bare er en protokoll. Det er en enkel protokoll (ikke nødvendig å skrive en ny for å bruke den) basert på ideen om at det på et tidspunkt i en distribuert arkitektur er behov for å utveksle informasjon. I tillegg, for systemer der det er mulighet for overbelastning og vanskeligheter med å behandle prosesser, er denne protokollen svært fordelaktig ved at den er lett og krever et minimum av ressurser. Til slutt lar den alle operasjoner utføres over HTTP, noe som gjør det mulig å omgå så vanskelige ting som brannmurer og beskytte deg mot å lytte ved hjelp av sockets på utrolig mange porter. Hovedsaken er at du innser dette, og alt annet er detaljer.

Selvfølgelig vil du gjerne vite disse detaljene, og jeg vil ikke ignorere dem. Det er tre grunnleggende komponenter i SOAP-spesifikasjonen: en SOAP-konvolutt, et sett med krypteringsregler og et middel for interaksjon mellom forespørselen og svaret. La oss tenke på en SOAP-melding som et vanlig brev. Husker du fortsatt de gamle tingene i konvolutter med et frimerke og adressen skrevet på forsiden? Denne analogien vil hjelpe deg å forstå konseptet SOAP som en "konvolutt" klarere. Figur 12-1 viser SOAP-prosesser i form av denne analogien.

Figur 12-1. SOAP Meldingsprosess

Ha dette bildet i bakhodet, og la oss se på de tre komponentene i SOAP-spesifikasjonen. Jeg skal snakke kort om hver av dem, og gi eksempler som best representerer konseptet. Disse tre nøkkelkomponentene gjør SOAP så viktig og meningsfylt. Feilhåndtering, støtte for ulike krypteringer, parameterserialisering og det faktum at SOAP fungerer over HTTP gjør det i de fleste tilfeller mer attraktivt enn andre løsninger for distribuerte protokoller. SOAP gir en høy grad av interoperabilitet med andre applikasjoner, som jeg dekket mer detaljert i boken min. Foreløpig vil jeg fokusere på kjerneelementene i SOAP.

Konvolutt

En SOAP-konvolutt ligner på en vanlig brevkonvolutt. Den inneholder informasjon om meldingen som vil bli kryptert i SOAP-hoveddelen, inkludert informasjon om mottaker og avsender, samt informasjon om selve meldingen. For eksempel kan SOAP-konvolutthodet indikere hvordan meldingen skal behandles. Før en søknad begynner å behandle en melding, undersøker den informasjon om meldingen, inkludert om den i det hele tatt kan behandle meldingen. I motsetning til situasjonen med standard XML-RPC-anrop (husker du? XML-RPC-meldinger, kryptering osv., er alt kombinert til et enkelt XML-fragment), med SOAP skjer den pågående behandlingen for å lære noe om meldingen. En typisk SOAP-melding kan også inneholde en krypteringsstil som vil hjelpe mottakeren med å behandle meldingen. Eksempel 12-1 viser en SOAP-konvolutt som ender med en kodingsspesifikasjon.

Eksempel 12-1: SOAP Konvolutt

Såpeboks http://www-106.ibm.com/developerworks/library/x-soapbx1.html

Som du kan se, er krypteringen satt inne i konvolutten, som lar applikasjonen bestemme (ved å bruke attributtverdien kodingsstil), om den kan lese den innkommende meldingen som ligger i elementet Kropp. Kontroller at SOAP-konvoluttens navneområde er riktig, ellers vil SOAP-serverne som mottar meldingen din rapportere en versjonsfeil, og du vil ikke kunne kommunisere med dem.

Kryptering

Det andre viktige elementet i SOAP er muligheten til å kryptere tilpassede datatyper. Med RPC (og XML-RPC) kan kryptering kun utføres på forhåndsdefinerte datatyper som støttes i XML-RPC-verktøysettet du lastet ned. Kryptering av andre typer data krever at du endrer RPC-serveren og klienten selv. Med SOAP kan et XML-skjema ganske enkelt brukes til å spesifisere nye datatyper (ved å bruke strukturen kompleksType, diskutert i kapittel 2 i boken min), og disse nye typene kan representeres i XML som en del av hoveddelen av SOAP. Takket være XML Schema-integrasjon kan du kryptere alle typer data i en SOAP-melding ved å logisk beskrive dem i et XML-skjema.

Anrop

Den beste måten å forstå hvordan et SOAP-anrop fungerer, er å sammenligne det med noe du er kjent med, for eksempel XML-RPC. Hvis du husker det, ligner XML-RPC-kallet kodebiten presentert i eksempel 12-2.

Eksempel 12-2. Ring til XML-RPC

// Spesifisere XML-prosessoren (parser) for å bruke XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); // Spesifisere serveren som tilkoblingen gjøres til XmlRpcClient client = new XmlRpcClient("http://rpc.middleearth.com"); // Opprette parametere Vector params = new Vector(); params.addElement(flynummer); params.addElement(antallSeter); params.addElement(kredittkorttype); params.addElement(kredittKortNum); // Be om boolske kjøpte billetter = (boolsk)client.execute("ticketCounter.buyTickets", params); // Behandle svaret

Jeg laget et enkelt program for bestilling av flybilletter. Ta en titt på eksempel 12-3, som viser et SOAP-anrop.

Eksempel 12-3. Ring til SOAP

// Opprette parametere Vector params = new Vector(); params.addElement(ny parameter("flynummer", heltall.klasse, flynummer, null)); params.addElement(ny parameter("antallSeats", Integer.class, numSeats, null)); params.addElement(ny parameter("kredittkorttype", String.class, kredittkorttype, null)); params.addElement(ny parameter("kredittkortnummer", Long.class, creditCardNum, null)); // Opprette et anropsobjekt Call call = new Call(); call.setTargetObjectURI("urn:xmltoday-airline-tickets"); call.setMethodName("kjøp billetter"); call.setEncodingStyleURI(Konstanter.NS_URI_SOAP_ENC); call.setParams(params); // Call Response res = call.invoke(ny URL("http://rpc.middleearth.com"), ""); // Behandle svaret

Som du kan se, er det faktiske kallet representert av objektet Anrop, minneboende. Den lar deg spesifisere anropsmål, anropsmetode, krypteringsstil, parametere og mange andre parametere som ikke er presentert i dette eksemplet. Dette er en mer fleksibel mekanisme enn XML-RPC-metoden, som lar deg spesifisere eksplisitt et sett med forskjellige parametere som er implisitt definert i XML-RPC. Senere i denne artikkelen vil du lære mer om anropsprosessen, inkludert hvordan SOAP håndterer ugyldige forespørsler, feilhierarkiet og, selvfølgelig, anropsresultatene som returneres.

Etter en så kort introduksjon vet du allerede nok til å være interessert i denne morsomme tingen. La meg nå introdusere deg til SOAP-implementeringen jeg skal bruke. Jeg vil forklare årsakene til at jeg valgte det og se på noen kodeeksempler.

Innstillinger

Nå som du har lært det grunnleggende om konseptet, er det tid for den morsomme delen: programmering. For å gjøre dette trenger du et praktisk prosjekt eller produkt, som er lettere å finne enn det kan virke ved første øyekast. Hvis du trenger et Java-prosjekt som gir SOAP-funksjoner, trenger du ikke lete lenge for å finne et. Det er to grupper av produkter: kommersielle og gratis. Som i min bok vil jeg unngå å nevne kommersielle produkter. Dette er slett ikke fordi de er dårlige (tvert imot, noen av dem er utmerkede), men fordi jeg vil at enhver leser skal kunne prøve noen av eksemplene som er gitt. Dette skyldes tilgjengelighet, som mange kommersielle produkter ikke har. Du må betale for å bruke dem, eller midlertidig bruke dem i en begrenset periode etter nedlasting.

Dermed nærmet vi oss problemfritt med åpen kildekode-prosjekter. Fra dette området kan jeg bare nevne ett produkt: Apache SOAP. Den ligger på http://xml.apache.org/soap og gir SOAP-verktøysett for Java. I skrivende stund ble versjon 2.2 utgitt, som du kan laste ned fra Apache-nettstedet. Det er denne versjonen jeg skal bruke i eksemplene for denne artikkelen.

Andre alternativer

Før jeg går videre til å installere og konfigurere Apache SOAP, vil jeg svare på noen spørsmål som kan ha sneket seg inn i hodet ditt. Jeg tror jeg har forklart ganske tydelig årsakene til at jeg ikke bruker kommersielle produkter. Imidlertid kan det hende du tenker på noen andre åpen kildekode eller relaterte prosjekter som du kanskje vil bruke, og du er overrasket over at jeg ikke har kommentert dem.

Hva med IBM SOAP4J?

Først på listen over alternativer er en implementering fra IBM: SOAP4J. IBMs arbeid dannet grunnlaget for Apache SOAP-prosjektet, akkurat som IBMs XML4J vokste til det som nå er kjent som Apache Xerces XML-parserprosjektet. Det antas at IBM-implementeringen vil bli redesignet, og slå seg sammen med Apache SOAP. Mye av det samme skjedde med IBMs XML4J: nå gir den kun pakking i Xerces Dette fremhever bare trendene - store produsenter støtter og bruker ofte OpenSource-prosjekter, i dette tilfellet bruker begge prosjektene (Apache og IBM) samme kodebase.

Er Microsoft ute av spillet?

Selvfølgelig ikke. Microsoft og SOAP-implementeringen, samt hele .NET-bevegelsen (diskutert mer detaljert i boken min), er ganske viktige. Jeg ønsket virkelig å bruke mesteparten av tiden min på å se på Microsofts SOAP-implementering i detalj, men den støtter bare COM-objekter og den støtter ikke Java. Av disse grunnene kunne ikke en slik beskrivelse inkluderes i en artikkel om Java og XML. Imidlertid har Microsoft (til tross for alle klagene vi, som utviklere, har på dette selskapet) gjort viktig arbeid innen webtjenester, og du vil gjøre en feil hvis du avviser det uten å tenke, kun styrt av rå følelser. Hvis du har behov for å jobbe med COM- eller Visual Basic-komponenter, anbefaler jeg på det sterkeste at du prøver å bruke Microsoft SOAP-verktøysettet, tilgjengelig på http://msdn.microsoft.com/library/default.asp?url=/nhp/Default .asp ?contentid=28000523 sammen med mange andre SOAP-ressurser.

Hva er Axis?

De av dere som følger Apache-aktiviteter må ha hørt om Apache Axis. Axis er et neste generasjons SOAP-verktøysett også utviklet under Apache XML-paraplyen. SOAP (en spesifikasjon, ikke en spesifikk implementering), som har utviklet seg raskt og radikalt i det siste, er svært vanskelig å følge. Å prøve å lage en versjon av SOAP som fullt ut oppfyller gjeldende krav etter hvert som de utvikler seg, er også ganske utfordrende. Som et resultat tilbyr den nåværende versjonen av Apache SOAP en løsning begrenset av designet. Etter å ha bestemt seg for at det ikke var verdt å prøve å redesigne det eksisterende verktøyet fullstendig, begynte Apache-utviklerne å lage et prosjekt basert på den nye koden. Dermed ble Axis født. SOAPs navn endret seg også, først fra SOAP til XP og deretter til XMLP. Da ble spesifikasjonsnavnet droppet fra navnet på den nye SOAP og navnet "Axis" ble født. Men nå ser det ut til at W3C går tilbake til navnet på SOAP-spesifikasjonen (versjon 1.2 eller 2.0), så ting kan fortsatt endre seg og det vil bli enda mer forvirring!

Tenk på IBM SOAP4J som en arkitektur?1 av SOAP-verktøysettet. Hva med Apache SOAP (diskutert i denne artikkelen) som arkitektur?2. Og Axis representerer ?3-arkitekturen, en ny generasjons arkitektur. Dette prosjektet bruker SAX mens Apache SOAP er DOM-basert. I tillegg gir Axis, i motsetning til Apache SOAP, en mer brukervennlig tilnærming til brukerinteraksjon. Etter å ha listet opp disse fordelene, lurer du kanskje på hvorfor jeg ikke valgte Axis som studiefag. Det ville bare vært litt for tidlig. Foreløpig er det kun versjon 0.51 av Axis som forberedes for utgivelse. Dette er ikke en betaversjon ennå, eller til og med en alfaversjon. Jeg vil gjerne snakke om de nye Axis-funksjonene, men du har ingen sjanse til å overbevise ledelsen om at du kan bruke sub-alfa åpen kildekode-programvare for dine kritiske systembehov. Så jeg bestemte meg for å fokusere på noe du er ekte du kan bruke allerede I dag- Apache SÅPE. Jeg tror at innen den endelige versjonen av Apache Axis er utgitt, vil jeg oppdatere dette materialet i neste utgave av boken min. Inntil da, la oss fokusere på løsningen som allerede er tilgjengelig.

Installasjon

Det er to mulige former for SOAP-installasjon. Den første er å starte en SOAP-klient ved å bruke SOAP API for å kommunisere med en server som kan akseptere SOAP-meldinger. Den andre måten er å kjøre en SOAP-server som kan motta meldinger fra en SOAP-klient. I denne delen har jeg beskrevet begge prosedyrene.

Klient

For å bruke SOAP-klienten må du først laste ned Apache SOAP, tilgjengelig på http://xml.apache.org/dist/soap. Jeg lastet ned versjon 2.2 i binært format (fra underkatalogen versjon-2.2). Deretter må du pakke ut innholdet i arkivet til en katalog på datamaskinen din. I mitt tilfelle var det katalogen javaxml2 (c:\javaxml2 på min Windows-datamaskin /javaxml2 på min Mac OS X-datamaskin). Som et resultat ble filene pakket ut /javaxml2/soap-2_2. Du må også laste ned JavaMail-pakken som er tilgjengelig fra Sun http://java.sun.com/products/javamail/. Det vil være nødvendig å støtte SMTP-overføringsprotokollen som brukes av Apache SOAP. Last deretter ned Java Beans Activation Framework (JAF), også tilgjengelig fra Sun http://java.sun.com/products/beans/glasgow/jaf.html. Basert på antakelsen om at du allerede har Xerces eller en annen XML-parser installert og klar til bruk.

Merk: Sørg for at XML-parseren er JAXP-kompatibel og bruker navneområdet riktig. Parseren din oppfyller sannsynligvis disse kravene. Hvis du har problemer, er det best å gå tilbake til å bruke Xerces.

Merk: Bruk de nyeste versjonene av Xerces. Versjon 1.4 og høyere vil gjøre det. Det er en del feil med SOAP og Xerces 1.3(.1), så jeg fraråder å bruke denne kombinasjonen.

Pakk ut JavaMail- og JAF-pakkene og inkluder deretter jar-filene deres i klassebanen din, så vel som i biblioteket såpe.krukke. Hver av disse jar-filene må være plassert enten i rotkatalogen til det tilsvarende programmet, eller i en underkatalog /lib. Når du er ferdig med variabelen din klassesti skal se omtrent slik ut:

$ echo $CLASSPATH /javaxml2/soap-2_2/lib/soap.jar:/javaxml2/lib/xerces.jar: /javaxml2/javamail-1.2/mail.jar:/javaxml2/jaf-1.0.1/activation.jar

For Windows vil det se slik ut:

c:\>echo %CLASSPATH% c:\javaxml2\soap-2_2\lib\soap.jar;c:\javaxml2\lib\xerces.jar; c:\javaxml2\javamail-1.2\mail.jar;c:\javaxml2\jaf-1.0.1\activation.jar

Og til slutt legg til katalogen javaxml2/soap-2_2/ i din klassestiå kjøre SOAP-eksempler. Jeg har beskrevet oppsettet for flere eksempler i dette kapittelet.

Server

For å lage et SOAP-kompatibelt sett med serverkomponenter, trenger du først en servletmotor. Som i tidligere kapitler brukte jeg Apache Tomcat (tilgjengelig på http://jakarta.apache.org/) som et eksempel for dette kapittelet. Du må legge til alt kunden trenger klassesti server. Den enkleste måten å gjøre dette på er å tilbakestille såpe.krukke, activation.jar Og mail.jar, så vel som din parser, inn i bibliotekkatalogen til servletmotoren din. For Tomcat er dette /lib-katalogen, som inneholder biblioteker for automatisk lasting. Hvis du ønsker å gi støtte for skript (som ikke er omtalt i dette kapittelet, men er i Apache SOAP-eksemplene), må du sette bsf.jar(tilgjengelig på http://oss.software.ibm.com/developerworks/projects/bsf) og js.jar(tilgjengelig på http://www.mozilla.org/rhino/) til samme katalog.

Merk: Hvis du bruker Xerces med Tomcat, må du gjenta trikset jeg dekket i kapittel 10. Gi nytt navn parser.jar V z_parser.jar, A jaxp.jar V z_jaxp.jarå sørge for det xerces.jar og den inkluderte versjonen av JAXP lastes før noen annen parser eller JAXP-implementering.

Start deretter servletmotoren på nytt, hvoretter du er klar til å skrive SOAP-serverkomponenter.

Router Servlet og Admin Client

Bortsett fra de grunnleggende operasjonene, inkluderer Apache SOAP en ruterservlet samt en adminklient. Selv om du ikke har tenkt å bruke dem, anbefaler jeg at du installerer dem for å teste at SOAP er riktig installert. Denne prosessen avhenger av hvilken servletmotor du bruker, så jeg vil begrense installasjonsprosessen til Tomcat. Installasjonsinstruksjoner for noen andre servletmotorer finner du på http://xml.apache.org/soap/docs/index.html.

Installasjonen under Tomcat er veldig enkel: bare ta filen såpe.krig fra katalogen soap-2_2/webapps og slipp den inn i katalogen $TOMCAT_HOME/webapps- og det er det! For å sjekke installasjonen, skriv inn adressen i nettleseren din http://localhost:8080/soap/servlet/rpcrouter. Du bør motta et svar som ligner på det som er vist i figur 12-2.

Figur 12-2. Ruter RPC Servlet

Selv om meldingen ser ut til å være en feilmelding, indikerer den at alt fungerer som det skal. Du bør få samme svar hvis du peker nettleseren til administratorens klientadresse: http://localhost:8080/soap/servlet/messagerouter.

For å fullføre testingen av serveren og klienten, sørg for at du har fulgt alle instruksjonene fullstendig. Kjør deretter følgende Java-klasse som vist nedenfor for å støtte servlet-URLen for RPC-ruterservleten:

C:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list Distribuerte tjenester:

Du bør få en tom liste over tjenester som vist ovenfor. Hvis du mottar meldinger, vennligst se gjennom den lange listen over mulige feil på http://xml.apache.org/soap/docs/trouble/index.html. Dette er den mest omfattende listen over problemer du kan støte på. Hvis du mottar en tom liste, betyr dette at oppsettet er fullført og du er klar til å begynne å se på eksemplene gitt i dette kapittelet.

La oss komme i gang

Det er tre hovedstadier i å skrive SOAP-baserte systemer. Etter å ha listet dem opp, vil jeg kort diskutere hver av dem:

  • Velge mellom SOAP-RPC og SOAP meldinger;
  • Å skrive eller få tilgang til en SOAP-tjeneste;
  • Skrive eller få tilgang til en SOAP-klient.

Det første trinnet er å velge om du vil bruke SOAP for RPC-anrop (der en ekstern prosedyre utføres på serveren), eller meldinger (der klienten ganske enkelt sender deler av informasjon til serveren). Jeg diskuterer disse prosessene i detalj nedenfor. Når du har tatt denne avgjørelsen, må du få tilgang til eller opprette din egen tjeneste. Siden vi alle er Java-profesjonelle, dekker dette kapittelet selvfølgelig hvordan du lager dine egne. Og til slutt må du skrive en klient for denne tjenesten, det er alt!

RPC eller meldinger?

Den første oppgaven din har ingenting med programmering å gjøre og er mer designmessig. Du må velge om du vil bruke RPC- eller meldingstjenesten. Vi vil anta at du er kjent med RPC (for eksempel ved å lese et av kapitlene i boken min). Klienten utfører en ekstern prosedyre på serveren og mottar deretter et svar. I dette scenariet fungerer SOAP som et forbedret XML-RPC-system som gir bedre feilhåndtering og overføring av komplekse datatyper over nettverket. Du er allerede kjent med dette konseptet, og siden RPC-systemer er lettere å skrive i SOAP, begynner jeg med dem. Denne artikkelen beskriver hvordan du oppretter en RPC-tjeneste, en RPC-klient og setter systemet i drift.

En annen måte å jobbe SOAP på er basert på meldingsutveksling. I stedet for å utføre eksterne prosedyrer, brukes den kun til å utveksle informasjon. Som du kan gjette, er dette et kraftig verktøy som ikke krever at klienten kjenner de individuelle metodene til noen server. Det gjør også modellering av eksterne systemer mer isolert ved å la datapakker (pakker i overført betydning, ikke i nettverksforstand) sendes til andre systemer. Samtidig trenger ikke andre systemer å vite om operasjonene som ble utført med disse dataene. Denne stilen er mer kompleks enn RPC-programmering, så jeg vil ikke beskrive den her. Du finner det i boken min, sammen med andre detaljer om interaksjon mellom bedrifter. Først, bli kjent med SOAP-RPC-programmering.

Som de fleste designproblemer er det opp til deg å ta denne avgjørelsen. Analyser søknaden din og prøv å finne ut hvorfor du trenger å bruke SOAP. Hvis du har en server og et sett med klienter som utfører spesifikke forretningsfunksjoner på forespørsel, er RPC mer egnet for deg. I komplekse systemer der datautveksling er mer enn bare å utføre spesifikke forretningsfunksjoner på forespørsel, er bruken av SOAP-meldinger mye å foretrekke.

RPC-tjeneste

Nå som formalitetene er over, er det på tide å handle. Som du vet, i RPC trenger du klasser hvis metoder vil bli utført eksternt.

Kodebiter

Jeg starter med å se på noen kodebiter for serveren. Disse fragmentene er klasser med metoder som kjøres for RPC-klienter. Jeg brukte kode fra boken min som eksempler. I stedet for å bruke enkle klasser, valgte jeg et mer komplekst eksempel for å demonstrere mulighetene til SOAP så tydelig som mulig. Så jeg brukte CD-klassen som et eksempel. Først definerer vi elementet kart for hver ikke-standard parametertype. For attributt kodingsstil, i det minste i Apache SOAP 2.2. du må oppgi verdien http://schemas.xmlsoap.org/soap/encoding/ . Dette er for øyeblikket den eneste støttede kodingen. Du må spesifisere navneområdet for den brukerdefinerte typen og deretter klassenavnet prefikset med navneområdet for den typen. I vårt tilfelle brukte jeg for disse formålene et fiktivt navneområde og et enkelt prefiks " x". Deretter bruker du attributtet javaType, angi det virkelige navnet på Java-klassen (for dette tilfellet - javaxml2.CD). Og til slutt, kuralesil med attributter java2XMLClassnavn Og xml2JavaKlassenavn. Med deres hjelp spesifiseres en klasse som konverteres fra Java til XML og omvendt. Jeg brukte den utrolig hendige BeanSerializer-klassen, som også følger med Apache SOAP. Hvis din egendefinerte parameter er i JavaBean-format, vil denne serializeren og deserializeren spare deg fra å måtte skrive din egen. Du trenger en klasse med en standard konstruktør (husk, for CD-klassen definerte jeg en enkel, parameterløs konstruktør), og publiser alle dataene til denne klassen ved å bruke metoder settXXX Og fåXXX. Fordi klasse CD tilfredsstiller alle disse kravene perfekt, BeanSerializer fungerer perfekt.

Merk: Hvilken klasse CD oppfyller kravene BeanSerializer. spiller ingen rolle. De fleste klasser konverteres enkelt til dette formatet. Derfor anbefaler jeg å unngå å skrive dine egne serializers og deserializers. Dette er en ekstra hodepine (ingenting komplisert, men for møysommelig) og jeg anbefaler at du sparer energi og bruker bønnekonvertering i dine egendefinerte parametere. I mange tilfeller krever bønnekonverteringer bare en standardkonstruktør (ingen parametere) i klassen din.

La oss nå gjenskape krukke fil og installer tjenesten vår på nytt:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml

Merk følgende: Hvis du lar servletmotoren kjøre og er vert for en tjeneste på samme tid, må du starte servletmotoren på nytt for å aktivere de nye klassene for SOAP-tjenesten og være vert for tjenesten på nytt.

Nå gjenstår det bare å modifisere klienten til å bruke nye klasser og metoder. Eksempel 12-10 inneholder en modifisert versjon av klientklassen CDAdder. Endringer som er gjort i forrige versjon er uthevet.

Eksempel 12-10: Oppdatert CDAdder-klasse

pakke javaxml2; importer java.net.URL; import java.util.Vector; import org.apache.soap.konstanter; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import org.apache.soap.util.xml.QName; offentlig klasse CDAdder( public void add (URL url, String title, String artist, String label) kaster SOAPException ( System.out.println("Legge til en CD med tittelen "" + tittel + "" artist "" + artist + "" studio " + label); CD cd = ny CD(tittel, artist, label); // Opprett et anropsobjekt Call Call call = new Call(); call.setSOAPMappingRegistry(register); call.setTargetObjectURI("urn:cd-catalog"); call.setMethodName("addCD"); call.setEncodingStyleURI(Konstanter.NS_URI_SOAP_ENC); // Sette parametere Vector params = new Vector(); params.addElement(ny parameter("cd", CD.class, cd, null)); call.setParams(params); // Behandling av Invoke call Response-svaret; respons = call.invoke(url, ""); if (!response.generatedFault()) ( System.out.println("Legg til CD fullført."); ) else (Fault fault = response.getFault(); System.out.println(Feil: " + fault.getFaultString ()); public static void main(String args) ( if (args.length != 4) ( System.out.println("Mal: java javaxml2.CDAdder " + "\"[CD-tittel]\" \"[Artistnavn]\ " \"[Studio CD]\""); prøv ( // URL til SOAP-serveren som tilkoblingen er gjort URL url = new URL(args); // Få verdier for ny CD-strengtittel = args; Strengekunstner = args; Strengetikett = args; // Legg til CD CDAdder adder = new CDAdder(); adder.add(url, tittel, artist, label); ) catch (Unntak e) ( e.printStackTrace(); ) ) )

Den eneste virkelig interessante endringen er i klassekartlegging CD:

// Kartlegg denne typen slik at den kan brukes med SOAP SOAPMappingRegistry registry = new SOAPMappingRegistry(); BeanSerializer serializer = ny BeanSerializer(); registry.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("urn:cd-catalog-demo", "cd"), CD.class, serializer, serializer);

Slik kan en brukerparameter kodes og overføres over nettverket. Jeg har allerede fortalt deg hvordan klassen BeanSerializer kan brukes til å behandle parametere i JavaBean-format, for eksempel klasse CD. Jeg brukte en plasseringsbeskrivelse for å indikere disse til serveren, men nå må jeg fortelle klienten å bruke denne serializeren og deserializeren. Denne funksjonen utføres av klassen SOAPMappingRegistry. Metode mapTypes() tar den krypterte strengen (igjen, det er bedre å bruke en konstant for dette NS_URI_SOAP_ENC), og informasjon om parametertypen som spesiell serialisering skal brukes for. QName angis først. Dette er grunnen til at det merkelige navnerommet ble brukt i vertsbeskrivelsen. Du må oppgi samme URN her, samt elementets lokale navn (for dette eksempelet "CD"), deretter Java-objektet Klasse klasse som vil bli serialisert ( CD.klasse) og til slutt en forekomst av klassen for serialisering og deserialisering. For dette eksemplet vil begge sakene involvere en instans BeanSerializer. Når alle disse innstillingene er lagt inn i registeret, varsle objektet Anrop ved hjelp av metoden setSOAPMapping-Registry().

Du kan kjøre denne klassen som vist tidligere, legge til en CD, og ​​alt skal fungere som forventet:

C:\javaxml2\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill" Legge til en CD med tittelen "Tony Rice" av Sugar Hills "Manzanita" Legger til en CD.

Jeg forlot klassemodifikasjonen CDLister for deg. Alt produseres etter samme mal. For å teste deg selv kan du se eksempelfilene for boken min, som allerede inneholder disse oppdaterte klassene.

Merk: Du kan bestemme det fordi klassen CDLister interagerer ikke direkte med objektet CD(returnert etter metode liste() typen betyr noe Hastbar), så trenger du ikke gjøre noen endringer. Imidlertid returnerte klassen Hastbar inneholder objektforekomster CD. Hvis SOAP ikke vet hvordan de skal deserialiseres, vil klienten gi en feilmelding. I dette tilfellet må du spesifisere i objektet for å løse problemet Anrop kopiere SOAPMappingRegistry.

Effektiv feilhåndtering

Nå som du har sett tilpassede objekter og gjort RPC-anrop og slikt, la meg snakke om et mindre spennende emne: feilhåndtering. Med enhver nettverkstransaksjon kan mange feil oppstå. Tjenesten starter ikke, det er en feil på serveren, et objekt kan ikke bli funnet, klasser mangler og mange andre problemer. Så langt har jeg bare brukt metoden fault.getString()å generere feilmeldinger. Men denne metoden er kanskje ikke alltid nyttig. For å se det i aksjon, fjern kommentarer fra konstruktøren CDCatalog:

offentlig CDCatalog() ( //catalog = ny hashtabell(); // Lag en katalog addCD(ny CD("Nickel Creek", "Nickel Creek", "Sugar Hill")); addCD(ny CD("La det falle", "Sean Watkins", "Sugar Hill")); addCD(ny CD("Aerial Boundaries", "Michael Hedges", "Windham Hill")); addCD(ny CD("Taproot", "Michael Hedges", "Windham Hill")); )

Kompiler den på nytt, start servletmotoren på nytt og vert den på nytt. Dette vil resultere i et unntak NullPointerException når klassekonstruktøren prøver å legge til CD til uinitialisert Hastbar. Når du starter klienten, vises en feilmelding, men den vil ikke være veldig informativ:

(gandalf)/javaxml2/build$ java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcrouter Vis gjeldende CD-katalog. Feil: Kan ikke løse målobjekt: null

Dette er slett ikke informasjonen som kan hjelpe til med å identifisere og rette en feil. Likevel takler rammeverket feilhåndtering på riktig måte. Husker du DOMFaultListener, som du spesifiserte som verdien av elementet faultListener? Tiden er inne for ham å gå inn i spillet. Objekt returnert i tilfelle feil Feil inneholder DOM (Document Object Model) org.w3c.dom.Element med detaljert informasjon om feilen. Legg først til et importuttrykk i kildekoden java.util.Iterator:

importer java.net.URL; import java.util.Enumeration; import java.util.Hashtable; importer java.util.Iterator; import java.util.Vector; import org.apache.soap.konstanter; import org.apache.soap.Fault; import org.apache.soap.SOAPException; import org.apache.soap.encoding.SOAPMappingRegistry; import org.apache.soap.encoding.soapenc.BeanSerializer; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; import org.apache.soap.util.xml.QName;

La oss nå gjøre endringer for å håndtere feil i list()-metoden:

if (!response.generatedFault()) ( Parameter returnValue = response.getReturnValue(); Hashtable catalog = (Hashtable)returnValue.getValue(); Enumeration e = catalog.keys(); while (e.hasMoreElements()) ( String title = (String)e.nextElement(); CD cd = (CD)catalog.get(title System.out.println(" "" + cd.getTitle() + "" artist " + cd.getArtist() + " studios " + cd.getLabel()); else ( Fault fault = response.getFault(); System.out.println("Feil: " + fault.getFaultString()); Vektoroppføringer = fault.getDetailEntries(); for (Iterator i = entries.iterator(); i.hasNext();) ( org.w3c.dom.Element entry = (org.w3c.dom.Element)i.next(); System.out.println(entry .getFirstChild().getNodeValue());

Bruker metode getDetailEntries() du får tilgang til SOAP-tjenesten og rådataserveren som støtter problemet. Koden behandler dem på nytt (vanligvis er det bare ett element, men det krever nøye oppmerksomhet) og avskjærer DOM-en Element, inneholdt i hver oppføring. Her er i hovedsak XML-en du jobber med:

SOAP-ENV:Server.BadTargetObjectURI Kan ikke løse mål: null Dette er hva vi ønsker!

Med andre ord, Fault-objektet gir deg tilgang til den delen av SOAP-konvolutten som inneholder feil. I tillegg gir Apache SOAP en Java-stakksporing når feil oppstår, og gir den detaljerte informasjonen som trengs for å rette dem. Å avskjære et element stackTrace og skrive ut nodeverdien Tekst fra dette elementet kan klienten skrive ut serverstabelsporingen. Ved å kompilere disse endringene og starte klienten på nytt vil du få følgende resultat:

C:\javaxml2\build>java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcr ytre Vis gjeldende CD-katalog. Feil: Kan ikke løse mål: null java.lang.NullPointerException i javaxml2.CDCatalog.addCD(CDCatalog.java:24) i javaxml2.CDCatalog. (CDCatalog.java:14) i java.lang.Class.newInstance0(Native Method) i java.lang.Class.newInstance(Class.java:237)

Det er ikke mye bedre, men du kan i det minste se litt informasjon om at et unntak har skjedd NullPointerException og til og med finne ut linjenumrene i serverklassene der dette problemet oppsto. Resultatet av disse nylige endringene har gitt deg et klart bilde av feilhåndteringsproblemet. Du bør nå sjekke serverklassene dine for feil. Ja, jeg glemte nesten, før det ikke glem å bytte klasse tilbake CDCatalog for å bli kvitt feilene vi med vilje introduserte for klarhet!

  1. Det er mye snakk om å kjøre SOAP over andre protokoller som SMTP (eller til og med Jabber). SOAP-standarden gir foreløpig ikke dette, men lignende funksjoner kan bli lagt til i fremtiden. Bli derfor ikke overrasket om du møter aktive diskusjoner om dette emnet.
  • Opplæringen

Hei alle sammen!
Det skjedde slik at jeg nylig begynte å utvikle webtjenester. Men i dag handler ikke temaet om meg, men om hvordan vi kan skrive vår egen XML Web Service basert på SOAP 1.2-protokollen.

Jeg håper at etter å ha lest emnet vil du kunne:

  • skrive din egen serverimplementering av en webapplikasjon;
  • skrive din egen klientimplementering av en webapplikasjon;
  • skrive din egen webtjenestebeskrivelse (WSDL);
  • sende klientmatrisene med samme type data til serveren.
Som du kanskje har gjettet, vil all magien gjøres ved hjelp av PHP og de innebygde SoapClient- og SoapServer-klassene. Vår kanin skal være en tjeneste for å sende SMS-meldinger.

1 Problemstilling

1.1 Grenser

I begynnelsen foreslår jeg å ta for oss resultatet som vi vil oppnå på slutten av emnet. Som annonsert ovenfor vil vi skrive en tjeneste for sending av SMS-meldinger, og mer presist vil vi motta meldinger fra forskjellige kilder via SOAP-protokollen. Deretter vil vi vurdere i hvilken form de kommer til serveren. Prosessen med å sette meldinger i kø for videre sending til leverandøren, er dessverre utenfor rammen av dette innlegget av mange grunner.

1.2 Hvilke data vil vi endre?

Flott, vi har bestemt oss for grensene! Det neste trinnet som må tas er å bestemme hvilke data vi skal utveksle mellom serveren og klienten. Om dette emnet foreslår jeg å ikke dele hår for lenge og umiddelbart svare på hovedspørsmålene for deg selv:
  • Hvilke minimumsdata må sendes til serveren for å sende en SMS-melding til en abonnent?
  • Hvilke minimumsdata må sendes fra serveren for å tilfredsstille kundens behov?
Noe sier meg at for dette må du sende følgende:
  • mobilnummer og
  • teksten til SMS-meldingen.
I prinsippet er disse to egenskapene nok til å sende, men jeg ser umiddelbart for meg at en SMS med bursdagshilsener kommer til deg klokken 3 om morgenen, eller 4! I dette øyeblikket vil jeg være veldig takknemlig for alle som ikke har glemt meg! Derfor vil vi også sende til serveren og
  • dato for sending av SMS-meldingen.
Det neste jeg vil sende til serveren er:
  • Meldingstype.
Denne parameteren er ikke obligatorisk, men den kan være veldig nyttig for oss hvis vi raskt trenger å fortelle sjefen hvor mange av kundene våre vi har "fornøyd" med nyhetene våre, og også trekke noen vakre statistikker om denne saken.

Og likevel har jeg glemt noe! Hvis vi reflekterer litt mer, er det verdt å merke seg at klienten kan sende enten én SMS-melding eller flere av dem til serveren om gangen. Med andre ord kan én datapakke inneholde fra én til uendelig meldinger.

Som et resultat får vi at for å sende en SMS-melding trenger vi følgende data:

  • Mobiltelefonnummer,
  • SMS-melding tekst,
  • tidspunkt for sending av SMS-meldingen til abonnenten,
  • meldingstype.

Vi har svart på det første spørsmålet, nå må vi svare på det andre spørsmålet. Og kanskje jeg tillater meg selv å rote litt. Derfor sender vi bare boolske data fra serveren, hvis betydning har følgende betydning:

  • TRUE – pakken nådde serveren, passerte autentisering og satt i kø for sending til SMS-leverandøren
  • FALSE – i alle andre tilfeller

Dette avslutter beskrivelsen av problemstillingen! Og til slutt, la oss komme ned til den morsomme delen - la oss finne ut hva slags merkelig beist denne SOAP er!

2 Hva er SOAP?

Generelt planla jeg i utgangspunktet ikke å skrive noe om hva SOAP er og ønsket å begrense meg til lenker til nettstedet w3.org med nødvendige spesifikasjoner, samt lenker til Wikipedia. Men helt til slutt bestemte jeg meg for å skrive et kort notat om denne protokollen.

Og jeg vil begynne min historie med det faktum at denne datautvekslingsprotokollen tilhører en undergruppe av protokoller basert på det såkalte RPC (Remote Procedure Call) paradigmet, hvis antipode er REST (Representational State Transfer). Du kan lese mer om dette på Wikipedia lenker til artikler er helt på slutten av emnet. Fra disse artiklene må vi forstå følgende: "RPC-tilnærmingen tillater bruk av et lite antall nettverksressurser med et stort antall metoder og en kompleks protokoll. Med REST-tilnærmingen er antall metoder og protokollkompleksitet strengt begrenset, noe som betyr at antallet individuelle ressurser kan være stort." Det vil si at i forhold til oss betyr dette at i tilfelle av RPC-tilnærmingen på siden vil det alltid være én inngang (lenke) til tjenesten og hvilken prosedyre man skal ringe for å behandle innkommende data vi overfører sammen med dataene, mens med REST-tilnærmingen i vår Siden har mange innganger (lenker), som hver aksepterer og behandler kun visse data. Hvis noen som leser vet hvordan de skal forklare forskjellen i disse tilnærmingene enda enklere, må du huske å skrive i kommentarene!

Det neste vi trenger å vite om SOAP er at denne protokollen bruker samme XML som en transport, noe som på den ene siden er veldig bra, fordi Vårt arsenal inkluderer umiddelbart den fulle kraften til en stabel med teknologier basert på dette markup-språket, nemlig XML-Schema - et språk for å beskrive strukturen til et XML-dokument (takk Wikipedia!), som muliggjør automatisk validering av data mottatt av serveren fra klienter.

Og så, nå vet vi at SOAP er en protokoll som brukes til å implementere eksterne prosedyrekall, og den bruker XML som transport! Hvis du leser artikkelen på Wikipedia, kan du også lære derfra at den kan brukes over alle protokoller på applikasjonsnivå, og ikke bare i kombinasjon med HTTP (dessverre vil vi i dette emnet kun vurdere SOAP over HTTP). Og vet du hva jeg liker best med alt dette? Hvis det ikke er noen gjetninger, så gir jeg et hint - SOAP!... Fortsatt ingen gjetninger?... Er du sikker på at du har lest artikkelen på Wikipedia?... Generelt sett vil jeg ikke torturere deg videre. Derfor går jeg rett til svaret: "SOAP (fra den engelske Simple Object Access Protocol - enkel protokoll tilgang til gjenstander; opp til spesifikasjon 1.2)". Det mest bemerkelsesverdige med denne linjen er i kursiv! Jeg vet ikke hvilke konklusjoner du trakk fra alt dette, men jeg ser følgende - siden denne protokollen ikke på noen måte kan kalles "enkel" (og tilsynelatende til og med w3 er enig i dette), så sluttet den fra versjon 1.2 å bli dekryptert på en eller annen måte ! Og det ble kjent som SOAP, bare SOAP, punktum.

Vel, ok, unnskyld meg, jeg ble litt på sidespor. Som jeg skrev tidligere, brukes XML som transport, og pakkene som går mellom klienten og serveren kalles SOAP-konvolutter. Hvis du vurderer den generelle strukturen til konvolutten, vil den virke veldig kjent for deg, fordi... ligner strukturen til en HTML-side. Den har en hoveddel - Konvolutt, som inkluderer seksjoner Overskrift Og Kropp, eller Feil. I Kropp data overføres og det er en obligatorisk del av konvolutten, mens Overskrift er valgfritt. I Overskrift autorisasjon eller andre data som ikke er direkte relatert til inndataene til nettjenesteprosedyrene kan overføres. Om Feil det er ikke noe spesielt å fortelle, bortsett fra at det kommer til klienten fra serveren i tilfelle feil.

Det er her min anmeldelseshistorie om SOAP-protokollen slutter (vi vil se på selve konvoluttene og strukturen deres mer detaljert når klienten og serveren vår endelig lærer å kjøre dem på hverandre) og en ny begynner - om SOAP-ledsageren kalt WSDL(Web Services Description Language). Ja, ja, dette er nettopp det som skremmer de fleste av oss fra å prøve å implementere API-en vår på denne protokollen. Som et resultat finner vi vanligvis opp hjulet vårt på nytt med JSON som transport. Så hva er WSDL? WSDL er et språk for å beskrive nettjenester og få tilgang til dem, basert på XML-språket (c) Wikipedia. Hvis denne definisjonen ikke tydeliggjør hele den hellige betydningen av denne teknologien, vil jeg prøve å beskrive den med mine egne ord!

WSDL er designet for å tillate våre klienter å kommunisere normalt med serveren. For å gjøre dette beskriver filen med filtypen "*.wsdl" følgende informasjon:

  • Hvilke navneområder ble brukt?
  • Hvilke dataskjemaer ble brukt?
  • Hvilke typer meldinger forventer netttjenesten fra klienter?
  • Hvilke data tilhører hvilke nettjenesteprosedyrer,
  • Hvilke prosedyrer inneholder nettjenesten?
  • Hvordan skal klienten ringe netttjenesteprosedyrene,
  • Hvilken adresse skal kundeanrop sendes til?
Som du kan se, er denne filen hele webtjenesten. Ved å spesifisere adressen til WSDL-filen i klienten, vil vi vite alt om enhver webtjeneste! Som et resultat trenger vi ikke å vite absolutt ingenting om hvor selve webtjenesten befinner seg. Alt du trenger å vite er plasseringen av WSDL-filen! Vi vil snart finne ut at SOAP ikke er så skummelt som russiske ordtak gjør det til.

3 Introduksjon til XML-skjema

Nå vet vi mye om hva SOAP er, hva som er inne i den, og har oversikt over teknologistabelen som omgir den. Siden SOAP først og fremst er en metode for interaksjon mellom en klient og en server, og XML-markeringsspråk brukes som transport for det, vil vi i denne delen forstå litt om hvordan automatisk datavalidering skjer ved bruk av XML-skjemaer.

Hovedoppgaven til diagrammet er å beskrive strukturen til dataene vi skal behandle. Alle data i XML-skjemaer er delt inn i enkel(skalær) og kompleks(strukturer) typer. Enkle typer inkluderer følgende typer:

  • linje,
  • Antall,
  • boolsk verdi,
  • dato.
Noe veldig enkelt som ikke har noen utvidelser inni. Deres antipode er komplekse komplekse typer. Det enkleste eksemplet på en kompleks type som kommer til alle, er objekter. For eksempel en bok. Boken består av egenskaper: forfatter, Navn, pris, ISBN-nummer etc. Og disse egenskapene kan på sin side enten være enkle typer eller komplekse. Og XML-skjemaets oppgave er å beskrive dette.

Jeg foreslår at du ikke går langt og skriver et XML-skjema for SMS-meldingen vår! Nedenfor er xml-beskrivelsen av SMS-meldingen:

71239876543 Testmelding 2013-07-20T12:00:00 12
Vårt komplekse typediagram vil se slik ut:


Denne oppføringen lyder som følger: Vi har en variabel " beskjed"skriv" Beskjed" og det er en kompleks type kalt " Beskjed", som består av et sekvensielt sett med elementer" telefon"type streng, « tekst"type streng, « Dato"type dato tid, « type"type desimal. Disse typene er enkle og er allerede definert i skjemabeskrivelsen. Gratulerer! Vi har nettopp skrevet vårt første XML-skjema!

Jeg tror at betydningen av elementene " element"Og" kompleksType"Alt har blitt mer eller mindre klart for deg, så vi vil ikke fokusere på dem mer og la oss bytte rett til komponistelementet" sekvens" Når vi bruker komponistelementet " sekvens"Vi informerer deg om at elementene som er inkludert i den alltid må være plassert i den sekvensen som er spesifisert i diagrammet, og alle er obligatoriske. Men fortvil ikke! Det er ytterligere to komponistelementer i XML-skjemaer: " valg"Og" alle" Komponist" valg" kunngjør at det må være ett av elementene som er oppført i den, og komponisten " alle» – enhver kombinasjon av de oppførte elementene.

Som du husker, i den første delen av emnet ble vi enige om at fra en til uendelig kan SMS-meldinger overføres i en pakke. Derfor foreslår jeg å forstå hvordan slike data er deklarert i XML-skjemaet. Den generelle pakkestrukturen kan se slik ut:

71239876543 Testmelding 1 2013-07-20T12:00:00 12 71239876543 Testmelding N 2013-07-20T12:00:00 12
Diagrammet for en så kompleks type vil se slik ut:


Den første blokken inneholder den kjente erklæringen av den komplekse typen " Beskjed" Hvis du la merke til, så i hver enkel type inkludert i " Beskjed", nye klargjørende attributter er lagt til" minForekommer"Og" maxForekommer" Som du kanskje gjetter ut fra navnet, den første ( minForekommer) indikerer at denne sekvensen må inneholde minst ett element av typen " telefon», « tekst», « Dato"Og" type", mens den neste ( maxForekommer) attribute erklærer for oss at det er høyst ett slikt element i sekvensen vår. Som et resultat, når vi skriver våre egne skjemaer for data, får vi det bredeste valget når det gjelder hvordan de skal konfigureres!

Den andre blokken i diagrammet erklærer elementet " meldingsliste"skriv" Meldingsliste" Det er klart at " Meldingsliste" er en kompleks type som inneholder minst ett element " beskjed", men det maksimale antallet slike elementer er ikke begrenset!

4 Skriv din WSDL

Husker du at WSDL er vår nettjeneste? Jeg håper du husker! Mens vi skriver det, vil vår lille nettjeneste kjøre på den. Derfor foreslår jeg å ikke rote rundt.

Generelt, for at alt skal fungere riktig for oss, må vi overføre en WSDL-fil med riktig MIME-type til klienten. For å gjøre dette, må du konfigurere webserveren din tilsvarende, nemlig angi MIME-typen for filer med «*.wsdl»-utvidelsen til følgende linje:

Application/wsdl+xml
Men i praksis sendte jeg vanligvis HTTP-headeren via PHP " tekst/xml»:

Header("Content-Type: text/xml; charset=utf-8");
og alt fungerte utmerket!

Jeg vil med en gang advare deg om at vår enkle nettjeneste vil ha en ganske imponerende beskrivelse, så ikke vær redd, fordi... Det meste av teksten er obligatorisk vann, og etter å ha skrevet den en gang, kan du hele tiden kopiere den fra en nettjeneste til en annen!

Siden WSDL er XML, må du skrive om dette direkte på den aller første linjen. Rotelementet til filen skal alltid hete " definisjoner»:


Vanligvis består WSDL av 4-5 hovedblokker. Den aller første blokken er definisjonen av en webtjeneste eller med andre ord inngangspunktet.


Det står her at vi har en tjeneste som heter - " SmsService" I prinsippet kan alle navnene i WSDL-filen endres av deg til hva du vil, pga de spiller absolutt ingen rolle.

Etter dette kunngjør vi at i vår nettjeneste " SmsService" det er et inngangspunkt ("port") kalt " SmsServicePort" Det er til dette inngangspunktet at alle forespørsler fra klienter til serveren vil bli sendt. Og angi i elementet " adresse» lenke til behandlerfilen som godtar forespørsler.

Når vi har definert webtjenesten og angitt inngangspunktet for den, må vi binde støttede prosedyrer til den:


For å gjøre dette, viser den hvilke operasjoner og i hvilken form de vil bli kalt. De. for port" SmsServicePort"en binding er definert under navnet" SmsServiceBinding", som har en anropstype" rpc"og HTTP brukes som overføringsprotokoll. Derfor indikerte vi her at vi vil foreta et RPC-kall over HTTP. Etter dette beskriver vi hvilke prosedyrer ( operasjon) støttes i nettjenesten. Vi støtter kun én prosedyre – " Send tekstmelding" Gjennom denne prosedyren vil våre fantastiske meldinger bli sendt til serveren! Etter at prosedyren er erklært, er det nødvendig å indikere i hvilken form dataene vil bli overført. I dette tilfellet er det indikert at standard SOAP-konvolutter vil bli brukt.

Etter det må vi binde prosedyren til meldinger:


For å gjøre dette spesifiserer vi at bindingen vår er av typen " SmsServicePortType"og i elementet" portType"med navnet av samme type indikerer vi bindingen av prosedyrer til meldinger. Og så vil den innkommende meldingen (fra klient til server) bli kalt " sendSmsRequest", og utgående (fra server til klient) " sendSmsResponse" Som alle navn i WSDL, er navnene på innkommende og utgående meldinger vilkårlige.

Nå må vi beskrive selve meldingene, dvs. innkommende og utgående:


For å gjøre dette legger vi til elementene " beskjed"med navn" sendSmsRequest"Og" sendSmsResponse"henholdsvis. I dem indikerer vi at inngangen skal være en konvolutt hvis struktur tilsvarer datatypen " Be om" Deretter returneres en konvolutt fra serveren som inneholder datatypen - " Respons».

Nå må vi bare gjøre litt - legg til en beskrivelse av disse typene til WSDL-filen vår! Og hvordan tror du WSDL beskriver innkommende og utgående data? Jeg tror at du allerede har forstått alt for lenge siden og fortalt deg selv at du bruker XML-skjemaer! Og du vil ha helt rett!


Du kan gratulere oss! Vår første WSDL er skrevet! Og vi er et skritt nærmere å nå målet vårt.
Deretter skal vi se på hva PHP gir oss for å utvikle våre egne distribuerte applikasjoner.

5 Vår første SOAP-server

Tidligere skrev jeg at for å lage en SOAP-server i PHP vil vi bruke den innebygde SoapServer-klassen. For at alle videre handlinger skal skje på samme måte som for meg, må du justere PHP-en din litt. For å være enda mer presis, må du sørge for at du har "php-soap"-utvidelsen installert. Det er best å lese hvordan du installerer det på webserveren din på det offisielle PHP-nettstedet (se listen over referanser).

Etter at alt er installert og konfigurert, må vi opprette en fil i rotmappen til hostingen din " smsservice.php» med følgende innhold:

setClass("SoapSmsGateWay"); //Start serveren $server->handle();
Jeg håper det ikke er nødvendig å forklare hva som er over linjen med "ini_set"-funksjonen. Fordi der bestemmes det hvilke HTTP-hoder vi skal sende fra serveren til klienten og miljøet er konfigurert. I linjen med "ini_set" deaktiverer vi caching av WSDL-filen slik at endringene våre i den umiddelbart trer i kraft på klienten.

Nå kommer vi til serveren! Som du kan se, tar hele SOAP-serveren bare tre linjer! På den første linjen oppretter vi en ny forekomst av SoapServer-objektet og sender adressen til vår WSDL-beskrivelse av webtjenesten til konstruktøren. Nå vet vi at den vil ligge i roten til hostingen i en fil med det selvforklarende navnet " smsservice.wsdl.php" I den andre linjen forteller vi SOAP-serveren hvilken klasse som må trekkes for å behandle konvolutten mottatt fra klienten og returnere konvolutten med svaret. Som du kanskje har gjettet, er det i denne klassen vår eneste metode vil bli beskrevet Send tekstmelding. På tredje linje starter vi serveren! Det er det, serveren vår er klar! Som jeg gratulerer oss alle med!

Nå må vi lage WSDL-filen. For å gjøre dette kan du enten kopiere innholdet fra forrige seksjon, eller ta deg friheter og "mal" det litt:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
På dette stadiet bør vi være helt fornøyd med den resulterende serveren, fordi Vi kan logge konvoluttene som kommer til den og deretter rolig analysere innkommende data. For at vi skal motta noe på serveren trenger vi en klient. Så la oss komme til det!

6 SOAP-klient på vei

Først av alt må vi lage en fil der vi skal skrive klienten. Som vanlig vil vi lage den i roten til verten og kalle den " klient.php", og inne vil vi skrive følgende:

meldingsliste = ny meldingsliste(); $req->messageList->message = ny melding(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Testmelding 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->message->type = 15; $client = new SoapClient("http://($_SERVER["HTTP_HOST")/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));
La oss beskrive objektene våre. Da vi skrev WSDL, beskrev den tre enheter for konvolutten som kommer inn til serveren: Be om, Meldingsliste Og Beskjed. Følgelig klasser Be om, Meldingsliste Og Beskjed er refleksjoner av disse enhetene i vårt PHP-skript.

Når vi har definert objektene, må vi lage et objekt ( $req), som vi sender til serveren. Deretter kommer de to mest kjære linjene for oss! Vår SOAP-klient! Tro det eller ei, dette er nok til at serveren vår begynner å motta meldinger fra klienten, så vel som at serveren vår skal kunne motta og behandle dem! I den første av dem oppretter vi en forekomst av SoapClient-klassen og sender adressen til plasseringen av WSDL-filen til konstruktøren, og i parametrene indikerer vi eksplisitt at vi vil bruke SOAP-protokollen versjon 1.2. På neste linje kaller vi metoden Send tekstmelding gjenstand $klient og umiddelbart vise resultatet i nettleseren.
La oss kjøre den og se hva vi endelig har fått!

Følgende objekt ble returnert til meg fra serveren:

Object(stdClass) public "status" => boolsk sann
Og dette er flott, fordi... Nå vet vi med sikkerhet at serveren vår fungerer og ikke bare fungerer, men kan også returnere noen verdier til klienten!

La oss nå se på loggen som vi holder på serversiden! I den første delen ser vi rådataene som ankom serveren:

79871234567 Testmelding 1 2013-07-21T15:00:00.26 15
Dette er konvolutten. Nå vet du hvordan det ser ut! Men det er usannsynlig at vi vil være interessert i å se på det hele tiden, så la oss deserialisere objektet fra loggfilen og se om alt er bra:

Object(stdClass) public "messageList" => objekt(stdClass) public "message" => objekt(stdClass) public "phone" => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 1 " (lengde=37) offentlig "date" => streng "2013-07-21T15:00:00.26" (lengde=22) offentlig "type" => streng "15" (lengde=2)
Som du kan se, ble objektet deserialisert riktig, noe jeg vil gratulere oss alle for! Noe mer interessant venter oss neste gang! Vi vil nemlig sende klienten til serveren ikke bare én SMS-melding, men en hel pakke (for å være mer presis, tre)!

7 Sende komplekse objekter

La oss tenke på hvordan vi kan overføre en hel haug med meldinger til serveren i en pakke? Sannsynligvis den enkleste måten ville være å organisere en matrise inne i messageList-elementet! La oss gjøre dette:

// opprett et objekt som skal sendes til serveren $req = new Request(); $req->messageList = ny meldingsliste(); $msg1 = ny melding(); $msg1->phone = "79871234567"; $msg1->text = "Testmelding 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = ny melding(); $msg2->phone = "79871234567"; $msg2->text = "Testmelding 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = ny melding(); $msg3->phone = "79871234567"; $msg3->text = "Testmelding 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;
Loggene våre indikerer at følgende pakke ble mottatt fra klienten:

79871234567 Testmelding 1 2013-07-21T15:00:00.26 15 79871234567 Testmelding 2 2014-08-22T16:01:10 16 79871234567 Testmelding 3 2014-08-22T16:01:10 17
Hvilket tull, sier du? Og du vil ha rett på en måte, fordi... Så snart vi fikk vite at et objekt forlot klienten, kom det til serveren vår i absolutt samme form i form av en konvolutt. Riktignok ble ikke SMS-meldinger serialisert i XML på den måten vi trengte - de måtte pakkes inn i elementer beskjed, ikke i Struktur. La oss nå se i hvilken form et slikt objekt kommer til metoden Send tekstmelding:

Object(stdClass) public "messageList" => object(stdClass) public "message" => objekt(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 1" (lengde=37) offentlig "dato" => streng "2013-07-21T15:00:00.26" (lengde=22) offentlig " type" => streng "15" (lengde=2) 1 => objekt(stdClass) public "phone" => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 2" (lengde= 37) offentlig "dato" => streng "2014-08-22T16:01:10" (lengde=19) offentlig "type" => streng "16" (lengde=2) 2 => objekt(stdClass) offentlig "telefon " => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 3" (lengde=37) offentlig "dato" => streng "2014-08-22T16:01:10" (lengde= 19) offentlig "type" => streng "17" (lengde=2)
Hva gir denne kunnskapen oss? Bare at banen vi valgte ikke er riktig, og vi fikk ikke svar på spørsmålet - "Hvordan kan vi få riktig datastruktur på serveren?" Men jeg foreslår at du ikke fortviler og prøver å konvertere vårt utvalg til typen en gjenstand:

$req->messageList->message = (objekt)$req->messageList->melding;
I dette tilfellet vil vi motta en ny konvolutt:

79871234567 Testmelding 1 2013-07-21T15:00:00.26 15 79871234567 Testmelding 2 2014-08-22T16:01:10 16 79871234567 Testmelding 3 2014-08-22T16:01:10 17
Kom inn i metoden Send tekstmelding objektet har følgende struktur:

Object(stdClass) public "messageList" => object(stdClass) public "message" => objekt(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 1" (lengde=37) offentlig "dato" => streng "2013-07-21T15:00:00.26" (lengde=22) offentlig " type" => streng "15" (lengde=2) 1 => objekt(stdClass) public "phone" => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 2" (lengde= 37) offentlig "dato" => streng "2014-08-22T16:01:10" (lengde=19) offentlig "type" => streng "16" (lengde=2) 2 => objekt(stdClass) offentlig "telefon " => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 3" (lengde=37) offentlig "dato" => streng "2014-08-22T16:01:10" (lengde= 19) offentlig "type" => streng "17" (lengde=2)
Når det gjelder meg, "summer ikke summen av å endre plassering av vilkårene" (c). Hva TULL, Hva Struktur– vi har ennå ikke nådd målet vårt! Og for å oppnå det, må vi sørge for at i stedet for disse uforståelige navnene vises vårt opprinnelige navn beskjed. Men forfatteren vet ennå ikke hvordan han skal oppnå dette. Derfor er det eneste vi kan gjøre å kvitte oss med den ekstra beholderen. Med andre ord skal vi nå sørge for at i stedet for beskjed ble til TULL! For å gjøre dette, endre objektet som følger:

// opprett et objekt som skal sendes til serveren $req = new Request(); $msg1 = ny melding(); $msg1->phone = "79871234567"; $msg1->text = "Testmelding 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = ny melding(); $msg2->phone = "79871234567"; $msg2->text = "Testmelding 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = ny melding(); $msg3->phone = "79871234567"; $msg3->text = "Testmelding 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (objekt)$req->messageList;
Hva om vi er heldige og det riktige navnet kommer opp fra diagrammet? For å gjøre dette, la oss se på konvolutten som kom:

79871234567 Testmelding 1 2013-07-21T15:00:00.26 15 79871234567 Testmelding 2 2014-08-22T16:01:10 16 79871234567 Testmelding 3 2014-08-22T16:01:10 17
Ja, et mirakel skjedde ikke! TULL– vi vinner ikke! Kom til Send tekstmelding objektet i dette tilfellet vil se slik ut:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => streng "Testmelding 1" (lengde=37) offentlig "dato" => streng "2013-07-21T15:00:00.26" (lengde=22) offentlig "type" => streng "15" (lengde =2) 1 => objekt(stdClass) offentlig "telefon" => streng "79871234567" (lengde=11) offentlig "tekst" => streng "Testmelding 2" (lengde=37) offentlig "dato" => streng " 2014-08-22T16:01:10" (lengde=19) offentlig "type" => streng "16" (lengde=2) 2 => objekt(stdClass) offentlig "telefon" => streng "79871234567" (lengde= 11) offentlig "tekst" => streng "Testmelding 3" (lengde=37) offentlig "dato" => streng "2014-08-22T16:01:10" (lengde=19) offentlig "type" => streng " 17" (lengde=2)
Som de sier - "Nesten"! På dette (litt triste) notatet foreslår jeg å sakte avslutte ting og trekke noen konklusjoner for oss selv.

8 Konklusjon

Endelig kom vi hit! La oss finne ut hva du kan gjøre nå:
  • du kan skrive WSDL-filen som er nødvendig for webtjenesten din;
  • du kan enkelt skrive din egen klient som kan kommunisere med serveren via SOAP;
  • du kan skrive din egen server som kommuniserer med omverdenen via SOAP;
  • du kan sende arrays av samme type objekter til serveren fra klienten din (med noen begrensninger).
Vi gjorde også noen funn under vår lille forskning:
  • den opprinnelige SoapClient-klassen serialiserer ikke datastrukturer av samme type korrekt i XML;
  • når du serialiserer en matrise til XML, oppretter den et ekstra element kalt Struktur;
  • når du serialiserer et objekt til XML, oppretter det et ekstra element kalt TULL;
  • TULL mindre ond enn Struktur på grunn av det faktum at konvolutten er mer kompakt (ekstra navneområder legges ikke til i XML-overskriften til konvolutten);
  • Dessverre validerer ikke SoapServer-klassen automatisk konvoluttdataene med vårt XML-skjema (kanskje andre servere gjør dette heller ikke).

Jeg skal ikke dvele ved spørsmålet om hva det er nettjenester og hvorfor de trengs. Det er mange artikler om dette emnet på Internett. Jeg skal bare prøve å kort vise hvor enkelt det er å lage en klient for en hvilken som helst nettjeneste i PHP.

Innstillinger

For bruk SÅPE i php må du koble til SOAP-modulen (inkludert i php5-distribusjonen). Under Windows gjøres dette enkelt - du må legge til (nemlig legg til, siden denne linjen ikke bare er kommentert der ute, den mangler helt) i php.ini:
extension=php_soap.dll

Ikke glem å restarte serveren hvis du har php installert som en modul.


Opprette en SOAP-klient fra et WSDL-dokument

Oppretting av en SOAP-klient skjer vanligvis ved WSDL-dokument, som er et XML-dokument i et spesifikt format som fullt ut beskriver en bestemt nettjeneste. For detaljer om WSDL henviser jeg deg til W3C-konsortiets nettsted - http://www.w3.org/TR/2005/WD-wsdl20-soap11-binding-20050510/.

Det viktigste du trenger å vite for å bygge en klient for en webtjeneste er å kjenne URL-en til WSDL-dokumentet.
La oss for eksempel ta netttjenesten "Currency Exchange Rate" fra xmethods.com. Adressen til denne nettjenesten, som lar deg motta valutakurser online, er http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl.

Det andre viktige poenget er at fra beskrivelsen av nettjenesten er det nødvendig å få informasjon om hvilke metoder denne tjenesten gir, og hvilke parametere vi skal sende til den som inngangsverdier (svært likt å kalle en vanlig PHP-funksjon eller klasse) metode). Vanligvis finnes denne informasjonen i beskrivelsen av tjenesten på nettstedet. Vår nettjeneste for å få valutakurser gir metoden getRate(), som valutakoder sendes til som argumenter.

Og til slutt er det viktig å vite hva du kan forvente som svar: hvor mange verdier, hvilken type osv. Dette kan også hentes fra beskrivelsen.
Og som et resultat viser koden seg å være veldig enkel og kompakt, nesten elementær:

// Bruke webtjenesten
// "Currency Exchange Rate" fra xmethods.com

// Opprette en SOAP-klient fra et WSDL-dokument
$client = new SoapClient("http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl");

// Send en SOAP-forespørsel og motta resultatet
$result = $client->getRate("oss", "russia");

Ekko 'Gjeldende dollarkurs: ', $resultat, ' rubler';
?>

Som du kan se av koden, må du sende URL-en til WSDL-dokumentet til SoapClient-klassekonstruktøren og motta et objekt for å jobbe med den ønskede webtjenesten. Deretter kalles en metode for dette objektet, hvis navn er det samme som navnet på selve webtjenestemetoden. Denne metoden returnerer resultatet vi ønsker.

Så dette enkle eksemplet illustrerer prinsippet om å bygge en SOAP-klient for webtjenester i PHP. Men i en ekte applikasjon er det fortsatt mye å ta vare på, spesielt det faktum at når nettjenesten kalles opp, kan den være midlertidig utilgjengelig eller returnere en feil. Det foreslår helt klart å bruke en blokk prøve/fange/kaste :)

Her på LeaseWeb jobber vi mye med SOAP web-tjenester for å integrere våre interne applikasjoner med hverandre. Spesielt under utvikling og testing av applikasjonene våre, da vi trenger evnen til å øve med SOAP API-er.

$ curl -sS http://leaseweb.github.io/php-soap-client/installer | php

Dette vil laste ned phar-filen til gjeldende arbeidskatalog og gjøre den kjørbar slik at du kan begynne å bruke den med en gang ved å påkalle:

$ ./soap_client

For å installere den nyeste masterversjonen kan du hente kildekoden direkte fra GitHub, pakke din egen .phar-fil og installere den - ved å bruke GNU Make.
For å kunne lage .phar-filen må du ha composer installert. For å lese mer om komponist, se deres utmerkede dokumentasjon.

# Installer php såpeklient $ git clone https://github.com/LeaseWeb/php-soap-client.git $ cd php-soap-client $ composer.phar install $ make $ sudo make install

Hvis du får et mislykket å kompilere phar-unntak mens du kjører, må du sette phar.readonly = Off i php.ini. På en utviklingsmaskin er dette greit å gjøre, men vær oppmerksom på sikkerhetsrisikoen når du setter phar.readonly til Av.

Ovennevnte make install-kommando vil installere soap_client-applikasjonen til /usr/local/bin og gjøre den kjørbar slik at du enkelt kan kalle den slik:

$ soap_client php-soap-client versjon 2.1.3 Bruk: kommando Alternativer: ... Tilgjengelige kommandoer: ring Ring fjerntjenesten med den spesifiserte `metoden` og skriv ut svaret til stdout. hjelp Viser hjelp for en kommandoliste Lister kommandoer liste-metoder Få en liste over tilgjengelige metoder for å ringe på fjernkontrollen. request Generer en xml-formatert SOAP-forespørsel for den gitte metoden og skriv ut til stdout. wsdl Få WSDL til en såpetjeneste.

Fra dette tidspunktet antar vi at du har installert soap_client.phar på systemet ditt i /usr/local/bin/soap_client og at katalogen /urs/local/bin er i $PATH .

La oss si at vi ønsker å se hvilke metoder som er tilgjengelige på den eksterne tjenesten http://www.webservicex.net/ConvertTemperature.asmx. Vi kan utstede følgende kommando:

$ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" listemetoder

Som vil gi ut følgende:

KonverterTemp

Hvis du kjører kommandoen ovenfor med alternativet -vvv, vil du få mer detaljert utdata.
I dette tilfellet er den eneste tilgjengelige metoden ConvertTemp . La oss se hvordan en SOAP XML-forespørsel ser ut for denne metoden:

$ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL"-forespørsel ConvertTemp 0

Hvis du vil lage en SOAP-forespørsel til ConvertTemp-metoden på den eksterne tjenesten, bruk call sub-kommandoen:

$ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" kall --editor ConvertTemp

Legg merke til --editor-alternativet etter anropsunderkommandoen. Hvis du bruker --editor-flagget vil soap_client åpne editoren spesifisert i miljøvariabelen $EDITOR slik at du kan endre forespørsels-XML før du sender den.

Hvis du sender den samme forespørselen flere ganger, kan du lagre en såpeforespørsel som en lokal XML-fil og sende den til /dev/stdin i kommandoen soap_client call:

# Få forespørselen xml og lagre den lokalt $ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" forespørsel ConvertTemp > my_sample_request.xml # Rediger nå my_sample_request.xml # Nå kan du ringe ConvertTemp-metoden med denne forhåndsforberedte forespørselen $ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" kaller ConvertTemp< my_sample_request.xml

Siden du vil gjenta soap_client-kommandoer ofte i løpet av kort tid mens du utforsker en ekstern nettjeneste, kan du spare deg selv for litt tid ved å sette en miljøvariabel SOAPCLIENT_ENDPOINT som inneholder URL-en til WSDL. Når denne miljøvariabelen er satt, kan du utelate kommandolinjealternativet --endpoint. La oss gjøre dette nå og kalle ConvertTemp-metoden:

$ eksport SOAPCLIENT_ENDPOINT="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" $ soap_client call ConvertTemp< my_sample_request.xml

Jeg ville vite hvor mye 107,6 grader Fahrenheit er i Celsius, så min my_sample_request.xml inneholder:

$ cat my_sample_request.xml 107.6 gradFahrenheit grader celsius

$ soap_client kalle ConvertTemp< my_sample_request.xml stdClass Object ( => 42)

Svaret er 42.

Hvis du heller ser svarene i XML-format, kan du bruke kommandolinjealternativet --xml:

$ soap_client kall --xml ConvertTemp< my_sample_request.xml 42

Denne opplæringen skal gi deg nok informasjon til å komme i gang med å utforske, teste og/eller utvikle SOAP API-er.
I et fremtidig blogginnlegg vil jeg fortsette temaet php-såpeklienten. Vi jobber for tiden med å pakke .phar-arkivet for nettet.

Lyrisk del.

Tenk deg at du har implementert eller implementerer et bestemt system som skal være tilgjengelig fra utsiden. De. det er en viss server du må kommunisere med. For eksempel en webserver.

Denne serveren kan utføre mange handlinger, jobbe med databasen, utføre noen tredjepartsforespørsler til andre servere, gjøre noen beregninger, etc. leve og muligens utvikle seg i henhold til scenarioet han kjenner til (dvs. i henhold til utviklerens scenario). Det er ikke interessant for en person å kommunisere med en slik server, fordi han kanskje ikke kan/vil gi vakre sider med bilder og annet brukervennlig innhold. Det er skrevet og fungerer for å fungere og gi data når det blir bedt om det, uten å bekymre deg for at det er lesbart for mennesker, klienten vil håndtere det selv.

Andre systemer som har tilgang til denne serveren, kan allerede disponere dataene som er mottatt fra denne serveren etter eget skjønn - behandle, akkumulere, utstede til sine klienter, etc.

Vel, et av alternativene for å kommunisere med slike servere er SOAP. SOAP xml meldingsutvekslingsprotokoll.

Praktisk del.

En webtjeneste (dette er navnet på hva serveren gir og hva klienter bruker) gjør det mulig å kommunisere med serveren med tydelig strukturerte meldinger. Faktum er at webtjenesten ikke godtar noen data. Netttjenesten vil svare med en feilmelding på meldinger som ikke er i samsvar med reglene. Feilen vil forresten også være i xml-form med en tydelig struktur (noe som ikke stemmer med teksten i meldingen).

WSDL (Web Services Description Language). Reglene som meldinger er komponert etter for nettjenesten er også beskrevet ved hjelp av xml og har også en klar struktur. De. Hvis en webtjeneste gir muligheten til å kalle en metode, må den tillate klienter å vite hvilke parametere som brukes for denne metoden. Hvis webtjenesten forventer en streng for Metode1 som en parameter og strengen skal hete Param1, vil disse reglene spesifiseres i webtjenestebeskrivelsen.

Ikke bare enkle typer, men også objekter og samlinger av objekter kan sendes som parametere. Beskrivelsen av et objekt kommer ned til en beskrivelse av hver komponent av objektet. Hvis et objekt består av flere felt, er hvert felt beskrevet, dets type, navn (hva er de mulige verdiene). Felt kan også være av en kompleks type, og så videre til beskrivelsen av typene avsluttes med enkle - streng, boolsk, tall, dato... Noen spesifikke typer kan imidlertid vise seg å være enkle, det er viktig at klienter kan forstå hvilke verdier de kan inneholde.

For klienter er det nok å kjenne url-en til nettjenesten; wsdl-en vil alltid være i nærheten, hvorfra du kan få en ide om metodene og deres parametere som denne nettjenesten gir.

Hva er fordelene med alle disse klokkene og fløyter:

  • I de fleste systemer skjer beskrivelsen av metoder og typer automatisk. De. programmereren på serveren trenger bare å si at denne metoden kan kalles gjennom en webtjeneste, og wsdl-beskrivelsen genereres automatisk.
  • Beskrivelsen, som har en tydelig struktur, kan leses av enhver såpeklient. De. uansett hva webtjenesten er, vil klienten forstå hvilke data webtjenesten mottar. Ved hjelp av denne beskrivelsen kan klienten bygge sin egen interne struktur av objektklasser, den såkalte. binding" og. Som et resultat må programmereren som bruker webtjenesten skrive noe sånt som (pseudokode):

    NewUser:=TSoapUser.Create("Vasya","Pupkin","admin"); soap.AddUser(NewUser);

  • Automatisk validering.

    • xml-validering. xml må være godt utformet. Ugyldig xml - umiddelbart en feil for klienten, la ham ordne opp i det.
    • skjemavalidering. xml må ha en viss struktur. xml samsvarer ikke med skjemaet - umiddelbart en feil til klienten, la ham ordne opp i det.
    • Dataverifisering utføres av såpeserveren slik at datatyper og begrensninger samsvarer med beskrivelsen.
  • Autorisasjon og autentisering kan implementeres ved hjelp av en egen metode. innfødt. eller bruke http-autorisasjon.
  • Webtjenester kan fungere både over såpeprotokollen og over http, det vil si gjennom get-forespørsler. Det vil si at hvis parametrene er enkle data (uten struktur), kan du ganske enkelt kalle den vanlige get www.site.com/users.asmx/GetUser?Name=Vasia eller post. Dette er imidlertid ikke overalt og ikke alltid.
  • ... se på Wikipedia

Det er også mange ulemper:

  • Urimelig stor meldingsstørrelse. Vel, her er selve naturen til xml slik at formatet er overflødig, jo flere tagger, jo mer ubrukelig informasjon. Pluss såpe legger til sin redundans. For intranettsystemer er problemet med trafikk mindre akutt enn for internett, så såpe for lokale nettverk er mer etterspurt, spesielt Sharepoint har en såpe-webtjeneste som du kan kommunisere med suksess (og noen begrensninger).
  • Automatisk endring av beskrivelsen av en webtjeneste kan ødelegge alle klienter. Vel, det er slik for ethvert system, hvis bakoverkompatibilitet med gamle metoder ikke støttes, vil alt falle av ...
  • Ikke et minus, men en ulempe. Alle metodekall må være atomære. Når vi for eksempel jobber med en database, kan vi starte en transaksjon, utføre flere spørringer og deretter rulle tilbake eller forplikte oss. Det er ingen transaksjoner i såpe. En forespørsel, ett svar, samtalen er over.
  • Å håndtere beskrivelsen av hva som er på serversiden (er alt beskrevet riktig?) og hva som er på klienten (hva beskrev de for meg her?) kan være ganske vanskelig. Det var flere ganger da jeg måtte forholde meg til klientsiden og overbevise serverprogrammereren om at dataene hans ble beskrevet feil, men han kunne ikke forstå noe om det i det hele tatt, for automatisk generering og det burde han ikke, det er et spørsmål om programvare. Og feilen lå naturligvis i metodekoden.
  • Praksis viser at webtjenesteutviklere er fryktelig langt unna de som bruker disse webtjenestene. Som svar på enhver forespørsel (gyldig fra utsiden), kan en uforståelig feil "Feil 5. Alt er dårlig" komme. Alt avhenger av utviklernes samvittighet :)
  • Jeg er sikker på at jeg fortsatt ikke husker noe...

Som et eksempel er det en åpen nettjeneste belavia:

  • http://86.57.245.235/TimeTable/Service.asmx - inngangspunkt, det er også en tekstbeskrivelse av metoder for tredjepartsutviklere.
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL - wsdl beskrivelse av metoder og typer mottatte og returnerte data.
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList - beskrivelse av en spesifikk metode med et eksempel på typen xml-forespørsel og xml-svar.

Du kan manuelt opprette og sende en forespørsel som:

POST /TimeTable/Service.asmx HTTP/1.1 Vert: 86.57.245.235 Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://webservices.belavia.by/GetAirportsList" ru

svaret kommer:

HTTP/1.1 200 OK Dato: Man, 30 Sep 2013 00:06:44 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Versjon: 4.0.30319 Cache-kontroll: privat, maks. -age=0 Content-Type: text/xml; charset=utf-8 Content-Length: 2940

PS Tidligere ble Aeroflot-netttjenesten åpnet, men etter at 1C la til såpestøtte til 8ku, installerte en haug med 1C-betatestere den. Nå har noe endret seg der (jeg vet ikke adressen, du kan slå den opp hvis du er interessert).
ZZY Ansvarsfraskrivelse. Han snakket på det daglige nivået. Du kan sparke.

visninger