You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSP调用自定义打印方法无法在Tomcat网页正常显示输出问题

JSP调用自定义方法打印ResultSet无法在网页正常显示

我在Tomcat上运行Web应用,自定义了ResultsPrinter类的printResultSet方法,用System.out.println()打印ResultSet内容,但在JSP中调用时,输出没法在网页正常显示,预期的表格只会出现在Tomcat控制台里。

问题代码

ResultsPrinter类代码

public class ResultsPrinter {
    public static void printResultSet(ResultSet rs) throws SQLException {
        ResultSetMetaData resultSetMetaData = rs.getMetaData();
        int ColumnCount = resultSetMetaData.getColumnCount();
        int[] columnMaxLengths = new int[ColumnCount];
        ArrayList<String[]> results = new ArrayList<>();
        while (rs.next()) {
            String[] columnStr = new String[ColumnCount];
            for (int i = 0; i < ColumnCount; i++) {
                columnStr[i] = rs.getString(i + 1);
                columnMaxLengths[i] = Math.max(columnMaxLengths[i], (columnStr[i] == null)? 0 : columnStr[i].length());
            }
            results.add(columnStr);
        }
        printSeparator(columnMaxLengths);
        printColumnName(resultSetMetaData, columnMaxLengths);
        printSeparator(columnMaxLengths);
        Iterator<String[]> iterator = results.iterator();
        String[] columnStr;
        while (iterator.hasNext()) {
            columnStr = iterator.next();
            for (int i = 0; i < ColumnCount; i++) {
                System.out.printf("|%" + columnMaxLengths[i] + "s", columnStr[i]);
            }
            System.out.println("|");
        }
        printSeparator(columnMaxLengths);
    }

    private static void printColumnName(ResultSetMetaData resultSetMetaData, int[] columnMaxLengths) throws SQLException {
        int columnCount = resultSetMetaData.getColumnCount();
        for (int i = 0; i < columnCount; i++) {
            System.out.printf("|%" + columnMaxLengths[i] + "s", resultSetMetaData.getColumnName(i + 1));
        }
        System.out.println("|");
    }
    private static void printSeparator(int[] columnMaxLengths) {
        for (int columnMaxLength : columnMaxLengths) {
            System.out.print("+");
            for (int j = 0; j < columnMaxLength; j++) {
                System.out.print("-");
            }
        }
        System.out.println("+");
    }
}

JSP代码

