用PrintWriter解决servlet的中文输出问题

在Java的Servlet中用ServletOutputStream.print()方法输出中文会有问题,如

ServletOutputStream out = response.getOutputStream();
out.print("你好");

在tomcat6会出现错误提示:
java.io.CharConversionException: Not an ISO 8859-1 character

在tomcat5或tomcat4能显示页面,但中文也是乱码。

解决办法:
 response.setCharacterEncoding("UTF-8"); (也可以是其他编码如GBK)
 response.setContentType("text/html");
或者直接
 response.setContentType("text/html;charset=UTF-8");

然后

PrintWriter out = response.getWriter();
 out.print("你好");
就能正常显示中文。

用此办法解决了proxool控制台org.logicalcobwebs.proxool.admin.servlet.AdminServlet不能显示中文的bug

该AdminServlet的doSnapshot()输出时间:

DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
 DATE_FORMAT.format(snapshot.getDateStarted())

正常应该显示如下格式:
 29-二月-2008 00:28:42

其中"月份"带了中文。

为了正常显示中文,把org.logicalcobwebs.proxool.admin.servlet.AdminServlet源代码抽出来修改

加入PrintWriter包:
 import java.io.PrintWriter;
将所有的ServletOutputStream用PrintWriter替换,所有的getOutputStream用getWriter替换

在doGet()中的response.setHeader("Pragma", "no-cache")语句后添加上编码:
        response.setCharacterEncoding("UTF-8");

编译该AdminServlet.java,运行一切ok!

附源代码:

另,对AdminServlet显示数据库连接url带用户名密码的bug做了修改:

String url= drillDownConnection.getDelegateUrl();

String[] urls=url.split("//?"); //这种方式只能解决mysql数据库的url,可以考虑

干脆不显示url,就能避免用户名密码暴露。

out.print(urls[0]);//Hide the user & password of url

----------------------------------

/**//*
 * This software is released under a licence similar to the Apache Software Licence.
 * See org.logicalcobwebs.proxool.package.html for details.
 * The latest version is available at http://proxool.sourceforge.net
 */
package org.logicalcobwebs.proxool.admin.servlet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logicalcobwebs.proxool.*;
import org.logicalcobwebs.proxool.admin.SnapshotIF;
import org.logicalcobwebs.proxool.admin.StatisticsIF;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;

/** *//**
 * Use this to admin each pool within Proxool. It acts like a normal
 * servlet., so just configure it within your web app as you see fit.
 * For example, within web.xml:
 * <pre>
 *   &lt;servlet&gt;
 *       &lt;servlet-name&gt;Admin&lt;/servlet-name&gt;
 *       &lt;servlet-class&gt;org.logicalcobwebs.proxool.admin.servlet.AdminServlet&lt;/servlet-class&gt;
 *       &lt;init-param&gt;
 *            &lt;param-name&gt;output&lt;/param-name&gt;
 *            &lt;param-value&gt;full|simple&lt;/param-value&gt;
 *        &lt;/init-param&gt;
 *        &lt;init-param&gt;
 *            &lt;param-name&gt;cssFile&lt;/param-name&gt;
 *            &lt;param-value&gt;/my_path/my.css&lt;/param-value&gt;
 *        &lt;/init-param&gt;
 *   &lt;/servlet&gt;
 *   &lt;servlet-mapping&gt;
 *       &lt;servlet-name&gt;Admin&lt;/servlet-name&gt;
 *       &lt;url-pattern&gt;/proxool&lt;/url-pattern&gt;
 *   &lt;/servlet-mapping&gt;
 * </pre>
 *
 * Options:
 * <ul>
 *   <li>output: full|simple. "full" means with HTML header and body tags "simple" means
 *   just the HTML. Choose "simple" if you are including this servlet within your own
 *   web page. Note that if you choose simple output then you're probably going to want
 *   to consider supplying some CSS to make it look nice.</li>
 *   <li>cssFile: If you choose full output (see above) then some CSS is included, inline,
 *   in the HTML header. If you specify a URL here then that file is also linked to. It is
 *   linked after the inline CSS so you only have to override thos styles you want to be
 *   different.</li>
 * </ul>
 *
 * @author bill
 * @author $Author: billhorsman $ (current maintainer)
 * @version $Revision: 1.14 $, $Date: 2006/06/09 17:32:54 $
 * @since Proxool 0.7
 * @modified by goodhumor $Date: 2008/02/29 00:28:42$
 */
public class AdminServlet extends HttpServlet ...{

    private static final Log LOG = LogFactory.getLog(ProxoolAdminServlet.class);

    /** *//**
     * The CSS class for a connection in different states:
     * <ul>
     *   <li>null</li>
     *   <li>available</li>
     *   <li>active</li>
     *   <li>offline</li>
     * </ul>
     */
    private static final String[] STATUS_CLASSES = ...{"null", "available", "active", "offline"};

    /** *//**
     * OUtput full HTML including &lt;HTML&gt;, &lt;HEAD&gt; and &lt;BODY&gt; tags.
     * @see #output
     * @see ProxoolAdminServlet configuration
     */
    public static final String OUTPUT_FULL = "full";

    /** *//**
     * OUtput simple HTML <em>excluding</em> &lt;HTML&gt;, &lt;HEAD&gt; and &lt;BODY&gt; tags.
     * @see #output
     * @see ProxoolAdminServlet configuration
     */
    public static final String OUTPUT_SIMPLE = "simple";

    /** *//**
     * Either {@link #OUTPUT_FULL} (default) or {@link #OUTPUT_SIMPLE}
     * @see ProxoolAdminServlet configuration
     */
    private String output;

    /** *//**
     * A valid URLL that can be linked to to override default, inline CSS.
     * @see ProxoolAdminServlet configuration
     */

    private String cssFile;

    /** *//**
     * Used as part of the CSS class
     */
    private static final String STATISTIC = "statistic";

    /** *//**
     * Used as part of the CSS class
     */
    private static final String CORE_PROPERTY = "core-property";

    /** *//**
     * Used as part of the CSS class
     */
    private static final String STANDARD_PROPERTY = "standard-property";

    /** *//**
     * Used as part of the CSS class
     */
    private static final String DELEGATED_PROPERTY = "delegated-property";

    /** *//**
     * Used as part of the CSS class
     */
    private static final String SNAPSHOT = "snapshot";

    public void init(ServletConfig servletConfig) throws ServletException ...{
        super.init(servletConfig);

        // Get output parameter. Default to OUTPUT_FULL.
        output = servletConfig.getInitParameter("output");
        if (output != null) ...{
            if (output.equalsIgnoreCase(OUTPUT_FULL)) ...{
                output = OUTPUT_FULL;
            } else if (output.equalsIgnoreCase(OUTPUT_SIMPLE)) ...{
                output = OUTPUT_SIMPLE;
            } else ...{
                LOG.warn("Unrecognised output parameter for " + this.getClass().getName() + ". Expected: " + OUTPUT_FULL + " or " + OUTPUT_SIMPLE);
                output = null;
            }
        }
        if (output == null) ...{
            output = OUTPUT_FULL;
        }

        cssFile = servletConfig.getInitParameter("cssFile");

    }

    /** *//**
     * HH:mm:ss
     * @see #formatMilliseconds
     */
    private static final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");

    /** *//**
     * dd-MMM-yyyy HH:mm:ss
     */
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00");

    private static final String DETAIL = "detail";
    private static final String DETAIL_MORE = "more";
    private static final String DETAIL_LESS = "less";

    /** *//**
     * The request parameter name that defines:
     * <ol>
     *   <li>{@link #TAB_DEFINITION} (default)</li>
     *   <li>{@link #TAB_SNAPSHOT}</li>
     *   <li>{@link #TAB_STATISTICS}</li>
     *  </ol>
     */
    private static final String TAB = "tab";

    /** *//**
     * @see #TAB
     */
    private static final String TAB_DEFINITION = "definition";

    /** *//**
     * @see #TAB
     */
    private static final String TAB_SNAPSHOT = "snapshot";

    /** *//**
     * @see #TAB
     */
    private static final String TAB_STATISTICS = "statistics";

    /** *//**
     * The request parameter name that defines the pool
     */
    private static final String ALIAS = "alias";

    /** *//**
     * If we are drilling down into a connection (on the {@link #TAB_SNAPSHOT snapshot} tab then
     * this points to the {@link org.logicalcobwebs.proxool.ProxyConnection#getId() ID} we are
     * getting detailed information for.
     */
    private static final String CONNECTION_ID = "id";

    /** *//**
     * Delegate to {@link #doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException ...{
        doGet(request, response);
    }

    /** *//**
     * Show the details for a pool.
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException ...{

        response.setHeader("Pragma", "no-cache");
        response.setCharacterEncoding("UTF-8");
        String link = request.getRequestURI();

        // Check the alias and if not defined and there is only one
        // then use that.
        String alias = request.getParameter(ALIAS);
        // Check we can find the pool.
        ConnectionPoolDefinitionIF def = null;
        if (alias != null) ...{
            try ...{
                def = ProxoolFacade.getConnectionPoolDefinition(alias);
            } catch (ProxoolException e) ...{
                alias = null;
            }
        }
        String[] aliases = ProxoolFacade.getAliases();
        if (alias == null) ...{
            if (aliases.length > 0) ...{
                alias = aliases[0];
            }
        }
        if (def == null && alias != null) ...{
            try ...{
                def = ProxoolFacade.getConnectionPoolDefinition(alias);
            } catch (ProxoolException e) ...{
                throw new ServletException("Couldn't find pool with alias " + alias);
            }
        }

        String tab = request.getParameter(TAB);
        if (tab == null) ...{
            tab = TAB_DEFINITION;
        }

        // If we are showing the snapshot, are we showing it in detail or not?
        String snapshotDetail = request.getParameter(DETAIL);

        // If we are showing the snapshot, are we drilling down into a connection?
        String snapshotConnectionId = request.getParameter(CONNECTION_ID);

        try ...{
            if (output.equals(OUTPUT_FULL)) ...{
                response.setContentType("text/html");

                openHtml(response.getWriter());
            }
            response.getWriter().println("<div class="version">Proxool " + Version.getVersion() + "</div>");
            doList(response.getWriter(), alias, tab, link);
            // Skip everything if there aren't any pools
            if (aliases != null && aliases.length > 0) ...{
                StatisticsIF[] statisticsArray = ProxoolFacade.getStatistics(alias);
                final boolean statisticsAvailable = (statisticsArray != null && statisticsArray.length > 0);
                final boolean statisticsComingSoon = def.getStatistics() != null;
                // We can't be on the statistics tab if there are no statistics
                if (!statisticsComingSoon && tab.equals(TAB_STATISTICS)) ...{
                    tab = TAB_DEFINITION;
                }
                doTabs(response.getWriter(), alias, link, tab, statisticsAvailable, statisticsComingSoon);
                if (tab.equals(TAB_DEFINITION)) ...{
                    doDefinition(response.getWriter(), def);
                } else if (tab.equals(TAB_SNAPSHOT)) ...{
                    doSnapshot(response.getWriter(), def, link, snapshotDetail, snapshotConnectionId);
                } else if (tab.equals(TAB_STATISTICS)) ...{
                    doStatistics(response.getWriter(), statisticsArray, def);
                } else ...{
                    throw new ServletException("Unrecognised tab '" + tab + "'");
                }
            }
        } catch (ProxoolException e) ...{
            throw new ServletException("Problem serving Proxool Admin", e);
        }

        if (output.equals(OUTPUT_FULL)) ...{
            closeHtml(response.getWriter());
        }

    }

    /** *//**
     * Output the tabs that we are showing at the top of the page
     * @param out where to write the HTNL to
     * @param alias the current pool
     * @param link the URL to get back to this servlet
     * @param tab the active tab
     * @param statisticsAvailable whether statistics are available (true if configured and ready)
     * @param statisticsComingSoon whether statistics will be available (true if configured but not ready yet)
     */
    private void doTabs(PrintWriter out, String alias, String link, String tab, boolean statisticsAvailable, boolean statisticsComingSoon) throws IOException ...{
        out.println("<ul>");
        out.println("<li class="" + (tab.equals(TAB_DEFINITION) ? "active" : "inactive") + ""><a class="quiet" href="" + link + "?alias=" + alias + "&tab=" + TAB_DEFINITION + "">Definition</a></li>");
        out.println("<li class="" + (tab.equals(TAB_SNAPSHOT) ? "active" : "inactive") + ""><a class="quiet" href="" + link + "?alias=" + alias + "&tab=" + TAB_SNAPSHOT + "">Snapshot</a></li>");
        if (statisticsAvailable) ...{
            out.println("<li class="" + (tab.equals(TAB_STATISTICS) ? "active" : "inactive") + ""><a class="quiet" href="" + link + "?alias=" + alias + "&tab=" + TAB_STATISTICS + "">Statistics</a></li>");
        } else if (statisticsComingSoon) ...{
            out.println("<li class="disabled">Statistics</li>");
        }
        out.println("</ul>");
    }

