将一个巨大的String作为post参数传递给servlet

时间:2016-04-20 05:08:12

标签: java servlets

我有一个servlet,它接收一个巨大的字符串(apprx 301695长度)作为post参数。

每分钟,.net应用程序都会向servlet发送如此庞大的字符串。

最初我曾经得到如下字符串:

 Line 1: String str = request.getParameter("data");

但是,3-4个小时后。我得到以下异常:

 java.lang.OutOfMemoryError: Java heap space

然后我评论了Line:1。即使我的servlet代码没有收到字符串,我也得到了与上面提到的相同的异常。

请指导我。我该如何处理这个问题?我已经阅读了许多与之相关的博客和文章,增加了堆大小等内容。但是,还没有找到任何解决方案。

原始代码如下:

private String scanType = "";
private static final String path = "D:\\Mobile_scan_alerts";
private static final String stockFileName = "stock.txt";
private static final String foFileName = "fo.txt";
private static Logger logger = null;
private String currDate = "";
private DateFormat dateFormat;
private StringBuffer stockData;
private StringBuffer foData;
 StringBuffer data = new StringBuffer("");
// For average time of received data
private static float sum = 0;
private static float count = 0;
private static float s_sum = 0;
private static float s_count = 0;
private static float fo_sum = 0;
private static float fo_count = 0;

private static final File dir = new File(path);
private static final File stockFile = new File(path + "\\" + stockFileName);
private static final File foFile = new File(path + "\\" + foFileName);

public void init() {

    logger = MyLogger.getScanAlertLogger();

    if(logger == null) {
        MyLogger.createLog();
        logger = MyLogger.getScanAlertLogger();
    }

}

