java parameters - Wie auf Parameter in einer RESTful POST-Methode zugegriffen wird





body request (2)


Ihre @POST Methode sollte ein JSON-Objekt anstelle einer Zeichenfolge akzeptieren. Jersey verwendet JAXB, um das Marshaling und das Unmarshalling von JSON-Objekten zu unterstützen ( Details finden Sie in der Trikot-Dokumentation ). Erstellen Sie eine Klasse wie:

@XmlRootElement
public class MyJaxBean {
    @XmlElement public String param1;
    @XmlElement public String param2;
}

Dann würde Ihre @POST Methode wie folgt aussehen:

@POST @Consumes("application/json")
@Path("/create")
public void create(final MyJaxBean input) {
    System.out.println("param1 = " + input.param1);
    System.out.println("param2 = " + input.param2);
}

Diese Methode erwartet, dass ein JSON-Objekt als Hauptteil des HTTP-POST empfangen wird. JAX-RS übergibt den Inhalt der HTTP-Nachricht als unannotated Parameter - input in diesem Fall. Die eigentliche Nachricht würde etwa so aussehen:

POST /create HTTP/1.1
Content-Type: application/json
Content-Length: 35
Host: www.example.com

{"param1":"hello","param2":"world"}

Die Verwendung von JSON auf diese Weise ist aus naheliegenden Gründen durchaus üblich. Wenn Sie es jedoch in etwas anderem als JavaScript generieren oder konsumieren, müssen Sie vorsichtig sein, um die Daten ordnungsgemäß zu entschlüsseln. In JAX-RS würden Sie einen MessageBodyReader und MessageBodyWriter , um dies zu implementieren. Ich glaube, dass Jersey bereits Implementierungen für die erforderlichen Typen (z. B. Java-Primitive und JAXB-Wrapped-Klassen) sowie für JSON hat. JAX-RS unterstützt eine Reihe anderer Methoden zur Datenübergabe. Diese erfordern nicht die Erstellung einer neuen Klasse, da die Daten mit einfacher Argumentübergabe übergeben werden.

HTML <FORM>

Die Parameter würden mit @FormParam kommentiert:

@POST
@Path("/create")
public void create(@FormParam("param1") String param1,
                   @FormParam("param2") String param2) {
    ...
}

Der Browser wird das Formular mit "application/x-www-form-urlencoded" . Die JAX-RS-Laufzeit wird dafür sorgen, dass der Körper dekodiert und an die Methode übergeben wird. Hier ist, was Sie auf dem Draht sehen sollten:

POST /create HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 25

param1=hello&param2=world

Der Inhalt ist in diesem Fall URL-codiert .

Wenn Sie die Namen der FormParam nicht kennen, können Sie Folgendes tun:

@POST @Consumes("application/x-www-form-urlencoded")
@Path("/create")
public void create(final MultivaluedMap<String, String> formParams) {
    ...
}

HTTP-Header

Sie können die Annotation @HeaderParam wenn Sie Parameter über HTTP-Header übergeben möchten:

@POST
@Path("/create")
public void create(@HeaderParam("param1") String param1,
                   @HeaderParam("param2") String param2) {
    ...
}

So würde die HTTP-Nachricht aussehen. Beachten Sie, dass dieser POST keinen Body hat.

POST /create HTTP/1.1
Content-Length: 0
Host: www.example.com
param1: hello
param2: world

Ich würde diese Methode nicht für die verallgemeinerte Parameterübergabe verwenden. Es ist wirklich praktisch, wenn Sie auf den Wert eines bestimmten HTTP-Headers zugreifen müssen.

HTTP-Abfrageparameter

Diese Methode wird hauptsächlich für HTTP-GETs verwendet, gilt jedoch gleichermaßen für POSTs. Es verwendet die Annotation @QueryParam .

@POST
@Path("/create")
public void create(@QueryParam("param1") String param1,
                   @QueryParam("param2") String param2) {
    ...
}

Wie bei der vorherigen Technik erfordert das Übergeben von Parametern über die Abfragezeichenfolge keinen Nachrichtentext. Hier ist die HTTP-Nachricht:

POST /create?param1=hello&param2=world HTTP/1.1
Content-Length: 0
Host: www.example.com

Sie müssen besonders vorsichtig sein, um Abfrageparameter auf der Clientseite korrekt zu codieren . Die Verwendung von Abfrageparametern kann problematisch sein, da Einschränkungen der URL-Länge, die von einigen Proxies erzwungen werden, sowie Probleme im Zusammenhang mit deren Codierung auftreten.

HTTP-Pfadparameter

Pfadparameter ähneln Abfrageparametern, außer dass sie in den HTTP-Ressourcenpfad eingebettet sind. Diese Methode scheint heute zu sein. Es gibt Auswirkungen in Bezug auf das HTTP-Caching, da der Pfad die HTTP-Ressource wirklich definiert. Der Code sieht etwas anders aus als die anderen, da die Annotation @Path geändert wurde und @PathParam verwendet @PathParam :

@POST
@Path("/create/{param1}/{param2}")
public void create(@PathParam("param1") String param1,
                   @PathParam("param2") String param2) {
    ...
}

Die Nachricht ähnelt der Abfrageparameterversion, außer dass die Namen der Parameter nirgendwo in der Nachricht enthalten sind.

POST /create/hello/world HTTP/1.1
Content-Length: 0
Host: www.example.com

Diese Methode teilt die gleiche Codierungsprobleme wie die Abfrageparameterversion. Pfadsegmente sind unterschiedlich codiert, so dass Sie auch dort vorsichtig sein müssen.

Wie Sie sehen können, gibt es Vor- und Nachteile für jede Methode. Die Wahl wird normalerweise von Ihren Kunden getroffen. Wenn Sie auf FORM basierende HTML-Seiten @FormParam , verwenden Sie @FormParam . Wenn Ihre Clients JavaScript + HTML5-basiert sind, werden Sie wahrscheinlich JAXB-basierte Serialisierungs- und JSON-Objekte verwenden wollen. Die MessageBodyReader/Writer Implementierungen sollten sich um die notwendigen Escapes kümmern, so dass eine Sache weniger schief gehen kann. Wenn Ihr Client Java-basiert ist, aber keinen guten XML-Prozessor (z. B. Android) hat, würde ich wahrscheinlich die FORM Codierung verwenden, da ein Inhaltshauptteil einfacher zu erzeugen und zu codieren ist als URLs. Hoffentlich beleuchtet dieser Mini-Wiki-Eintrag die verschiedenen Methoden, die JAX-RS unterstützt.

Hinweis: Im Interesse einer vollständigen Offenlegung habe ich diese Funktion von Jersey noch nicht verwendet. Wir haben daran herumgebastelt, seit wir eine Reihe von JAXB + JAX-RS-Anwendungen implementiert haben und in den mobilen Client-Bereich wechseln. JSON passt viel besser zu XML auf HTML5- oder jQuery-basierten Lösungen.

Meine POST-Methode sieht folgendermaßen aus:

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String param1, String param2){
    System.out.println("param1 = " + param1);
    System.out.println("param2 = " + param2);
}

Wenn ich einen Jersey-Client in Netbeans erstelle, sieht die Methode, die die Post-Methode aufruft, so aus:

public void create(Object requestEntity){
    webResource.path("create").type(MediaType.APPLICATION_JSON).post(requestEntity);
}

Bei diesem Test:

@Test
public void hello(){
    String json = "{param1=\"hello\",param2=\"hello2\"}";
    this.client.create(json);
}

Es gibt folgende Ausgabe auf dem Server:

INFO: param1 = {param1="hello",param2="hello2"}
INFO: param2 = 

Was muss ich ändern, damit die Parameter den richtigen Wert ergeben?




REST-Grundlagen

REST hat eine einheitliche Schnittstellenbeschränkung, die besagt, dass der REST-Client auf Standards statt auf anwendungsspezifischen Details des eigentlichen REST-Services angewiesen sein muss, sodass der REST-Client nicht durch geringfügige Änderungen unterbrochen wird und wahrscheinlich wiederverwendbar ist.

Es gibt also einen Vertrag zwischen dem REST-Client und dem REST-Service. Wenn Sie HTTP als zugrunde liegendes Protokoll verwenden, sind die folgenden Standards Bestandteil des Vertrags:

  • HTTP 1.1
    • Methodendefinitionen
    • Statuscodedefinitionen
    • Cache-Steuerkopfzeilen
    • Akzeptieren und Inhaltstyp Header
    • Auth-Header
  • IRI (utf8 URI )
  • Körper (wählen Sie einen)
    • registrierter anwendungsspezifischer MIME-Typ, zB maze+xml
    • herstellerspezifischer MIME-Typ, z. B. vnd.github+json
    • generischer MIME-Typ mit
  • Hyperlinks
    • Was sollte sie enthalten?
      • Link-Header senden
      • Senden einer Hypermedia-Antwort, z. B. html, atom + xml, hal + json, ld + json & hydra usw.
    • Semantik
      • Verwenden Sie IANA Link-Beziehungen und wahrscheinlich benutzerdefinierte Link-Beziehungen
      • Verwenden Sie einen anwendungsspezifischen RDF-Vokabular

REST verfügt über eine statusfreie Einschränkung, die angibt, dass die Kommunikation zwischen dem REST-Dienst und dem Client staatenlos sein muss. Dies bedeutet, dass der REST-Dienst die Client-Status nicht verwalten kann, sodass Sie keinen serverseitigen Sitzungsspeicher haben können. Sie müssen jede einzelne Anfrage authentifizieren. So ist beispielsweise HTTP basic auth (Teil des HTTP-Standards) in Ordnung, weil es bei jeder Anfrage den Benutzernamen und das Passwort sendet.

Um deine Fragen zu beantworten

  1. Ja das kann sein.

    Um nur zu erwähnen, die Clients kümmern sich nicht um die IRI-Struktur, sie kümmern sich um die Semantik, weil sie Links mit Link-Relationen oder verknüpften Daten (RDF) -Attributen folgen.

    Das einzige, was an den IRIs wichtig ist, ist, dass ein einzelnes IRI nur eine einzige Ressource identifizieren muss. Es ist einer einzelnen Ressource wie einem Benutzer erlaubt, viele verschiedene IRIs zu haben.

    Es ist ziemlich einfach, warum wir nette IRIs wie /users/123/password ; Es ist viel einfacher, die Routing-Logik auf dem Server zu schreiben, wenn Sie das IRI einfach durch Lesen verstehen.

  2. Sie haben mehr Verben, wie PUT, PATCH, OPTIONS und noch mehr, aber Sie brauchen nicht mehr von ihnen ... Anstatt neue Verben hinzuzufügen, müssen Sie lernen, wie Sie neue Ressourcen hinzufügen.

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (Die Anmeldung ist wegen der statuslosen Einschränkung aus REST-Perspektive nicht sinnvoll.)

  3. Ihren Benutzern ist es egal, warum das Problem besteht. Sie möchten nur wissen, ob Erfolg oder Fehler vorliegt, und wahrscheinlich eine Fehlermeldung, die sie verstehen können, zum Beispiel: "Es tut uns leid, aber wir konnten Ihren Beitrag nicht speichern.", Etc ...

    Die HTTP-Status-Header sind Ihre Standard-Header. Alles andere sollte in dem Körper sein, denke ich. Ein einzelner Header reicht nicht aus, um beispielsweise detaillierte mehrsprachige Fehlermeldungen zu beschreiben.

  4. Die statusfreie Einschränkung (zusammen mit den Beschränkungen des Caches und des geschichteten Systems) stellt sicher, dass der Service gut skaliert. Sie wollen sicherlich nicht Millionen von Sitzungen auf dem Server verwalten, wenn Sie das gleiche auf den Clients tun können ...

    Der Drittanbieter-Client erhält ein Zugriffstoken, wenn der Benutzer über den Hauptclient Zugriff darauf gewährt. Danach sendet der 3rd Party Client das Access Token bei jeder Anfrage. Es gibt kompliziertere Lösungen, z. B. können Sie jede einzelne Anfrage signieren usw. Weitere Informationen finden Sie im OAuth-Handbuch.

Ähnliche Literatur





java web-services rest jersey jax-rs