0

我正在编写一个软件,该软件的一部分涉及我的 Java 桌面客户端应用程序和 servlet 之间的通信。servlet 从数据库中提取文本数据并将其写入 1 个单独的 out.println() 语句。问题是,当 servlet 写入的文本数据很多时,部分文本永远不会到达客户端。尽管在 servlet 中设置了 contentlength response.setContentLength(text.length())。会发生什么?这是小服务程序:

package servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;'
import javax.sql.DataSource;
/**
 *
 * @author GBEMIRO
 */

public class MessageRetrieverServlet extends HttpServlet {

DataSource pool;  // Database connection pool
private HttpSession session;

@Override
public void init() throws ServletException {
    try {
        // Create a JNDI Initial context to be able to lookup the DataSource
        InitialContext ctx = new InitialContext();
        // Lookup the DataSource, which will be backed by a pool
        //   that the application server provides.
        pool = (DataSource) ctx.lookup("java:comp/env/jdbc/TestDB");
        if (pool == null) {
            throw new ServletException("Unknown DataSource 'jdbc/TestDB'");
        }
    } catch (NamingException ex) {
        ex.printStackTrace();
    }
}//end method init

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    session = request.getSession();
    Connection conn = null;
    try {

        String email = request.getParameter("email");

        conn = pool.getConnection();

        PreparedStatement pstmt = conn.prepareStatement("SELECT MSG FROM POSTS_TABLE WHERE EMAIL = ? ");

        pstmt.setString(1, email);

        ResultSet rs = pstmt.executeQuery();
        rs.next();

        //The huge text
        Clob clob = rs.getClob("MSG");

        /**
         * The text retrieved into msg is very large, but I checked with
         * System.out.println(msg) statements it is complete up to this
         * point, no part of it is lost. So the retrieval from the database
         * is always successful.
         *
         */
        String msg = clob.getSubString(0, (int) clob.length());

        out.print(msg);

    }//end try
    catch (SQLException exception) {
        String errorMsg = "error3";
        exception.printStackTrace();
        out.print(errorMsg);
    } catch (NumberFormatException numberFormatException) {
        String errorMsg = "error4";
        numberFormatException.printStackTrace();
        out.print(errorMsg);
    }


    try {
    } finally {
        out.close();
        try {
            if (conn != null) {
                conn.close();
            }  // return to pool
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}//end method

// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
 * Handles the HTTP
 * <code>GET</code> method.
 *
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}

/**
 * Handles the HTTP
 * <code>POST</code> method.
 *
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}

/**
 * Returns a short description of the servlet.
 *
 * @return a String containing servlet description
 */
@Override
public String getServletInfo() {
    return "Short description";
}// </editor-fold>
}

Now this is the receiving method on the client where the problem arises:

public void retrieveMessages(){
    try {
        URL url = new URL("http://"+server_name_or_ip+":8080/SecureChatEngine/MessageRetrieverServlet");

            HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
        urlCon.setDoInput(true);
        urlCon.setDoOutput(true);
              urlCon.setRequestMethod("POST");        
  urlCon.setRequestProperty("Content-type",
      "application/x-www-form-urlencoded");

  PrintWriter out = new PrintWriter( new OutputStreamWriter(
      urlCon.getOutputStream(  ), "8859_1"), true );
        StringBuilder sb = new StringBuilder("");
        sb.append(URLEncoder.encode("email","UTF-8"));
        sb.append("=");
        sb.append(URLEncoder.encode("gbenroscience@yahoo.com","UTF-8"));

           String formData = sb.toString();
           out.print(formData);
        out.flush();


   int contentLength = urlCon.getContentLength();
  byte[] raw = new byte[contentLength];
  int length = urlCon.getInputStream().read(raw);
  System.out.println("len = "+length);
  out.close();
/**
* The message retrieved here is incomplete..a truncated version of what is coming from the server, whereas 
* it should be the full version.
*/
String serverMsg = new String(raw, 0, length);    

}
catch(Exception e){
e.printStackTrace();
}

}//end method
4

2 回答 2

2

不能保证 read() 会填满缓冲区。请参阅 Javadoc。您必须循环阅读,直到 EOS。

于 2013-01-30T04:16:19.363 回答
1

@EJP 的答案是正确的,不能保证您一次读取就可以读取输入流。你需要循环如下......

BufferedReader in = null;
    StringBuilder sb = new StringBuilder();
    try {
        in = new BufferedReader(new InputStreamReader(urlCon.getInputStream()));
        String input = null;
        while((input=in.readLine())!=null) {
            sb.append(input);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(in!=null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    String serverMsg = sb.toString();
于 2013-01-30T04:58:58.780 回答