<%
    try {
        ResultsPrinter.printResultSet(connector.query("show tables;"));
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
%>

问题原因

System.out.println()的输出目标是Tomcat服务器的控制台/日志文件,不是JSP用来向浏览器返回内容的响应输出流,所以网页上看不到任何输出。另外,即使把输出转到响应流,浏览器默认会忽略文本中的换行和连续空格,直接输出会导致格式混乱,需要用HTML的<pre>标签保留控制台样式的格式。

解决方案

方案1:修改方法输出到JSP响应流

修改ResultsPrinter类,让方法接收JSP内置的PrintWriter对象(代表响应输出流),将内容输出到浏览器:

import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

public class ResultsPrinter {
    public static void printResultSet(ResultSet rs, PrintWriter out) throws SQLException {
        ResultSetMetaData resultSetMetaData = rs.getMetaData();
        int columnCount = resultSetMetaData.getColumnCount();
        int[] columnMaxLengths = new int[columnCount];
        ArrayList<String[]> results = new ArrayList<>();
        
        while (rs.next()) {
            String[] columnStr = new String[columnCount];
            for (int i = 0; i < columnCount; i++) {
                columnStr[i] = rs.getString(i + 1);
                columnMaxLengths[i] = Math.max(columnMaxLengths[i], (columnStr[i] == null) ? 0 : columnStr[i].length());
            }
            results.add(columnStr);
        }

        // 用<pre>标签保留格式
        out.println("<pre>");
        printSeparator(columnMaxLengths, out);
        printColumnName(resultSetMetaData, columnMaxLengths, out);
        printSeparator(columnMaxLengths, out);
        
        Iterator<String[]> iterator = results.iterator();
        String[] columnStr;
        while (iterator.hasNext()) {
            columnStr = iterator.next();
            for (int i = 0; i < columnCount; i++) {
                out.printf("|%" + columnMaxLengths[i] + "s", columnStr[i]);
            }
            out.println("|");
        }
        
        printSeparator(columnMaxLengths, out);
        out.println("</pre>");
    }

    private static void printColumnName(ResultSetMetaData resultSetMetaData, int[] columnMaxLengths, PrintWriter out) throws SQLException {
        int columnCount = resultSetMetaData.getColumnCount();
        for (int i = 0; i < columnCount; i++) {
            out.printf("|%" + columnMaxLengths[i] + "s", resultSetMetaData.getColumnName(i + 1));
        }
        out.println("|");
    }

    private static void printSeparator(int[] columnMaxLengths, PrintWriter out) {
        for (int columnMaxLength : columnMaxLengths) {
            out.print("+");
            for (int j = 0; j < columnMaxLength; j++) {
                out.print("-");
            }
        }
        out.println("+");
    }
}

修改JSP代码,传入out对象:

<%
    try {
        ResultsPrinter.printResultSet(connector.query("show tables;"), out);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
%>

方案2:返回HTML格式字符串(推荐)

让方法返回拼接好的HTML字符串,再在JSP中输出,更符合Web开发的职责分离原则:

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;

public class ResultsPrinter {
    public static String getResultSetAsHtml(ResultSet rs) throws SQLException {
        StringBuilder htmlBuilder = new StringBuilder();
        ResultSetMetaData resultSetMetaData = rs.getMetaData();
        int columnCount = resultSetMetaData.getColumnCount();
        int[] columnMaxLengths = new int[columnCount];
        ArrayList<String[]> results = new ArrayList<>();
        
        while (rs.next()) {
            String[] columnStr = new String[columnCount];
            for (int i = 0; i < columnCount; i++) {
                columnStr[i] = rs.getString(i + 1);
                columnMaxLengths[i] = Math.max(columnMaxLengths[i], (columnStr[i] == null) ? 0 : columnStr[i].length());
            }
            results.add(columnStr);
        }

        htmlBuilder.append("<pre>");
        printSeparator(columnMaxLengths, htmlBuilder);
        printColumnName(resultSetMetaData, columnMaxLengths, htmlBuilder);
        printSeparator(columnMaxLengths, htmlBuilder);
        
        for (String[] columnStr : results) {
            for (int i = 0; i < columnCount; i++) {
                htmlBuilder.append(String.format("|%" + columnMaxLengths[i] + "s", columnStr[i]));
            }
            htmlBuilder.append("|\n");
        }
        
        printSeparator(columnMaxLengths, htmlBuilder);
        htmlBuilder.append("</pre>");
        
        return htmlBuilder.toString();
    }

    private static void printColumnName(ResultSetMetaData resultSetMetaData, int[] columnMaxLengths, StringBuilder sb) throws SQLException {
        int columnCount = resultSetMetaData.getColumnCount();
        for (int i = 0; i < columnCount; i++) {
            sb.append(String.format("|%" + columnMaxLengths[i] + "s", resultSetMetaData.getColumnName(i + 1)));
        }
        sb.append("|\n");
    }

    private static void printSeparator(int[] columnMaxLengths, StringBuilder sb) {
        for (int columnMaxLength : columnMaxLengths) {
            sb.append("+");
            for (int j = 0; j < columnMaxLength; j++) {
                sb.append("-");
            }
        }
        sb.append("+\n");
    }
}

JSP代码修改为:

<%
    try {
        String tableHtml = ResultsPrinter.getResultSetAsHtml(connector.query("show tables;"));
        out.print(tableHtml);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
%>

内容的提问来源于stack exchange,提问作者Allonsy Jia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 15:05:15