/**
 * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
 * methods.
 *
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    PrintWriter out = response.getWriter();
    response.setContentType("text/plain");
    String strScan = "";

    try {

        String asof = null;

        scanType = request.getParameter("type");
        scanType = scanType == null ? "" : scanType;


        if(scanType.length() > 0){

            if(scanType.equalsIgnoreCase("s")) {
                stockData = null;
                stockData = new StringBuffer(request.getParameter("scanData"));
                stockData = stockData == null ? new StringBuffer("") : stockData;
            } else {
                foData = null;
                foData = new StringBuffer(request.getParameter("scanData"));
                foData = foData == null ? new StringBuffer("") : foData;
            }

        }

        asof = request.getParameter("asof");
        asof = asof == null ? "" : asof.trim();

        // Date format without seconds
        DateFormat formatWithoutSec = new SimpleDateFormat("yyyy/MM/dd HH:mm");

        dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date tmp = new Date();

        // format: yyyy/MM/dd HH:mm:ss
        currDate = dateFormat.format(tmp);

        //format: yyyy/MM/dd HH:mm
        Date asofDate = formatWithoutSec.parse(asof);
        Date cDate = formatWithoutSec.parse(currDate);
        cDate.setSeconds(0);


        System.out.println(asofDate.toString()+" || "+cDate.toString());

        int isDataExpired = asofDate.toString().compareTo(cDate.toString());

        if(isDataExpired > 0 || isDataExpired == 0) {

            if(scanType != null && scanType.length() > 0) {
                checkAndCreateDir();
                strScan = scanType.equalsIgnoreCase("s") ? "Stock Data Recieved at "+currDate
                        : "FO Data Recieved at "+currDate;
                //System.out.println(strScan);
            } else {
                strScan = "JSON of scan data not received properly at "+currDate;
                //System.out.println("GSAS: received null or empty");
            }

        } else {
            strScan = "GSAS: " + scanType + ": Received Expired Data of "+asofDate.toString()+" at "+cDate.toString();
            System.out.println(strScan);
        }
        scanType = null;


    } catch (Exception ex) {
        strScan = "Mobile server issue for receiving scan data";
        System.out.println("GSAS: Exception-1: "+ex);
        logger.error("GetScanAlertServlet: processRequest(): Exception: "+ex.toString());
    } finally {
        logger.info("GetScanAlertServlet: "+strScan);
        out.println(strScan);
    }

}

private void checkAndCreateDir() {

    try {
            boolean isStock = false;
            Date ddate = new Date();
            currDate = dateFormat.format(ddate);
            sum += ddate.getSeconds();
            count++;
            logger.info("Total Average Time: "+(sum/count));

            if(scanType.equalsIgnoreCase("s")){ //For Stock
                setStockData(stockData);

                Date date1 = new Date();
                currDate = dateFormat.format(date1);
                s_sum += date1.getSeconds();
                s_count++;
                logger.info("Stock Average Time: "+(s_sum/s_count));

                //file = new File(path + "\\" + stockFileName);
                isStock = true;

            } else if (scanType.equalsIgnoreCase("fo")) { //For FO
                setFOData(foData);

                Date date2 = new Date();
                currDate = dateFormat.format(date2);
                fo_sum += date2.getSeconds();
                fo_count++;
                logger.info("FO Average Time: "+(fo_sum/fo_count));

                //file = new File(path + "\\" +foFileName);
                isStock = false;
            }


            if(!dir.exists()) { // Directory not exists
                if(dir.mkdir()) {

                    if(isStock)
                        checkAndCreateFile(stockFile);
                    else
                        checkAndCreateFile(foFile);

                }
            } else { // Directory already exists

                    if(isStock)
                        checkAndCreateFile(stockFile);
                    else
                        checkAndCreateFile(foFile);
            }

    } catch (Exception e) {
        System.out.println("GSAS: Exception-2: "+e);
        logger.error("GetScanAlertServlet: checkAndCreateDir(): Exception: "+e);
    }

}

private void checkAndCreateFile(File file) {

    try{
        if(!file.exists()){ // File not exists

            if(file.createNewFile()){
                writeToFile(file);
            }

        } else { // File already exists
            writeToFile(file);
        }
    } catch (Exception e) {
        System.out.println("GSAS: Exception-3: "+e);
        logger.error("GetScanAlertServlet: checkAndCreateFile(): Exception: "+e.toString());
    }
}


private void writeToFile(File file) {

    FileOutputStream fop = null;

    try{

        if(scanType.equalsIgnoreCase("s")){ //For Stock
            data = getStockData();
        } else if (scanType.equalsIgnoreCase("fo")) { //For FO
            data = getFOData();
        }

        if(data != null && data.length() > 0 && file != null){

            fop = new FileOutputStream(file);

            byte[] contentBytes = data.toString().getBytes();
            for(byte b : contentBytes){
                fop.write(b);
            }
            //fop.write(contentBytes);

            fop.flush();


        } else {

            System.out.println("GSAS: Data is null/empty string");
            logger.info("GSAS: Data is null or empty string");

        }
        data = null;
    } catch (Exception  e) {
        System.out.println("GSAS: Exception-4: "+e);
        logger.info("GetScanAlertServlet: writeToFile(): Exception: "+e.toString());

    } finally {

        try {

            if(fop != null)
                fop.close();

        } catch (IOException ex) {
                java.util.logging.Logger.getLogger(GetScanAlertServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

private String readFromFile(String fileName){

    String fileContent = "";
    try{

        String temp = "";
        File file = new File(fileName);
        if(file.exists()){

            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);

            while((temp = br.readLine()) != null)
            {
                fileContent += temp;
            }
            br.close();
        } else {
            System.out.println("GSAS: File not exists to read");
            logger.info("GetScanAlertServlet: File not exists to read");
        }

        temp = null;
        file = null;

    } catch (Exception e) {
        System.out.println("GSAS: Exception-5: "+e);
        logger.error("GetScanAlertServlet: readFromFile(): Exception: "+e.toString());
    }
    return fileContent;
}

public StringBuffer getStockData() {

    //String temp="";
    //StringBuffer temp = (StringBuffer)scanDataSession.getAttribute("stock");
    //if(temp != null && temp.length() > 0) {
    //    return temp;
    //}
    if(stockData != null && stockData.length() > 0){
        return stockData;
    } else {
        stockData = null;
        stockData = new StringBuffer(readFromFile(path + "\\"+ stockFileName));
        return stockData;
    }
}


public StringBuffer getFOData(){

    //String temp="";
    //StringBuffer temp = (StringBuffer)scanDataSession.getAttribute("fo");
    //if(temp != null && temp.length() > 0) {
    //    return temp;
    //}
    if(foData != null && foData.length() > 0) {
        return foData; 
    } else {
        foData = null;
        foData = new StringBuffer(readFromFile(path + "\\" + foFileName));
        return foData;
    }   
}

}

4 个答案:

答案 0 :(得分:0)

增加堆大小不是解决此问题的好方法。您的上游应用程序应该停止向您的Servlet发送大量字符串。

您的上游(.net)应用程序应考虑将所有数据写入文件,只需将文件的位置作为参数发送到您的Servlet。一旦您的servlet收到来自上游的通知,您可以考虑从该位置下载/读取文件。

  

然后我评论了Line:1。尽管如此,我的servlet代码没有   接收字符串(如注释),我得到相同的例外   如上所述。

Line:1是读取数据。如果你评论它,你就不会收到字符串。

答案 1 :(得分:0)

您可以使用apache commons-fileupload库Streaming API,这样,您可以将上传的文件作为流文件并将其写入文件:

Hyperdb

现在你有了InputStream,所以你可以在输出流中写它。

但要使用它,您需要.NET应用程序将字节上传到服务器,而不是将整个String作为请求参数发送。

http://commons.apache.org/proper/commons-fileupload/streaming.html

答案 2 :(得分:0)

如果您无法控制传递给servlet的String,请检查您的VM参数并适当修改它们。例如:

$( "#wideModal" ).on('hidden.bs.modal', function(){
    $(this).off();
    $('#wideModal .modal-content').removeData('bs.modal');
});

检查完整的解释here

答案 3 :(得分:0)

我们使用GZip压缩/解压缩来降低字符串的大小。它有效地发挥了作用。

因此,.net服务压缩了巨大的字符串,将其发送到我们的Servlet。然后我们在服务器上解压缩它。