HttpServletRequest'ten POST istek gövdesini alın


115

HttpServletRequest nesnesinden tüm gövdeyi almaya çalışıyorum.

Takip ettiğim kod şuna benziyor:

if ( request.getMethod().equals("POST") )
{
    StringBuffer sb = new StringBuffer();
    BufferedReader bufferedReader = null;
    String content = "";

    try {
        //InputStream inputStream = request.getInputStream();
        //inputStream.available();
        //if (inputStream != null) {
        bufferedReader =  request.getReader() ; //new BufferedReader(new InputStreamReader(inputStream));
        char[] charBuffer = new char[128];
        int bytesRead;
        while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
            sb.append(charBuffer, 0, bytesRead);
        }
        //} else {
        //        sb.append("");
        //}

    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    test = sb.toString();
}

curl ve wget ile işlevselliği şu şekilde test ediyorum:

curl --header "MD5: abcd" -F "fileupload=@filename.txt http://localhost:8080/abcd.html"

wget --header="MD5: abcd" --post-data='{"imei":"351553012623446","hni":"310150","wdp":false}' http://localhost:8080/abcd.html"

Ama while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 )hiçbir şey döndürmüyor ve bu yüzden StringBuffer'a eklenen hiçbir şey almıyorum.

Yanıtlar:


192

Java 8'de bunu daha basit ve temiz bir şekilde yapabilirsiniz:

if ("POST".equalsIgnoreCase(request.getMethod())) 
{
   test = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}

8
Herhangi bir 3. parti bağımlılığı olmayan saf bir Java olduğu için bu çözümü tercih ediyorum.
lu_ko

49
getReaderZaten çağrıldığı gibi istek metnini tekrar okuyamayacağımızı unutmayın .
Nikhil Sahu

1
Yeni biçimlendirilmiş HTTP POST verilerini tekrar isteğe nasıl geri döndürebiliriz?
Pra_A

1
Bu çözümü denedim ama çok ciddi bir sorun ortaya çıkardı, bu kodu bir oncePerRequest filtresi içinde istek bilgisini günlüğe kaydetmek için kullandım ve bunu kullandığımda, tüm post yöntemlerimdeki tüm @modelAttribute bağlarımın tüm alanlarında null verdi nesne. Bu yaklaşımı kullanmanızı önermiyorum.
Muhammed Fathi

Okuyucuyu kapatmamalı mıyız?
aristo_sh

46

Commons-io ile kolay yol.

IOUtils.toString(request.getReader());

https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/IOUtils.html


Okuyucunun çıktısının nasıl görüneceğine dair bir örnek verebilirseniz yardımcı olurum (yani anahtarları göster ya da gösterme)
ArthurG

Bu benim için çalıştı. Bu çözümün, bufferedreader.readLine () 'ın görünürde bir sebep olmaksızın "kilitlendiği" yaygın bir senaryoyu da önlediğini doğrulayabilirim
Naren

Merhaba @DavidDomingo,% 100 çalışıyor, bunun üstündeki yanıtta (aynı şekilde çalışıyor) aynı şeyi yorumladığınızı okuyabilirim. Kodunuzda bir yerde (muhtemelen filtreler), veya belki Bahar tarafından birisi daha önce getReader () yöntemi çağrılmadığından, çünkü onu iki veya daha fazla kez çağırırsanız, yalnızca ilk yükü döndürür.
Dani

Merhaba @Dani, bu yüzden işe yaramıyor. Okuyucu boş. RestController'ın siz herhangi bir uç noktada yapmadan önce okuduğunu düşünüyorum. Vücudu almanın en kolay yolu HttpEntity kullanmaktır.
David Domingo

31

Kodunuzun oldukça gürültülü olduğunu unutmayın. İpliğin eski olduğunu biliyorum, ama yine de birçok insan okuyacak. Guava kitaplığını kullanarak aynı şeyi yapabilirsiniz :

    if ("POST".equalsIgnoreCase(request.getMethod())) {
        test = CharStreams.toString(request.getReader());
    }

3
Belki düşününif(RequestMethod.POST.name().equalsIgnoreCase(...)) { ... }
Madbreaks

Java.lang.IllegalStateException: getReader () bu istek için zaten çağrıldı
Pra_A

18

Tek istediğiniz POST istek gövdesi ise, aşağıdaki gibi bir yöntem kullanabilirsiniz:

static String extractPostRequestBody(HttpServletRequest request) throws IOException {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

Kredi: https://stackoverflow.com/a/5445161/1389219


1
request.getInputStream()İsteğin karakter kodlamasını olduğu gibi kabul request.getReader()etmediğini dikkate alın . Bağlantı için +1 olsa da.
Vadzim

PUT yöntemi için eşdeğeri ne olmalıdır?
devanathan

10

Bu hem GET hem de POST için çalışır:

@Context
private HttpServletRequest httpRequest;


private void printRequest(HttpServletRequest httpRequest) {
    System.out.println(" \n\n Headers");

    Enumeration headerNames = httpRequest.getHeaderNames();
    while(headerNames.hasMoreElements()) {
        String headerName = (String)headerNames.nextElement();
        System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
    }

    System.out.println("\n\nParameters");

    Enumeration params = httpRequest.getParameterNames();
    while(params.hasMoreElements()){
        String paramName = (String)params.nextElement();
        System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
    }

    System.out.println("\n\n Row data");
    System.out.println(extractPostRequestBody(httpRequest));
}

static String extractPostRequestBody(HttpServletRequest request) {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = null;
        try {
            s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

9

İstek gövdesi boşsa, bu, önceden tüketilmiş olduğu anlamına gelir. Örneğin, bir tarafından request.getParameter(), getParameterValues()ya da getParameterMap()çağrı. Bu çağrıları yapan hatları kodunuzdan kaldırmanız yeterlidir.


Bu yalnızca, curlörneğin bir dosya yüklemesi değilse işe yarar , hayır?
Dave Newton

1
Bu şeyi denedim. Ama yine de POST gövdesini alamıyorum. Bir şey kaçırıyor olmalıyım. Sadece eklemek için: Geliştirme için Tapestry kullanıyorum.
patel bhavin

3

Bu, tüm HTTP yöntemleri için çalışacaktır.

public class HttpRequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public HttpRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = IOUtils.toString(request.getReader());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getBody().getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener listener) {
            }

        };
        return servletInputStream;
    }

    public String getBody() {
        return this.body;
    }
}

0

Bu durumu bu şekilde çözdüm. Okuyucu alma yeteneğine sahip ObjectMapper'ın readValue yöntemini kullanarak istek gövdesinden çıkarılan bir nesneyi döndüren bir kullanım yöntemi oluşturdum.

public static <T> T getBody(ResourceRequest request, Class<T> class) {
    T objectFromBody = null;
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(request);
        objectFromBody = objectMapper.readValue(httpServletRequest.getReader(), class);
    } catch (IOException ex) {
        log.error("Error message", ex);
    }
    return objectFromBody;
}

1
PortalUtil nedir?
Ferry Kranenburg

Bahse girerim bu
Liferay'den, Liferay'e
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.