本帖最后由 liutianxiong888 于 2012-06-15 14:28:47 编辑

解决方案 »

  1.   

    你是在Servlet中做的操作么?
    那么不需要对out进行flush()也不需要做close(),容器自己会搞定这些操作的。另外,如果你返回的数据是XML,你缺少了<?XML 这个头信息。
    当然未必能消除你所面临的问题。不过我认为不应是flush()本身的问题,我觉得还是检查下 msg.toString() 输出的是啥。
      

  2.   

    在action中做的操作,不需要对out进行flush()也不需要做close(),意思是tomcat自己调用了flush()和close()?
    返回的是XML数据,没有带xml头信息!返回的数据都是在<data>下!
      

  3.   

    Tomcat自己当然会负责close(),close()之前就会自动flush()。XML标准就应该有头信息:
    <?xml version="1.0" encoding="UTF-8"?>
    <data>
      ...
    </data>
      

  4.   

    嗯,我知道XML标准是要带头信息的,这个客户端发送的请求数据也是<data>返回的也是<data>,没有按标准的来!
    msg.toString() 也就是StringBuffer()的toString()方法,这里面它new了个String,这是它的源码!public synchronized String toString() {
          return new String(value, 0, count);
    }
      

  5.   

    你用 System.out.println(msg.toString()); 显示的内容正确么?“自动加上大小及最后一个0”是增加在了 <data> 节点之前?
      

  6.   

    是的,<data>前有个以16进制表示的数据大小,</data>后有个0。
    System.out.println(msg.toString());这个肯定是正常的,因为写日志里面的时候是正常的,所以往控制台打印也是一样的!
      

  7.   

    源码片段有么?我觉得不可能是flush()的问题,从设计上它就没这个职能。
      

  8.   

    以下是整个方法的代码:public ActionForward getAppSortInfo(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) throws Exception {

    BufferedReader reader=null;
    String uid = null, sortid = null;
    int page = 0;
    StringBuffer msg=new StringBuffer("");
    StringBuffer sbf = new StringBuffer("");
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/get";//获取跟目录
    SAXReader sr = new SAXReader();
    Document doc;
    try {
    System.out.println(basePath);
    reader = request.getReader();
    doc = sr.read(reader);
    Element elm = doc.getRootElement(); uid = elm.elementTextTrim("uid");
    sortid = elm.elementTextTrim("sortid");
    page = "".equals(elm.elementTextTrim("page"))?0:Integer.parseInt(elm.elementTextTrim("page")); } catch (DocumentException e) {
    e.printStackTrace();
    } finally{
    if(null != reader) reader.close();
    }
    int list = page*20;
    String sql = "select app_name,app_packname,app_id,app_vscode,app_vsname,app_score,app_icon,app_apk,app_size from joye_et_app where app_sort="+sortid+" order by app_priority asc,app_regtime desc limit "+list+",20";
    Statement st = null;
    ResultSet rs = null;
    Connection conn = null;
    try {
    conn = DBConn.getConnection();
    st = conn.createStatement();
    rs = st.executeQuery(sql);
    while(rs.next()){
    sbf.append("<gtab>");
    sbf.append("<name>"+rs.getString("app_name").trim().replace("&", "&amp;")+"</name>");
    sbf.append("<pack>"+rs.getString("app_packname").replace("&", "&amp;")+"</pack>");
    sbf.append("<appid>"+rs.getString("app_id")+"</appid>");
    sbf.append("<vscode>"+rs.getString("app_vscode")+"</vscode>");
    sbf.append("<vsname>"+rs.getString("app_vsname")+"</vsname>");
    sbf.append("<score>"+rs.getString("app_score")+"</score>");
    String icon_url=rs.getString("app_icon");
    if(!icon_url.startsWith("http://"))
    icon_url=basePath+icon_url;
    sbf.append("<url>"+icon_url.replace("&", "&amp;")+"</url>");
    String apk_url=rs.getString("app_apk");
    if(!apk_url.startsWith("http://"))
    apk_url=basePath+apk_url;
    sbf.append("<apk>"+apk_url.replace("&", "&amp;")+"</apk>");
    sbf.append("<size>"+rs.getString("app_size")+"</size>");
    sbf.append("</gtab>");
    }
    HH:mm:ss").format(new Date()));
    }catch(SQLException ex){
    ex.printStackTrace();
    } finally{
    try {
    if(null != rs) rs.close();
    if(null != st) st.close();
    DBConn.close(conn);
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }

    response.setContentType("text/xml");
    response.setCharacterEncoding("utf-8");
    PrintWriter out=null;
    try {
    out=response.getWriter();
    msg.append("<data>");
    msg.append(sbf.toString());
    msg.append("</data>");
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    out.print(msg.toString());
                    //out.flush();
    out.close();
    return null;
    }

      

  9.   

    catch那里的HH:mm:ss").format(new Date()));这个是多了的,没删干净的!
      

  10.   

    从你的代码中,确实没看出有可疑的地方。不过 out.close() 这句是多余的。另外的怀疑就是,是否有其他的 filter 或者 action链 做了操作?
    干净点的测试就是:
    response.setContentType("text/xml");
    response.setCharacterEncoding("utf-8");
    PrintWriter out=null;
    try {
                out=response.getWriter();
    } catch (IOException e) {
                e.printStackTrace();
    }
    out.flush();
    out.close();然后再把out的flush()和close()都删掉,看看又有啥不一样的。
      

  11.   

    还有一个解决乱码的filter,就没了!
    之前的代码确实没有close();
    前面测试出问题,客户端那边就说检查一下有没有关闭流
    然后我就加上了close();后来想出还有个flush()清空缓存区的
    这样,二个方法我就同时加上了,可是还是不行!最后通过
    httpdebug工具查看到了,返回的数据前加上了:以16进制表示的数据大小,以及最后面加个0
    通过查找问题,发现是由于加上了flush()方法所导致
      

  12.   

    本地测试不出来你这个神奇的效果 =_=不过flush() 和 close() 确实是不需要的,尤其是close(),强行关闭输出流是中间件所不推荐的。
      

  13.   

    哦,你测试的是发送XML数据吗?
    我也不知道这是为什么,如果你不是flush()导致的,好像又没别的了啊!
      

  14.   

    除了不是用Struts,其它都差不多。
      

  15.   

    看下了servlet的api,查找到getWrite(),发现api中有这样一句:Calling flush() on the PrintWriter commits the response. 调用flush()在PrintWriter 提交响应!意思是说,flush()需要调用吗?
      

  16.   

    不需要,你随便找个Servlet,基本上都不会看到调用flush的,除非有很特殊的实时性需要。
      

  17.   

    怀疑是编码的问题.
    LZ的java文件是什么编码?客户端用的是什么编码?