Maison >Java >javaDidacticiel >Comment activer plusieurs lectures du corps de la requête POST dans les filtres de servlet Java ?

Comment activer plusieurs lectures du corps de la requête POST dans les filtres de servlet Java ?

Barbara Streisand
Barbara Streisandoriginal
2024-11-28 15:21:12210parcourir

How to Enable Multiple Reads of POST Request Body in Java Servlet Filters?

Lectures multiples du corps de la demande de publication dans les filtres de servlet Java

Problème :

Dans les filtres de servlet Java, accès à la requête HTTP Les paramètres d'un corps de requête POST peuvent entraîner l'indisponibilité des paramètres ultérieurement dans la chaîne de filtrage. Cela se produit car le corps de la requête est consommé lors de la lecture initiale.

Solution :

Pour surmonter ce problème et permettre plusieurs lectures des paramètres du corps de la requête, une solution implique étendre HttpServletRequestWrapper et mettre en cache les octets du flux d'entrée. Voici une classe de wrapper de requête personnalisée :

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
  private ByteArrayOutputStream cachedBytes;

  public MultiReadHttpServletRequest(HttpServletRequest request) {
    super(request);
  }

  @Override
  public ServletInputStream getInputStream() throws IOException {
    if (cachedBytes == null)
      cacheInputStream();

      return new CachedServletInputStream(cachedBytes.toByteArray());
  }

  @Override
  public BufferedReader getReader() throws IOException{
    return new BufferedReader(new InputStreamReader(getInputStream()));
  }

  private void cacheInputStream() throws IOException {
    cachedBytes = new ByteArrayOutputStream();
    IOUtils.copy(super.getInputStream(), cachedBytes);
  }

  /* An input stream which reads the cached request body */
  private static class CachedServletInputStream extends     ServletInputStream {

    private final ByteArrayInputStream buffer;

    public CachedServletInputStream(byte[] contents) {
      this.buffer = new ByteArrayInputStream(contents);
    }

    @Override
    public int read() {
      return buffer.read();
    }

    @Override
    public boolean isFinished() {
      return buffer.available() == 0;
    }

    @Override
    public boolean isReady() {
      return true;
    }

    @Override
    public void setReadListener(ReadListener listener) {
  throw new RuntimeException("Not implemented");
    }
  }
}

Utilisation :

Enveloppez la demande d'origine avec le wrapper personnalisé avant de la transmettre à travers la chaîne de filtres :

public class MyFilter implements Filter {
  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

    MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request);
    doMyThing(multiReadRequest.getInputStream());
    chain.doFilter(multiReadRequest, response);
  }
}

Cela permet plusieurs lectures du corps de la requête, soit via getInputStream() ou getReader() méthodes.

Remarque :

Pour les versions plus récentes de l'interface ServletInputStream, des méthodes supplémentaires telles que isReady() et setReadListener() doivent être implémentées dans la classe de flux d'entrée personnalisée. . Reportez-vous au lien fourni dans la réponse pour plus de détails.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn