web-dev-qa-db-fra.com

Comment utiliser les intercepteurs de Jersey pour obtenir le corps de la requête

J'utilise REST-Jersey dans mon projet. Toutes les données POST sont envoyées au format JSON et ne sont pas décompressées du côté serveur dans les beans respectifs. Quelque chose comme ça:

Envoi de la demande au serveur:

    $('a#sayHelloPost').click(function(event){
        event.preventDefault();
        var mangaData = {
            title:'Bleach',
            author:'Kubo Tite'
        }
        var formData=JSON.stringify(mangaData);
        console.log(formData);
        $.ajax({
                url:'rest/cred/sayposthello',
                type: 'POST',
                data: formData,
                dataType: 'json',
                contentType:'application/json'
        })
});

Charge utile:

{"title":"Bleach","author":"Kubo Tite"}

Fin serveur:

@POST
@Path("/sayposthello")
@Produces(MediaType.APPLICATION_JSON)
public Response sayPostHello(MangaBean mb){
    System.out.println(mb);
    return Response.status(200).build();
}

MangaBean:

public class MangaBean {
    private String title;
    private String author;
    @Override
    public String toString() {
        return "MangaBean [title=" + title + ", author=" + author + "]";
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
}

Sortie sur console:

MangaBean [title=Bleach, author=Kubo Tite]

J'ai eu l'implémentation d'intercepteur REST de ici .

public class JerseyFilter implements ContainerRequestFilter{

    @Override
    public ContainerRequest filter(ContainerRequest req) {
        return req;
    }

} 

Je veux accéder à la charge utile (corps de la demande) dans l'intercepteur. Comme les données sont au format JSON, elles ne sont pas accessibles en tant que paramètres de requête. Existe-t-il un moyen d'obtenir le corps de la demande dans la méthode d'intercepteur? S'il vous plaît des conseils.

15
Mono Jamoon

Voici une façon d'implémenter, très similaire à celle utilisée par Jersey pour implémenter ses filtres de journalisation. Vous pouvez lire l'entité et la coller à la demande afin de ne pas la consommer accidentellement dans votre filtre.

import com.Sun.jersey.api.container.ContainerException;
import com.Sun.jersey.core.util.ReaderWriter;
import com.Sun.jersey.spi.container.ContainerRequest;
import com.Sun.jersey.spi.container.ContainerRequestFilter;

import Java.io.ByteArrayInputStream;
import Java.io.ByteArrayOutputStream;
import Java.io.IOException;
import Java.io.InputStream;

public class JerseyFilter implements ContainerRequestFilter {

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        InputStream in = request.getEntityInputStream();
        final StringBuilder b = new StringBuilder();
        try {
            if (in.available() > 0) {
                ReaderWriter.writeTo(in, out);

                byte[] requestEntity = out.toByteArray();
                printEntity(b, requestEntity);

                request.setEntityInputStream(new ByteArrayInputStream(requestEntity));
            }
            return request;
        } catch (IOException ex) {
            throw new ContainerException(ex);
        }

    }

    private void printEntity(StringBuilder b, byte[] entity) throws IOException {
        if (entity.length == 0)
            return;
        b.append(new String(entity)).append("\n");
        System.out.println("#### Intercepted Entity ####");
        System.out.println(b.toString());
    }
}
27
Arul Dhesiaseelan

Vous pouvez obtenir le corps POST à partir du flux d'entrée Requests . Essayez quelque chose comme ceci:

        @Override
        public ContainerRequest filter(ContainerRequest req) {
            try{

            StringWriter writer = new StringWriter();       
                IOUtils.copy(req.getEntityInputStream(), writer, "UTF-8");

            //This is your POST Body as String      
            String body = writer.toString();

                }
            catch (IOException e) {}
         return req; }
4
azraelAT

Vous ne pouvez lire le contenu qu'une seule fois, car il s'agit d'un flux d'entrée. Si vous le récupérez dans l'intercepteur, vous ne pourrez pas le fournir dans l'analyse principale.

Ce que vous devez faire est de créer un filtre qui lit les données et les rend accessibles à toute autre personne qui en a besoin. Les étapes de base sont les suivantes:

  • dans votre filtre, créez une nouvelle sous-classe de HttpServletRequestWrapper qui lit l'entrée dans un tampon et remplace getInputStream () pour fournir un nouveau flux d'entrée à ce tampon
  • passez votre nouvelle sous-classe en bas de la chaîne
2
jgm

N'utilisez pas la méthode in.available() pour vérifier le nombre total d'octets de Inputstream. Certains clients ne définissent pas cette valeur. Et dans ce cas, ce sera grave même si le flux d'entrée du corps du message existe.

 InputStream in = request.getEntityInputStream();
        final StringBuilder b = new StringBuilder();
        try {
            if (in.available() > 0)

Utilisez le code ci-dessous 

String json = IOUtils.toString(requestContext.getEntityStream(), Charsets.UTF_8);
            messageBody = json;
            InputStream in = IOUtils.toInputStream(json);
            requestContext.setEntityStream(in);
2
SyParth