web-dev-qa-db-de.com

So greifen Sie mit einer RESTful POST - Methode auf Parameter zu

Meine POST Methode sieht so 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, folgendermaßen aus:

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

Beim Ausführen dieses Tests:

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

Es gibt die folgende Ausgabe auf dem Server:

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

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

117
Klaasvaak

Ihre @POST - Methode sollte ein JSON-Objekt anstelle einer Zeichenfolge akzeptieren. Jersey verwendet JAXB, um JSON-Objekte zu marshallen und deren Marshalling aufzuheben (siehe die Jersey-Dokumentation enthält Einzelheiten ). Erstelle eine Klasse wie:

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

Dann würde Ihre @POST - Methode folgendermaßen 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 das JSON-Objekt als Hauptteil des HTTP-POST empfangen wird. JAX-RS übergibt den Inhaltshauptteil der HTTP-Nachricht als nicht kommentierten Parameter - in diesem Fall input. Die eigentliche Nachricht würde ungefähr 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 offensichtlichen Gründen weit verbreitet. Wenn Sie es jedoch in etwas anderem als JavaScript generieren oder verbrauchen, müssen Sie vorsichtig sein, um den Daten ordnungsgemäß zu entgehen. In JAX-RS würden Sie einen MessageBodyReader und MessageBodyWriter verwenden, um dies zu implementieren. Ich glaube, dass Jersey bereits Implementierungen für die erforderlichen Typen (z. B. Java) und JAXB-umschlossene Klassen) sowie für JSON hat. JAX-RS unterstützt eine Reihe anderer Methoden zur Datenübergabe Sie müssen keine neue Klasse erstellen, da die Daten mithilfe der einfachen Argumentübergabe übergeben werden.


HTML <FORM>

Die Parameter würden mit @ FormParam mit Anmerkungen versehen:

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

Der Browser verschlüsselt das Formular mit "application/x-www-form-urlencoded" . Die JAX-RS-Laufzeit sorgt dafür, dass der Body dekodiert und an die Methode übergeben wird. Folgendes sollten Sie auf dem Draht sehen:

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 verschlüsselt .

Wenn Sie die Namen der FormParams 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 verwenden, 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 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 jedoch sehr praktisch, wenn Sie auf den Wert eines bestimmten HTTP-Headers zugreifen müssen.


HTTP-Abfrageparameter

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

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

Wie bei der vorherigen Technik ist für die Übergabe von Parametern über die Abfragezeichenfolge kein Nachrichtentext erforderlich. 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 sorgfältig darauf achten, Abfrageparameter zu codieren auf der Clientseite. Die Verwendung von Abfrageparametern kann aufgrund von URL-Längenbeschränkungen, die von einigen Proxys erzwungen werden, sowie aufgrund von Codierungsproblemen problematisch sein.


HTTP-Pfadparameter

Pfadparameter sind Abfrageparametern ähnlich, mit der Ausnahme, dass sie in den HTTP-Ressourcenpfad eingebettet sind. Diese Methode scheint heute zu stimmen. Es gibt Auswirkungen in Bezug auf das HTTP-Caching, da der Pfad die HTTP-Ressource wirklich definiert. Der Code sieht ein wenig anders aus als die anderen, da die Annotation @ Path geändert wird und @ PathParam verwendet wird:

@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 an keiner Stelle in der Nachricht enthalten sind.

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

Diese Methode hat die gleichen Codierungsprobleme wie die Abfrageparameterversion. Pfadsegmente werden unterschiedlich codiert Sie müssen also auch dort vorsichtig sein.


Wie Sie sehen, gibt es für jede Methode Vor- und Nachteile. Die Wahl wird in der Regel von Ihren Kunden entschieden. Wenn Sie FORM-basierte HTML-Seiten bereitstellen, verwenden Sie @FormParam. Wenn Ihre Clients JavaScript + HTML5-basiert sind, möchten Sie wahrscheinlich JAXB-basierte Serialisierung und JSON-Objekte verwenden. Die MessageBodyReader/Writer - Implementierungen sollten sich um das notwendige Entkommen kümmern, damit eine Sache weniger schief gehen kann. Wenn Ihr Client Java) basiert, aber keinen guten XML-Prozessor hat (z. B. Android), würde ich wahrscheinlich FORM-Codierung verwenden, da ein Inhaltskörper einfacher zu generieren und zu verwenden ist Kodieren Sie richtig, als es URLs sind. Hoffentlich gibt dieser Mini-Wiki-Eintrag einen Einblick in die verschiedenen Methoden, die JAX-RS unterstützt.

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

342
D.Shawley