    /** *//**
     * Output the statistics. If there are more than one set of statistics then show them all.
     * @param out where to write HTML to
     * @param statisticsArray the statistics we have ready to see
     * @param cpd defines the connection
     */
    private void doStatistics(PrintWriter out, StatisticsIF[] statisticsArray, ConnectionPoolDefinitionIF cpd) throws IOException ...{

        for (int i = 0; i < statisticsArray.length; i++) ...{
            StatisticsIF statistics = statisticsArray[i];

            openDataTable(out);

            printDefinitionEntry(out, ProxoolConstants.ALIAS, cpd.getAlias(), CORE_PROPERTY);

            // Period
            printDefinitionEntry(out, "Period", TIME_FORMAT.format(statistics.getStartDate()) + " to " + TIME_FORMAT.format(statistics.getStopDate()), STATISTIC);

            // Served
            printDefinitionEntry(out, "Served", statistics.getServedCount() + " (" + DECIMAL_FORMAT.format(statistics.getServedPerSecond()) + "/s)", STATISTIC);

            // Refused
            printDefinitionEntry(out, "Refused", statistics.getRefusedCount() + " (" + DECIMAL_FORMAT.format(statistics.getRefusedPerSecond()) + "/s)", STATISTIC);

            // averageActiveTime
            printDefinitionEntry(out, "Average active time", DECIMAL_FORMAT.format(statistics.getAverageActiveTime() / 1000) + "s", STATISTIC);

            // activityLevel
            StringBuffer activityLevelBuffer = new StringBuffer();
            int activityLevel = (int) (100 * statistics.getAverageActiveCount() / cpd.getMaximumConnectionCount());
            activityLevelBuffer.append(activityLevel);
            activityLevelBuffer.append("%<br/>");
            String[] colours = ...{"0000ff", "eeeeee"};
            int[] lengths = ...{activityLevel, 100 - activityLevel};
            drawBarChart(activityLevelBuffer, colours, lengths);
            printDefinitionEntry(out, "Activity level", activityLevelBuffer.toString(), STATISTIC);

            closeTable(out);
        }
    }

