spring boot开发web api应用实践(四)为proxool连接池增加管理页面

proxool默认提供了org.logicalcobwebs.proxool.admin.servlet.AdminServlet类,为用户提供页面查看连接池情况,包括连接池的配置信息、连接池连接的使用情况等。唯一缺陷是没有访问控制,人人都可访问(或许有,而我不知道)。本例重写AdminServlet类增加登录控制,并且增加Servlet3.0的@WebServlet注解。为简单起见,登录所用的用户名/密码直接写入AdminServlet类中。

为方便AppMain类启动时扫描到,将该类放在AppMain类所在的com.zweixhxu.springboot包的子包proxool里

AdminServlet.java

package com.zweixhxu.springboot.proxool;

import org.logicalcobwebs.proxool.*;
import org.logicalcobwebs.proxool.admin.SnapshotIF;
import org.logicalcobwebs.proxool.admin.StatisticsIF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebInitParam;
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;
 
@WebServlet(urlPatterns="/proxoolPool", initParams={  
        @WebInitParam(name= AdminServlet.PARAM_USER_NAME, value="proxool"),  
        @WebInitParam(name= AdminServlet.PARAM_LOGIN_PASS, value= "proxool@123"),  
})
public class AdminServlet extends HttpServlet {

    protected static final Logger LOG = LoggerFactory.getLogger(AdminServlet.class);
 
    private static final String[] STATUS_CLASSES = {"null", "available", "active", "offline"};
 
    public static final String OUTPUT_FULL = "full";
 
    public static final String OUTPUT_SIMPLE = "simple";
 
    private String output;
 
    private String cssFile;
 
    private static final String STATISTIC = "statistic";
 
    private static final String CORE_PROPERTY = "core-property";
 
    private static final String STANDARD_PROPERTY = "standard-property";
 
    private static final String DELEGATED_PROPERTY = "delegated-property";

    protected static final String PARAM_REQ_ID = "requestId";
    protected static final String PARAM_OP_TYPE = "opType";
    public static final String PARAM_USER_NAME = "userName";
    public static final String PARAM_LOGIN_PASS = "loginPass";
    
    protected static final String OP_TYPE_LOGIN = "login";
     
    private static final String SNAPSHOT = "snapshot";

    private static String loginName = "proxool";
    private static String loginPass = "proxool@123456";
    
    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 {}. Expected: {} or {}", this.getClass().getName(), OUTPUT_FULL, OUTPUT_SIMPLE);
                output = null;
            }
        }
        if (output == null) {
            output = OUTPUT_FULL;
        }

        loginName = servletConfig.getInitParameter(PARAM_USER_NAME);
        loginPass = servletConfig.getInitParameter(PARAM_LOGIN_PASS);
        cssFile = servletConfig.getInitParameter("cssFile");

    }
 
    private static final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
 
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    private static final DateFormat DATE_FORMAT_M = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

    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";

    protected static final String LOGIN_SESSION_KEY = "dbPoolLoginUser";
    
    protected boolean checkNotLogin(HttpServletRequest request, HttpServletResponse response, String requestId){
        return request.getSession().getAttribute(LOGIN_SESSION_KEY)==null;
    }
    
    protected boolean doLogin(HttpServletRequest request, HttpServletResponse response){
        String userName = request.getParameter(PARAM_USER_NAME);
        String pwd = request.getParameter(PARAM_LOGIN_PASS); 
        
        if (!loginName.equals(userName) || !loginPass.equals(pwd)){
            LOG.error("用户{}登录失败,用户名或密码失败", userName);
            return false;
        }
        
        doLoginSuccess(request, response, userName+"="+pwd); 
        return true;
    }
    
    protected void doLoginSuccess(HttpServletRequest request, HttpServletResponse response, Object result){
        request.getSession().setAttribute(LOGIN_SESSION_KEY, result);
    }

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

    /**
     * Show the details for a pool.
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Pragma", "no-cache");
        PrintWriter out = response.getWriter();
        String link = request.getRequestURI();
        
        String opType = request.getParameter(PARAM_OP_TYPE); 
        String requestId = request.getParameter(PARAM_REQ_ID);
        LOG.debug("ProxoolAdmin>opType={}, \"{}\".equals(opType) => {}", opType, OP_TYPE_LOGIN, OP_TYPE_LOGIN.equals(opType));
        if (OP_TYPE_LOGIN.equals(opType)){
            try{
                if (doLogin(request, response)){
                    requestId = request.getSession().getId();
                }else{ 
                    failedAndDispalyLoginPage("用户名或密码错误,登录失败", response, out, link);
                    return;
                } 
            }catch(Exception e){
                failedAndDispalyLoginPage("系统异常:" + e.toString(), response, out, link);
                return;
            }
        }
        
        if ("logout".equals(opType)){
            doLogout(request, response);
        }
         
        if (requestId==null || checkNotLogin(request, response, requestId)){
            failedAndDispalyLoginPage("", response, out, link); 
            return;
        }
        
        // 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(out);
            }
            out.println("<div class=\"version\">Proxool " + Version.getVersion() + "&nbsp;&nbsp;&nbsp;<a href=\""+link+"?opType=logout&"+PARAM_REQ_ID+"="+requestId+"\">退出登录</a>");
            out.println("</div>");
            doList(out, 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(out, alias, link, requestId, tab, statisticsAvailable, statisticsComingSoon);
                if (tab.equals(TAB_DEFINITION)) {
                    doDefinition(out, def);
                } else if (tab.equals(TAB_SNAPSHOT)) {
                    doSnapshot(out, def, link, snapshotDetail, snapshotConnectionId, requestId);
                } else if (tab.equals(TAB_STATISTICS)) {
                    doStatistics(out, 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(out);
        }

    }
    
    private void failedAndDispalyLoginPage(String failMsg, HttpServletResponse response, PrintWriter out, String link) throws IOException{
        response.setContentType("text/html");
        openHtml(out);
        displayLoginForm(out, link);
        out.println("<div style='color:red;'>" + failMsg +"</div>");
        closeHtml(out);
    }
 
    private void doTabs(PrintWriter out, String alias, String link, String requestId, 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 + "&"+PARAM_REQ_ID+"=" + requestId + "&tab=" + TAB_DEFINITION + "\">Definition</a></li>");
        out.println("<li class=\"" + (tab.equals(TAB_SNAPSHOT) ? "active" : "inactive") + "\"><a class=\"quiet\" href=\"" + link + "?alias=" + alias + "&"+PARAM_REQ_ID+"=" + requestId + "&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 + "&"+PARAM_REQ_ID+"=" + requestId + "&tab=" + TAB_STATISTICS + "\">Statistics</a></li>");
        } else if (statisticsComingSoon) {
            out.println("<li class=\"disabled\">Statistics</li>");
        }
        out.println("</ul>");
    }
 
    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);
        }
    }
 
    private void drawBarChart(StringBuffer out, String[] colours, int[] lengths) {
        out.append("<table style=\"margin: 8px; font-size: 50%;\" width=\"96%\" 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>");
    }
 
    private void doDefinition(PrintWriter out, ConnectionPoolDefinitionIF cpd) throws IOException {
        openDataTable(out);
 
        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);

    }
 
    private void doSnapshot(PrintWriter out, ConnectionPoolDefinitionIF cpd, String link, String level, String connectionId, String requestId) 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", DATE_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=\"hidden\" name=\"" + PARAM_REQ_ID + "\" value=\"" + (requestId==null?"":requestId) + "\">");
                out.print("<input type=\"submit\" value=\"More information&gt;\">");
                out.println("</form></td>");
                out.println("    </tr>");
            } else {

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

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

                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);
        }
    }
 
    private void doSnapshotDetails(PrintWriter out, ConnectionPoolDefinitionIF cpd, SnapshotIF snapshot, String link, String connectionId, String requestId) 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 start</td>");
            out.print("<td align=\"center\">last stop</td>");
            out.print("<td align=\"center\">lap (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(PARAM_REQ_ID);
                        out.print("=");
                        out.print(requestId==null?"":requestId);
                        out.print("\">");
                        out.print(connectionInfo.getId());
                        out.print("</a>");
                    }
                    out.print("</td>");

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

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

                    // stop
                    out.print("<td>&nbsp;");
                    out.print(connectionInfo.getTimeLastStopActive() > 0 ? DATE_FORMAT_M.format(new Date(connectionInfo.getTimeLastStopActive())) : "-");
                    out.print("&nbsp;</td>");

                    // active
                    out.print("<td align=\"right\" class=\"");
                    out.print(getStatusClass(connectionInfo));
                    out.print("\">&nbsp;");
                    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;</td>");

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

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

        } else {
            out.println("No connections yet");
        }
    }
 
    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
        out.print("<div class=\"drill-down\">");
        out.print("url = ");
        out.print(drillDownConnection.getDelegateUrl());
        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;}\n" +
                "div.version {font-weight: bold; font-size: 100%; margin-bottom: 8px;}\n" +
                "h1 {font-weight: bold; font-size: 100%}\n" +
                "option {padding: 2px 24px 2px 4px;}\n" +
                "input {margin: 0px 0px 4px 12px;}\n" +
                "table.data {font-size: 90%; border-collapse: collapse; border: 1px solid black;}\n" +
                "table.data th {background: #bddeff;text-align: left; padding-right: 8px; font-weight: normal; border: 1px solid black;}\n" +
                "table.data td {background: #ffffff; vertical-align: top; padding: 0px 2px 0px 2px; border: 1px solid black;}\n" +
                "td.null {background: yellow;}\n" +
                "td.available {color: black;}\n" +
                "td.active {color: red;}\n" +
                "td.offline {color: blue;}\n" +
                "div.drill-down {}\n" +
                "ul {list-style: none; padding: 0px; margin: 0px; position: relative; font-size: 90%;}\n" +
                "li {padding: 0px; margin: 0px 4px 0px 0px; display: inline; border: 1px solid black; border-width: 1px 1px 0px 1px;}\n" +
                "li.active {background: #bddeff;}\n" +
                "li.inactive {background: #eeeeee;}\n" +
                "li.disabled {background: #dddddd; color: #999999; padding: 0px 4px 0px 4px;}\n" +
                "a.quiet {color: black; text-decoration: none; padding: 0px 4px 0px 4px; }\n" +
                "a.quiet:hover {background: white;}\n");
        out.println("</style>");
        
        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>");
    }

    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(long time) {
        if (time > Integer.MAX_VALUE) {
            return time + "ms";
        } else {
            Calendar c = Calendar.getInstance();
            c.clear();
            c.add(Calendar.MILLISECOND, (int) time);
            return TIME_FORMAT.format(c.getTime());
        }
    }
    
    private void displayLoginForm(PrintWriter out, String link){ 
        out.println("<form action=\"" + link + "\" method=\"POST\" name=\"loginForm\" onsubmit=\"return formSubmit();\">");
        out.println("    <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">");
        out.println("        <tr><td>用户名:</td>");
        out.println("            <td><input id=\""+PARAM_USER_NAME+"\" name=\""+PARAM_USER_NAME+"\" type=\"text\"></td>");
        out.println("        </tr>");
        out.println("        <tr><td>密码:</td>");
        out.println("            <td><input id=\""+PARAM_LOGIN_PASS+"\" name=\""+PARAM_LOGIN_PASS+"\" type=\"password\"></td>");
        out.println("        </tr>");
        out.println("        <tr>");
        out.println("            <td colspan=\"2\"><input id=\"btn\" name=\"btn\" type=\"submit\" value=\"登  录\"></td>");
        out.println("        </tr>");
        out.println("    </table>");
        out.println("    <input name=\""+PARAM_OP_TYPE+"\" value=\""+OP_TYPE_LOGIN+"\" type=\"hidden\">");
        out.println("</form>");

        out.println("<script>");
        out.println("function M(id){return document.getElementById(id);}");
        out.println("function formSubmit(){");
        out.println("    if (M(\""+PARAM_USER_NAME+"\").value==''){");
        out.println("        alert(\"请输入用户名\");return false;");
        out.println("    }");
        out.println("    if (M(\""+PARAM_LOGIN_PASS+"\").value==''){");
        out.println("        alert(\"请输入密码\");return false;");
        out.println("    }");
        out.println("    return true;");
        out.println("}");
        out.println("</script>"); 
    }
}

    启动应用后,访问http://localhost:18081/proxoolPool显示登录页面,输入用户名/密码,就是@WebServlet注解里initParam配置的用户名密码登录即可

猜你喜欢

转载自hzwei206.iteye.com/blog/2366721