web-dev-qa-db-fra.com

Comment accéder aux paramètres d'une méthode RESTful POST

Ma méthode POST se présente comme suit:

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

Lorsque je crée un client Jersey dans Netbeans, la méthode qui appelle la méthode post ressemble à ceci:

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

Lors de l'exécution de ce test:

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

Il donne la sortie suivante sur le serveur:

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

Que dois-je changer pour que les paramètres donnent la valeur correcte?

117
Klaasvaak

Votre méthode @POST devrait accepter un objet JSON au lieu d'une chaîne. Jersey utilise JAXB pour prendre en charge le marshaling et le dissémination des objets JSON (voir la documentation du maillot pour plus de détails ). Créez une classe comme:

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

Ensuite, votre méthode @POST ressemblerait à ceci:

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

Cette méthode s'attend à recevoir l'objet JSON en tant que corps du HTTP POST. JAX-RS transmet le corps du contenu du message HTTP en tant que paramètre non annoté - input dans ce cas. Le message réel ressemblerait à quelque chose comme:

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

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

L'utilisation de JSON de cette manière est assez courante pour des raisons évidentes. Cependant, si vous le générez ou le consommez avec autre chose que JavaScript, vous devez faire attention à ne pas échapper correctement les données. Dans JAX-RS, vous utiliseriez un MessageBodyReader et MessageBodyWriter pour implémenter cela. Je pense que Jersey a déjà des implémentations pour les types requis (par exemple, primitives Java et classes encapsulées JAXB) ainsi que pour JSON. JAX-RS prend en charge plusieurs autres méthodes de transmission de données. Celles-ci ne nécessitent pas la création d'une nouvelle classe car les données sont transmises en utilisant un simple argument.


HTML <FORM>

Les paramètres seraient annotés avec @ FormParam :

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

Le navigateur va encoder le formulaire en utilisant "application/x-www-form-urlencoded" . Le moteur d’exécution JAX-RS s’occupe de décoder le corps et de le transmettre à la méthode. Voici ce que vous devriez voir sur le fil:

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

Le contenu est URL codée dans ce cas.

Si vous ne connaissez pas les noms des FormParam, vous pouvez procéder comme suit:

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

En-têtes HTTP

Vous pouvez utiliser l'annotation @ HeaderParam si vous souhaitez passer des paramètres via des en-têtes HTTP:

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

Voici à quoi ressemblerait le message HTTP. Notez que ce POST n'a pas de corps.

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

Je n'utiliserais pas cette méthode pour le passage généralisé de paramètres. C'est très pratique si vous avez besoin d'accéder à la valeur d'un en-tête HTTP particulier.


Paramètres de requête HTTP

Cette méthode est principalement utilisée avec HTTP GET, mais elle est également applicable aux POST. Il utilise l'annotation @ QueryParam .

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

Comme la technique précédente, la transmission de paramètres via la chaîne de requête ne nécessite pas de corps de message. Voici le message HTTP:

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

Vous devez faire particulièrement attention à correctement coder les paramètres de requête du côté client. L'utilisation de paramètres de requête peut être problématique en raison des restrictions de longueur d'URL imposées par certains mandataires ainsi que des problèmes liés à leur codage.


Paramètres de chemin HTTP

Les paramètres de chemin sont similaires aux paramètres de requête, sauf qu'ils sont incorporés dans le chemin de la ressource HTTP. Cette méthode semble être en faveur aujourd'hui. La mise en cache HTTP a des impacts, car le chemin est ce qui définit réellement la ressource HTTP. Le code est un peu différent des autres puisque l'annotation @ Path est modifiée et qu'il utilise @ PathParam :

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

Le message est similaire à la version du paramètre de requête, à l'exception du fait que les noms des paramètres ne sont inclus nulle part dans le message.

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

Cette méthode partage les mêmes problèmes d'encodage que la version du paramètre de requête. Les segments de chemin sont encodés différemment vous devez donc y faire attention également.


Comme vous pouvez le constater, chaque méthode a ses avantages et ses inconvénients. Le choix est généralement décidé par vos clients. Si vous servez des pages HTML basées sur FORM-, utilisez @FormParam. Si vos clients sont basés sur JavaScript + HTML5, vous souhaiterez probablement utiliser la sérialisation JAXB et les objets JSON. Les implémentations MessageBodyReader/Writer doivent prendre en charge l'évasion nécessaire pour vous, de sorte que le problème ne se produise plus. Si votre client est basé sur Java mais ne dispose pas d'un bon processeur XML (par exemple, Android), j'utiliserais probablement le codage FORM, car il est plus facile de générer et de coder correctement le corps du contenu que les URL. sont. Espérons que cette entrée de mini-wiki apporte un éclairage sur les différentes méthodes prises en charge par JAX-RS.

Remarque: Dans l'intérêt d'une divulgation complète, je n'ai pas encore utilisé cette fonctionnalité de Jersey. Nous y bricolions, car plusieurs applications JAXB + JAX-RS sont déployées et nous nous déplaçons dans l’espace client mobile. JSON convient beaucoup mieux que XML aux solutions HTML5 ou basées sur jQuery.

342
D.Shawley