    /** *//**
     * We can draw a bar chart simply enough. The two arrays passed as parameters must be of equal length
     * @param out where to write the HTML
     * @param colours the colur (CSS valid string) for each segment
     * @param lengths the length of each segment. Can be any size since the chart just takes up as much room
     * as possible as uses the relative length of each segment.
     */
    private void drawBarChart(StringBuffer out, String[] colours, int[] lengths) ...{
        out.append("<table style="margin: 8px; font-size: 50%;" width="100%" border="0" cellspacing="0" cellpadding="0"><tr>");

        // Calculate total length
        int totalLength = 0;
        for (int i = 0; i < colours.length; i++) ...{
            totalLength += lengths[i];
        }

        // Draw segments
        for (int j = 0; j < colours.length; j++) ...{
            String colour = colours[j];
            int length = lengths[j];
            if (length > 0) ...{
                out.append("<td style="background-color: #");
                out.append(colour);
                out.append("" width="");
                out.append(100 * length / totalLength);
                out.append("%">&nbsp;</td>");
            }
        }
        out.append("</tr></table>");
    }

    /** *//**
     * Output the {@link ConnectionPoolDefinitionIF definition}
     * @param out where to write the HTML
     * @param cpd the definition
     */
    private void doDefinition(PrintWriter out, ConnectionPoolDefinitionIF cpd) throws IOException ...{
        openDataTable(out);

        /**//*
            TODO: it would be nice to have meta-data in the definition so that this is much easier.
         */
        printDefinitionEntry(out, ProxoolConstants.ALIAS, cpd.getAlias(), CORE_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.DRIVER_URL, cpd.getUrl(), CORE_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.DRIVER_CLASS, cpd.getDriver(), CORE_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.MINIMUM_CONNECTION_COUNT, String.valueOf(cpd.getMinimumConnectionCount()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.MAXIMUM_CONNECTION_COUNT, String.valueOf(cpd.getMaximumConnectionCount()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.PROTOTYPE_COUNT, cpd.getPrototypeCount() > 0 ? String.valueOf(cpd.getPrototypeCount()) : null, STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.SIMULTANEOUS_BUILD_THROTTLE, String.valueOf(cpd.getSimultaneousBuildThrottle()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.MAXIMUM_CONNECTION_LIFETIME, formatMilliseconds(cpd.getMaximumConnectionLifetime()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.MAXIMUM_ACTIVE_TIME, formatMilliseconds(cpd.getMaximumActiveTime()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.HOUSE_KEEPING_SLEEP_TIME, (cpd.getHouseKeepingSleepTime() / 1000) + "s", STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.HOUSE_KEEPING_TEST_SQL, cpd.getHouseKeepingTestSql(), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.TEST_BEFORE_USE, String.valueOf(cpd.isTestBeforeUse()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.TEST_AFTER_USE, String.valueOf(cpd.isTestAfterUse()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.RECENTLY_STARTED_THRESHOLD, formatMilliseconds(cpd.getRecentlyStartedThreshold()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.OVERLOAD_WITHOUT_REFUSAL_LIFETIME, formatMilliseconds(cpd.getOverloadWithoutRefusalLifetime()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.INJECTABLE_CONNECTION_INTERFACE_NAME, String.valueOf(cpd.getInjectableConnectionInterface()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.INJECTABLE_STATEMENT_INTERFACE_NAME, String.valueOf(cpd.getInjectableStatementInterface()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.INJECTABLE_CALLABLE_STATEMENT_INTERFACE_NAME, String.valueOf(cpd.getInjectableCallableStatementInterface()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.INJECTABLE_PREPARED_STATEMENT_INTERFACE_NAME, String.valueOf(cpd.getInjectablePreparedStatementInterface()), STANDARD_PROPERTY);

        // fatalSqlExceptions
        String fatalSqlExceptions = null;
        if (cpd.getFatalSqlExceptions() != null && cpd.getFatalSqlExceptions().size() > 0) ...{
            StringBuffer fatalSqlExceptionsBuffer = new StringBuffer();
            Iterator i = cpd.getFatalSqlExceptions().iterator();
            while (i.hasNext()) ...{
                String s = (String) i.next();
                fatalSqlExceptionsBuffer.append(s);
                fatalSqlExceptionsBuffer.append(i.hasNext() ? ", " : "");
            }
            fatalSqlExceptions = fatalSqlExceptionsBuffer.toString();
        }
        printDefinitionEntry(out, ProxoolConstants.FATAL_SQL_EXCEPTION, fatalSqlExceptions, STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.FATAL_SQL_EXCEPTION_WRAPPER_CLASS, cpd.getFatalSqlExceptionWrapper(), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.STATISTICS, cpd.getStatistics(), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.STATISTICS_LOG_LEVEL, cpd.getStatisticsLogLevel(), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.VERBOSE, String.valueOf(cpd.isVerbose()), STANDARD_PROPERTY);
        printDefinitionEntry(out, ProxoolConstants.TRACE, String.valueOf(cpd.isTrace()), STANDARD_PROPERTY);
        // Now all the properties that are forwarded to the delegate driver.
        Properties p = cpd.getDelegateProperties();
        Iterator i = p.keySet().iterator();
        while (i.hasNext()) ...{
            String name = (String) i.next();
            String value = p.getProperty(name);
            // Better hide the password!
            if (name.toLowerCase().indexOf("password") > -1 || name.toLowerCase().indexOf("passwd") > -1) ...{
                value = "******";
            }
            printDefinitionEntry(out, name + " (delegated)", value, DELEGATED_PROPERTY);
        }

        closeTable(out);

    }

    /** *//**
     * Output a {@link SnapshotIF snapshot} of the pool.
     * @param out where to write the HTML
     * @param cpd defines the pool
     * @param link the URL back to this servlet
     * @param level either {@link #DETAIL_LESS} or {@link #DETAIL_MORE}
     * @param connectionId the connection we want to drill into (optional)
     */
    private void doSnapshot(PrintWriter out, ConnectionPoolDefinitionIF cpd, String link, String level, String connectionId) throws IOException, ProxoolException ...{
        boolean detail = (level != null && level.equals(DETAIL_MORE));
        SnapshotIF snapshot = ProxoolFacade.getSnapshot(cpd.getAlias(), detail);

        if (snapshot != null) ...{

            openDataTable(out);

            printDefinitionEntry(out, ProxoolConstants.ALIAS, cpd.getAlias(), CORE_PROPERTY);

            // dateStarted
            printDefinitionEntry(out, "Start date", DATE_FORMAT.format(snapshot.getDateStarted()), SNAPSHOT);

            // snapshot date
            printDefinitionEntry(out, "Snapshot", TIME_FORMAT.format(snapshot.getSnapshotDate()), SNAPSHOT);

            // connections
            StringBuffer connectionsBuffer = new StringBuffer();
            connectionsBuffer.append(snapshot.getActiveConnectionCount());
            connectionsBuffer.append(" (active), ");
            connectionsBuffer.append(snapshot.getAvailableConnectionCount());
            connectionsBuffer.append(" (available), ");
            if (snapshot.getOfflineConnectionCount() > 0) ...{
                connectionsBuffer.append(snapshot.getOfflineConnectionCount());
                connectionsBuffer.append(" (offline), ");
            }
            connectionsBuffer.append(snapshot.getMaximumConnectionCount());
            connectionsBuffer.append(" (max)<br/>");
            String[] colours = ...{"ff9999", "66cc66", "cccccc"};
            int[] lengths = ...{snapshot.getActiveConnectionCount(), snapshot.getAvailableConnectionCount(),
                    snapshot.getMaximumConnectionCount() - snapshot.getActiveConnectionCount() - snapshot.getAvailableConnectionCount()};
            drawBarChart(connectionsBuffer, colours, lengths);
            printDefinitionEntry(out, "Connections", connectionsBuffer.toString(), SNAPSHOT);

            // servedCount
            printDefinitionEntry(out, "Served", String.valueOf(snapshot.getServedCount()), SNAPSHOT);

            // refusedCount
            printDefinitionEntry(out, "Refused", String.valueOf(snapshot.getRefusedCount()), SNAPSHOT);

            if (!detail) ...{
                out.println("    <tr>");
                out.print("        <td colspan="2" align="right"><form action="" + link + "" method="GET">");
                out.print("<input type="hidden" name="" + ALIAS + "" value="" + cpd.getAlias() + "">");
                out.print("<input type="hidden" name="" + TAB + "" value="" + TAB_SNAPSHOT + "">");
                out.print("<input type="hidden" name="" + DETAIL + "" value="" + DETAIL_MORE + "">");
                out.print("<input type="submit" value="More information&gt;">");
                out.println("</form></td>");
                out.println("    </tr>");
            } else ...{

                out.println("    <tr>");
                out.print("      <th width="200" valign="top">");
                out.print("Details:<br>(click ID to drill down)");
                out.println("</th>");
                out.print("      <td>");

                doSnapshotDetails(out, cpd, snapshot, link, connectionId);

                out.println("</td>");
                out.println("    </tr>");

                long drillDownConnectionId;
                if (connectionId != null) ...{
                    drillDownConnectionId = Long.valueOf(connectionId).longValue();
                    ConnectionInfoIF drillDownConnection = snapshot.getConnectionInfo(drillDownConnectionId);
                    if (drillDownConnection != null) ...{
                        out.println("    <tr>");
                        out.print("      <th valign="top">");
                        out.print("Connection #" + connectionId);
                        out.println("</td>");
                        out.print("      <td>");

                        doDrillDownConnection(out, drillDownConnection);

                        out.println("</td>");
                        out.println("    </tr>");
                    }
                }

                out.println("    <tr>");
                out.print("        <td colspan="2" align="right"><form action="" + link + "" method="GET">");
                out.print("<input type="hidden" name="" + ALIAS + "" value="" + cpd.getAlias() + "">");
                out.print("<input type="hidden" name="" + TAB + "" value="" + TAB_SNAPSHOT + "">");
                out.print("<input type="hidden" name="" + DETAIL + "" value="" + DETAIL_LESS + "">");
                out.print("<input type="submit" value="&lt; Less information">");
                out.println("</form></td>");
                out.println("    </tr>");
            }

            closeTable(out);
        }
    }

    /** *//**
     * If we want a {@link #DETAIL_MORE more} detailed {@link SnapshotIF snapshot} then {@link #doSnapshot(javax.servlet.PrintWriter, org.logicalcobwebs.proxool.ConnectionPoolDefinitionIF, String, String, String)}
     * calls this too
     * @param out where to write the HTML
     * @param cpd defines the pool
     * @param snapshot snapshot
     * @param link the URL back to this servlet
     * @param connectionId the connection we want to drill into (optional)
     * @param connectionId
     * @throws IOException
     */
    private void doSnapshotDetails(PrintWriter out, ConnectionPoolDefinitionIF cpd, SnapshotIF snapshot, String link, String connectionId) throws IOException ...{

        long drillDownConnectionId = 0;
        if (connectionId != null) ...{
            drillDownConnectionId = Long.valueOf(connectionId).longValue();
        }

        if (snapshot.getConnectionInfos() != null && snapshot.getConnectionInfos().length > 0) ...{
            out.println("<table cellpadding="2" cellspacing="0" border="0">");
            out.println("  <tbody>");

            out.print("<tr>");
            out.print("<td>#</td>");
            out.print("<td align="center">born</td>");
            out.print("<td align="center">last<br>start</td>");
            out.print("<td align="center">lap<br>(ms)</td>");
            out.print("<td>&nbsp;thread</td>");
            out.print("</tr>");

            ConnectionInfoIF[] connectionInfos = snapshot.getConnectionInfos();
            for (int i = 0; i < connectionInfos.length; i++) ...{
                ConnectionInfoIF connectionInfo = connectionInfos[i];

                if (connectionInfo.getStatus() != ConnectionInfoIF.STATUS_NULL) ...{

                    out.print("<tr>");

                    // drillDownConnectionId
                    out.print("<td style="background-color: #");
                    if (connectionInfo.getStatus() == ConnectionInfoIF.STATUS_ACTIVE) ...{
                        out.print("ffcccc");
                    } else if (connectionInfo.getStatus() == ConnectionInfoIF.STATUS_AVAILABLE) ...{
                        out.print("ccffcc");
                    } else if (connectionInfo.getStatus() == ConnectionInfoIF.STATUS_OFFLINE) ...{
                        out.print("ccccff");
                    }
                    out.print("" style="");

                    if (drillDownConnectionId == connectionInfo.getId()) ...{
                        out.print("border: 1px solid black;");
                        out.print("">");
                        out.print(connectionInfo.getId());
                    } else ...{
                        out.print("border: 1px solid transparent;");
                        out.print(""><a href="");
                        out.print(link);
                        out.print("?");
                        out.print(ALIAS);
                        out.print("=");
                        out.print(cpd.getAlias());
                        out.print("&");
                        out.print(TAB);
                        out.print("=");
                        out.print(TAB_SNAPSHOT);
                        out.print("&");
                        out.print(DETAIL);
                        out.print("=");
                        out.print(DETAIL_MORE);
                        out.print("&");
                        out.print(CONNECTION_ID);
                        out.print("=");
                        out.print(connectionInfo.getId());
                        out.print("">");
                        out.print(connectionInfo.getId());
                        out.print("</a>");
                    }
                    out.print("</td>");

                    // birth
                    out.print("<td>&nbsp;");
                    out.print(TIME_FORMAT.format(connectionInfo.getBirthDate()));
                    out.print("</td>");

                    // started
                    out.print("<td>&nbsp;");
                    out.print(connectionInfo.getTimeLastStartActive() > 0 ? TIME_FORMAT.format(new Date(connectionInfo.getTimeLastStartActive())) : "-");
                    out.print("</td>");

                    // active
                    out.print("<td align="right" class="");
                    out.print(getStatusClass(connectionInfo));
                    out.print("">");
                    String active = "&nbsp;";
                    if (connectionInfo.getTimeLastStopActive() > 0) ...{
                        active = String.valueOf((int) (connectionInfo.getTimeLastStopActive() - connectionInfo.getTimeLastStartActive()));
                    } else if (connectionInfo.getTimeLastStartActive() > 0) ...{
                        active = String.valueOf((int) (snapshot.getSnapshotDate().getTime() - connectionInfo.getTimeLastStartActive()));
                    }
                    out.print(active);
                    out.print("&nbsp;&nbsp;</td>");

                    // requester
                    out.print("<td>&nbsp;");
                    out.print(connectionInfo.getRequester() != null ? connectionInfo.getRequester() : "-");
                    out.print("</td>");

                    out.println("</tr>");
                }
            }
            out.println("  </tbody>");
            out.println("</table>");

        } else ...{
            out.println("No connections yet");
        }
    }

    /** *//**
     * What CSS class to use for a particular connection.
     * @param info so we know the {@link org.logicalcobwebs.proxool.ConnectionInfoIF#getStatus()} status
     * @return the CSS class
     * @see #STATUS_CLASSES
     */
    private static String getStatusClass(ConnectionInfoIF info) ...{
        try ...{
            return STATUS_CLASSES[info.getStatus()];
        } catch (ArrayIndexOutOfBoundsException e) ...{
            LOG.warn("Unknown status: " + info.getStatus());
            return "unknown-" + info.getStatus();
        }
    }

    private void doDrillDownConnection(PrintWriter out, ConnectionInfoIF drillDownConnection) throws IOException ...{

        // sql calls
        String[] sqlCalls = drillDownConnection.getSqlCalls();
        for (int i = 0; sqlCalls != null && i < sqlCalls.length; i++) ...{
            String sqlCall = sqlCalls[i];
            out.print("<div class="drill-down">");
            out.print("sql = ");
            out.print(sqlCall);
            out.print("</div>");
        }

        // proxy
        out.print("<div class="drill-down">");
        out.print("proxy = ");
        out.print(drillDownConnection.getProxyHashcode());
        out.print("</div>");

        // delegate
        out.print("<div class="drill-down">");
        out.print("delegate = ");
        out.print(drillDownConnection.getDelegateHashcode());
        out.print("</div>");

        // url
        String url= drillDownConnection.getDelegateUrl();
        String[] urls=url.split("/?");    //Hide the user & password of url
        out.print("<div class="drill-down">");
        out.print("url = ");
        out.print(urls[0]);
        out.print("</div>");

    }

    private void openHtml(PrintWriter out) throws IOException ...{
        out.println("<html><header><title>Proxool Admin</title>");
        out.println("<style media="screen">");
        out.println("body {background-color: #93bde6;} " +
                "div.version {font-weight: bold; font-size: 100%; margin-bottom: 8px;} " +
                "h1 {font-weight: bold; font-size: 100%} " +
                "option {padding: 2px 24px 2px 4px;} " +
                "input {margin: 0px 0px 4px 12px;} " +
                "table.data {font-size: 90%; border-collapse: collapse; border: 1px solid black;} " +
                "table.data th {background: #bddeff; width: 25em; text-align: left; padding-right: 8px; font-weight: normal; border: 1px solid black;} " +
                "table.data td {background: #ffffff; vertical-align: top; padding: 0px 2px 0px 2px; border: 1px solid black;} " +
                "td.null {background: yellow;} " +
                "td.available {color: black;} " +
                "td.active {color: red;} " +
                "td.offline {color: blue;} " +
                "div.drill-down {} " +
                "ul {list-style: none; padding: 0px; margin: 0px; position: relative; font-size: 90%;} " +
                "li {padding: 0px; margin: 0px 4px 0px 0px; display: inline; border: 1px solid black; border-width: 1px 1px 0px 1px;} " +
                "li.active {background: #bddeff;} " +
                "li.inactive {background: #eeeeee;} " +
                "li.disabled {background: #dddddd; color: #999999; padding: 0px 4px 0px 4px;} " +
                "a.quiet {color: black; text-decoration: none; padding: 0px 4px 0px 4px; } " +
                "a.quiet:hover {background: white;} ");
        out.println("</style>");
        // If we have configured a cssFile then that will override what we have above
        if (cssFile != null) ...{
            out.println("<link rel="stylesheet" media="screen" type="text/css" href="" + cssFile + ""></script>");
        }
        out.println("</header><body>");
    }

    private void closeHtml(PrintWriter out) throws IOException ...{
        out.println("</body></html>");
    }

    private void openDataTable(PrintWriter out) throws IOException ...{
        out.println("<table cellpadding="2" cellspacing="0" border="1" class="data">");
        out.println("  <tbody>");
    }

    private void closeTable(PrintWriter out) throws IOException ...{
        out.println("  </tbody>");
        out.println("</table>");
        out.println("<br/>");
    }

    private void printDefinitionEntry(PrintWriter out, String name, String value, String type) throws IOException ...{
        out.println("    <tr>");
        out.print("      <th valign="top">");
        out.print(name);
        out.println(":</th>");
        out.print("      <td class="" + type + ""nowrap>");
        if (value != null && !value.equals("null")) ...{
            out.print(value);
        } else ...{
            out.print("-");
        }
        out.print("</td>");
        out.println("    </tr>");
    }

    /** *//**
     * Output the list of available connection pools. If there are none then display a message saying that.
     * If there is only one then just display nothing (and the pool will displayed by default)
     * @param out where to write the HTML
     * @param alias identifies the current pool
     * @param tab identifies the tab we are on so that changing pools doesn't change the tab
     * @param link the URL back to this servlet
     */
    private void doList(PrintWriter out, String alias, String tab, String link) throws IOException ...{

        String[] aliases = ProxoolFacade.getAliases();

        if (aliases.length == 0) ...{
            out.println("<p>No pools have been registered.</p>");
        } else if (aliases.length == 1) ...{
            // Don't bother listing. Just show it.
        } else ...{
            out.println("<form action="" + link + "" method="GET" name="alias">");
            out.println("<select name="alias" size="" + Math.min(aliases.length, 5) + "">");
            for (int i = 0; i < aliases.length; i++) ...{
                out.print("  <option value="");
                out.print(aliases[i]);
                out.print(""");
                out.print(aliases[i].equals(alias) ? " selected" : "");
                out.print(">");
                out.print(aliases[i]);
                out.println("</option>");
            }
            out.println("</select>");
            out.println("<input name="" + TAB + "" value="" + tab + "" type="hidden">");
            out.println("<input value="Show" type="submit">");
            out.println("</form>");
        }
    }

    /** *//**
     * Express time in an easy to read HH:mm:ss format
     *
     * @param time in milliseconds
     * @return time (e.g. 180000 = 00:30:00)
     * @see #TIME_FORMAT
     */
    private String formatMilliseconds(int time) ...{
        Calendar c = Calendar.getInstance();
        c.clear();
        c.add(Calendar.MILLISECOND, time);
        return TIME_FORMAT.format(c.getTime());
    }
}

/**//*
Revision history:
$Log: ProxoolAdminServlet.java,v $
Revision 1.14  2006/06/09 17:32:54  billhorsman
Fix closing tag for select. Credit to Paolo Di Tommaso.

Revision 1.13  2006/01/18 14:39:56  billhorsman
Unbundled Jakarta's Commons Logging.

Revision 1.12  2005/10/07 08:23:10  billhorsman
Doc

Revision 1.11  2005/10/02 09:45:49  billhorsman
Layout

Revision 1.10  2005/09/26 21:47:46  billhorsman
no message

Revision 1.9  2005/09/26 13:31:14  billhorsman
Smartened up ProxoolAdminServlet

Revision 1.8  2003/09/29 17:49:19  billhorsman
Includes new fatal-sql-exception-wrapper-class in display

Revision 1.7  2003/08/06 20:08:58  billhorsman
fix timezone display of time (for millisecond based properties)

Revision 1.6  2003/03/10 23:43:14  billhorsman
reapplied checkstyle that i'd inadvertently let
IntelliJ change...

Revision 1.5  2003/03/10 15:26:51  billhorsman
refactoringn of concurrency stuff (and some import
optimisation)

Revision 1.4  2003/03/03 11:12:00  billhorsman
fixed licence

Revision 1.3  2003/02/26 16:59:18  billhorsman
fixed spelling error in method name

Revision 1.2  2003/02/26 16:51:12  billhorsman
fixed units for average active time. now displays
properly in seconds

Revision 1.1  2003/02/24 10:19:44  billhorsman
moved ProxoolAdminServlet into servlet package

Revision 1.1  2003/02/19 23:36:51  billhorsman
renamed monitor package to admin

Revision 1.10  2003/02/12 12:28:27  billhorsman
added url, proxyHashcode and delegateHashcode to
ConnectionInfoIF

Revision 1.9  2003/02/11 00:30:28  billhorsman
add version

Revision 1.8  2003/02/06 17:41:05  billhorsman
now uses imported logging

Revision 1.7  2003/02/06 15:42:21  billhorsman
display changes

Revision 1.6  2003/02/05 17:04:02  billhorsman
fixed date format

Revision 1.5  2003/02/05 15:06:16  billhorsman
removed dependency on JDK1.4 imaging.

Revision 1.4  2003/01/31 16:53:21  billhorsman
checkstyle

Revision 1.3  2003/01/31 16:38:52  billhorsman
doc (and removing public modifier for classes where possible)

Revision 1.2  2003/01/31 11:35:57  billhorsman
improvements to servlet (including connection details)

Revision 1.1  2003/01/31 00:38:22  billhorsman
*** empty log message ***

*/

用PrintWriter解决proxool servlet的中文输出问题相关推荐

  1. 解决 IntelliJ IDEA Tomcat 控制台中文输出乱码问题

    解决 IntelliJ IDEA Tomcat 控制台中文输出乱码问题 参考文章: (1)解决 IntelliJ IDEA Tomcat 控制台中文输出乱码问题 (2)https://www.cnbl ...

  2. Jenkins控制台中文输出乱码解决方法

    Jenkins控制台中文输出乱码解决方法 参考文章: (1)Jenkins控制台中文输出乱码解决方法 (2)https://www.cnblogs.com/dreamer-fish/p/1181204 ...

  3. python语言支持中文输出_python2输出汉字的解决办法暨python2/python3的编码环境参数的查看-Go语言中文社区...

    版权声明:转载请注明作者(独孤尚良dugushangliang)出处: https://blog.csdn.net/dugushangliang/article/details/89944870 本来 ...

  4. Pycharm控制台中文输出乱码怎么办?控制台输出乱码问题的解决方法

    Pycharm控制台中文输出乱码怎么办?控制台输出乱码问题的解决方法 **1. 乱码显示** **2. 乱码显示** **3. 乱码显示等等** 快捷操作:可选择文章目录来快速直达查看 文章目录 Py ...

  5. mysql执行语句出来全是问号_解决MySQL中文输出变成问号的问题

    解决MySQL中文输出变成问号的问题 于是我在程序中加入:mysql_query("SET NAMES GB2312");问题迎刃而解.主要是一个编码问题. 注意这句代码的插入位置 ...

  6. centos java 乱码,linux(centos7)下程序中文输出乱码问题的解决

    目前的程序代码都是在window编写,编码格式为GBK.转移到linux下,编译正常,在控制台运行时中文输出为乱码.查linux的LANG发现为UTF-8,于是修改为GBK.再次运行程序,依然为乱码. ...

  7. JAVA运行时中文输出乱码原因与解决

    JAVA运行时中文输出乱码 public class project1 { public static void main(String[] args) {System.out.println(&qu ...

  8. c语言程序编译输出乱码,解决VC++编译程序出现中文乱码的问题

    大家在使用VC++进行编译的时候,是否都会遇见一种情况,那就是编译以后出现了中文代码.小编觉得,这一种情况还是比较普遍的.那么为了可以解决大家的难题,今天小编就教大家解决VC++编译程序出现中文乱码的 ...

  9. Java Servlet API中文说明文档

    Java Servlet API中文说明文档 目 录 1.... Servet资料 1.1      绪言 1.2      谁需要读这份文档 1.3      Java Servlet API的组成 ...

最新文章

  1. 如何查找Authorization object在哪些ABAP代码里使用到
  2. python 数据分析学什么-从零开始学数据分析,什么程度可以找工作?
  3. android 圆滑曲线,如何使用贝塞尔曲线在一组点上绘制平滑线?
  4. mysql根据bin log恢复_MySQL 通过 binlog 恢复数据
  5. R 语言数据读取与存储
  6. Action类中通过ServletActionContext来获取web资源
  7. 敏捷开发用户故事系列之二:如何面向客户价值编写故事
  8. 城管威逼交警“让老百姓笑话”
  9. servlet返回数据给html_Servlet 简介
  10. 速途网范锋:我的创业路早已命中注定
  11. Astar2007初赛第一场的题目2
  12. 每天学点linux之-mkdir和cd
  13. 提示wininet.dll文件找不到的解决
  14. Android 事件拦截分发
  15. 墨菲定律: If anything can go wrong,it will.
  16. 【Lua】【协同程序】【coroutine】知识点详解
  17. Python - 随机生成英文字母
  18. L3-020 至多删三个字符 (30 分)
  19. 杰出校友王章清董事长
  20. 领导拒绝涨薪?我直接跳槽,涨薪6k

热门文章

  1. 浅析油田有线数字电视机顶盒发放策略
  2. 报告| 7月区块链游戏行业全景:玩赚游戏持续火爆,链游用户指数级增长
  3. 说说事业单位教师入编体检详细流程怎样预防体检不合格
  4. 商品进销差价_商品进销差价的核算方法总结(1)
  5. Discuz!NT论坛添加背景音乐
  6. 哪些情况下适合发短信?
  7. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java社团管理系统85143
  8. python画图设置彩色线条_更改绘图中的线条颜色
  9. 内存越界导致的原因:
  10. 河内塔c语言编程,〖C语言程序设计〗汉诺塔游戏