簡體   English   中英

如何在不讀取整個請求的情況下發送響應?

[英]How to send response without reading entire request?

我正在基於Tomcat Servlet和NIO創建服務。 輸入時會有很大的XML請求(〜100 MB),通過HTML POST方法發送。 我只想流式傳輸8個KiB,然后立即將響應發送給客戶端。

public class A extends HttpServlet {
    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs) {
        byte[] buffer = new byte[1024*8];
        try {
            rq.getInputStream().read(buffer);
            rs.setContentType("text/plain");
            rs.getOutputStream().write("Some Response".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
     }
}

當我嘗試發送小的請求(內容中的幾行)時,沒有問題,套接字可以正常工作。

2016-02-01 10:44:52 Http11NioProtocol [DEBUG]套接字:[org.apache.tomcat.util.net.NioEndpoint$KeyAttachment@74f19fed:org.apache.tomcat.util.net.NioChannel@c478210:java.nio .channels.SocketChannel [connected local = / 0:0:0:0:0:0:0:1:8080 remote = / 0:0:0:0:0:0:0:0:1:63943]],狀態進入:[OPEN_READ],退出:: [ OPEN ]

但是,如果我嘗試發送更大的請求(超過100 MB),則客戶端將沒有響應。

2016-02-01 10:48:42 Http11NioProtocol [DEBUG]套接字:[org.apache.tomcat.util.net.NioEndpoint$KeyAttachment@2b36c88f:org.apache.tomcat.util.net.NioChannel@25f12241:java.nio .channels.SocketChannel [connected local = / 0:0:0:0:0:0:0:1:8080 remote = / 0:0:0:0:0:0:0:0:1:64079]],狀態進入:[OPEN_READ],退出:[ 關閉 ]

2016-02-01 10:48:42 LimitLatch [DEBUG]倒計時[http-nio-8080-exec-3] 閂鎖= 1

在讀取整個輸入流請求之前,Tomcat不想打開套接字(狀態為:CLOSED)。

是否可以在不讀取整個請求的情況下將響應發送到客戶端? 根據規范,我能夠在請求的前8 KiB上找到有趣的信息。

您的代碼僅讀取請求的一部分,

您可以使用此方法將Stream轉換為String

private static String convertStreamToString(InputStream is) throws IOException{
        int i = 0;
        byte[] buff = new byte[1024];
        StringBuilder sb = new StringBuilder();
        while (i != -1) {            
            i = is.read(buff);
            if(i != -1){
            sb.append(new String(buff,0,i));
            }
        }
        return sb.toString();
    }

因此,在您的代碼中

public class A extends HttpServlet {
    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs) {

        try {
            String response = convertStreamToString(rq.getInputStream());   
            rs.getOutputStream().write(response.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
     }
     private static String convertStreamToString(InputStream is) throws IOException{
        int i = 0;
        byte[] buff = new byte[1024];
        StringBuilder sb = new StringBuilder();
        while (i != -1) {            
            i = is.read(buff);
            if(i != -1){
                sb.append(new String(buff,0,i));
            }
        }
        return sb.toString();
    }

}

或者您可以使用掃描儀將流直接轉換為字符串

    Scanner scanner = new Scanner(inputStream);
    StringBuilder sb = new StringBuilder();
    while (scanner.hasNext()) {            
        sb.append(scanner.next());
    }

因此,在您的代碼中

public class A extends HttpServlet {
    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs) {

        try {
             Scanner scanner = new Scanner(rq.getInputStream());
             StringBuilder sb = new StringBuilder();
             while (scanner.hasNext()) {            
                 sb.append(scanner.next());
             }
            rs.getOutputStream().write(sb.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
     }

}

此代碼

byte[] buffer = new byte[1024*8];
rq.getInputStream().read(buffer);

僅讀取1024個字節的請求,並將其存儲到緩沖區數組(1024個字節),方法read將返回已讀取的字節數,因為根本不會讀取1024個字節,如果請求僅發送200個字節,則824個字節將無用。 因此,如果請求僅發送200個字節

int x = rq.getInputStream().read(buffer);

這個x為200,因此要完整閱讀,您需要進行循環

// integer to read
int bytesRead = 0;
// loop until bytesRead is -1 (end of request), -1 means there are no bytes to read, so it will read until there are no bytes to read
while(bytesRead != -1){
    bytesRead = rq.getInputStream().read(buffer);
    if(bytesRead != -1){
    // process the bytes here , but only process bytes from 0 to bytesRead
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM