Come accedere ai parametri in un metodo POST RESTful


123

Il mio metodo POST ha questo aspetto:

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

Quando creo un client Jersey in Netbeans, il metodo che chiama il metodo post ha questo aspetto:

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

Quando si esegue questo test:

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

Fornisce il seguente output nel server:

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

Cosa devo modificare in modo che i parametri diano il valore corretto?


lo stai usando su un'applicazione Android o no?
Android-Droid

Finalmente voglio chiamare questo metodo di pubblicazione in un'app Android. In qualche modo il webservice non sa come firmare i valori ai parametri. Voglio sapere come farlo.
Klaasvaak

Risposte:


356

Il tuo @POSTmetodo dovrebbe accettare un oggetto JSON invece di una stringa. Jersey usa JAXB per supportare il marshalling e l'unmarshaling di oggetti JSON (vedi i documenti jersey per i dettagli ). Crea una classe come:

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

Quindi il tuo @POSTmetodo sarebbe simile al seguente:

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

Questo metodo prevede di ricevere l'oggetto JSON come corpo del POST HTTP. JAX-RS passa il corpo del contenuto del messaggio HTTP come parametro non annotato, inputin questo caso. Il messaggio effettivo sarebbe simile a:

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

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

L'uso di JSON in questo modo è abbastanza comune per ovvi motivi. Tuttavia, se lo stai generando o consumando in qualcosa di diverso da JavaScript, devi stare attento a sfuggire correttamente ai dati. In JAX-RS, useresti MessageBodyReader e MessageBodyWriter per implementarlo. Credo che Jersey abbia già implementazioni per i tipi richiesti (ad esempio, primitive Java e classi con wrapping JAXB) così come per JSON. JAX-RS supporta una serie di altri metodi per il passaggio dei dati. Questi non richiedono la creazione di una nuova classe poiché i dati vengono passati utilizzando un semplice passaggio di argomenti.


HTML <FORM>

I parametri sarebbero annotati usando @FormParam :

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

Il browser codificherà il modulo utilizzando "application / x-www-form-urlencoded" . Il runtime JAX-RS si occuperà di decodificare il corpo e passarlo al metodo. Ecco cosa dovresti vedere sul filo:

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

In questo caso, il contenuto è codificato in URL .

Se non conosci i nomi dei FormParam puoi fare quanto segue:

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

Intestazioni HTTP

Puoi utilizzare l' annotazione @HeaderParam se desideri passare i parametri tramite intestazioni HTTP:

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

Ecco come sarebbe il messaggio HTTP. Nota che questo POST non ha un corpo.

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

Non userei questo metodo per il passaggio di parametri generalizzato. Tuttavia, è davvero utile se è necessario accedere al valore di una particolare intestazione HTTP.


Parametri delle query HTTP

Questo metodo viene utilizzato principalmente con HTTP GET ma è ugualmente applicabile ai POST. Utilizza l' annotazione @QueryParam .

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

Come la tecnica precedente, il passaggio di parametri tramite la stringa di query non richiede un corpo del messaggio. Ecco il messaggio HTTP:

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

È necessario prestare particolare attenzione a codificare correttamente i parametri di query sul lato client. L'utilizzo dei parametri di query può essere problematico a causa delle restrizioni sulla lunghezza degli URL applicate da alcuni proxy e dei problemi associati alla loro codifica.


Parametri del percorso HTTP

I parametri del percorso sono simili ai parametri della query tranne per il fatto che sono incorporati nel percorso della risorsa HTTP. Questo metodo sembra essere a favore oggi. Ci sono impatti rispetto alla memorizzazione nella cache HTTP poiché il percorso è ciò che definisce realmente la risorsa HTTP. Il codice ha un aspetto leggermente diverso dagli altri poiché l' annotazione @Path viene modificata e utilizza @PathParam :

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

Il messaggio è simile alla versione del parametro di query tranne per il fatto che i nomi dei parametri non sono inclusi in alcun punto del messaggio.

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

Questo metodo condivide gli stessi problemi di codifica della versione del parametro di query. I segmenti di percorso sono codificati in modo diverso, quindi devi stare attento anche lì.


Come puoi vedere, ci sono pro e contro per ogni metodo. La scelta è solitamente decisa dai tuoi clienti. Se stai offrendo FORMpagine HTML basate sulla pubblicazione, utilizza @FormParam. Se i tuoi client sono basati su JavaScript + HTML5, probabilmente vorrai utilizzare la serializzazione basata su JAXB e gli oggetti JSON. Le MessageBodyReader/Writerimplementazioni dovrebbero prendersi cura dell'escape necessario per te in modo che sia una cosa in meno che può andare storta. Se il tuo client è basato su Java ma non ha un buon processore XML (es. Android), allora probabilmente userei la FORMcodifica poiché un corpo di contenuto è più facile da generare e codificare correttamente rispetto agli URL. Si spera che questa voce di mini-wiki faccia luce sui vari metodi supportati da JAX-RS.

Nota: nell'interesse della completa divulgazione, non ho ancora utilizzato questa funzione di Jersey. Ci stavamo armeggiando poiché abbiamo implementato un certo numero di applicazioni JAXB + JAX-RS e ci stiamo muovendo nello spazio dei client mobili. JSON si adatta molto meglio a XML su soluzioni basate su HTML5 o jQuery.


4
Ho testato questa funzione ieri, le annotazioni @XmlElement non erano necessarie
mmatloka

Grazie per questo. Se voglio comunque inviare 2 stringhe, cosa deve essere consumato dal restfull? O più parametri funzionano solo con @PathParm?
Klaasvaak

1
@Klaasvaak - è necessario specificare da dove ci si aspetta che ogni parametro venga estratto. Come hai fatto adesso, Jersey / NetBeans sta assumendo un modulo post ed estrae i dati inviati come FormParm. Annota ogni potenziamento del tuo metodo con la posizione da cui desideri i dati (PathParam, FormParam, CookieParam ecc.)
Perception

1
@Klaasvaak - Ho aggiunto una serie di esempi utilizzando le varie annotazioni
D.Shawley

2
Grazie mille per questo! Questo era davvero quello che stavo cercando. Mi hai reso la giornata;) Sto usando FormParams ora e funziona!
Klaasvaak
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.