diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatService.java b/src/main/java/com/alibaba/druid/stat/DruidStatService.java index 1b510e0804..4494694218 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidStatService.java +++ b/src/main/java/com/alibaba/druid/stat/DruidStatService.java @@ -299,7 +299,7 @@ public final class DruidStatService implements DruidStatServiceMBean { return returnJSONResult(RESULT_CODE_SUCCESS, result); } - private String returnJSONResult(int resultCode, Object content) { + public static String returnJSONResult(int resultCode, Object content) { Map dataMap = new LinkedHashMap(); dataMap.put("ResultCode", resultCode); dataMap.put("Content", content); diff --git a/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java b/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java index 2342ccb306..2870421b72 100644 --- a/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java +++ b/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java @@ -17,8 +17,15 @@ package com.alibaba.druid.support.http; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -40,31 +47,43 @@ import com.alibaba.druid.util.StringUtils; */ public class StatViewServlet extends HttpServlet { - private final static Log LOG = LogFactory.getLog(StatViewServlet.class); + private final static Log LOG = LogFactory.getLog(StatViewServlet.class); - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final String PARAM_NAME_RESET_ENABLE = "resetEnable"; - public static final String PARAM_NAME_ALLOW = "allow"; - public static final String PARAM_NAME_DENY = "deny"; + public static final String PARAM_NAME_RESET_ENABLE = "resetEnable"; + public static final String PARAM_NAME_ALLOW = "allow"; + public static final String PARAM_NAME_DENY = "deny"; - public static final String PARAM_NAME_USERNAME = "loginUsername"; - public static final String PARAM_NAME_PASSWORD = "loginPassword"; + public static final String PARAM_NAME_USERNAME = "loginUsername"; + public static final String PARAM_NAME_PASSWORD = "loginPassword"; - public static final String SESSION_USER_KEY = "druid-user"; + public static final String PARAM_NAME_JMX_URL = "jmxUrl"; + public static final String PARAM_NAME_JMX_USERNAME = "jmxUsername"; + public static final String PARAM_NAME_JMX_PASSWORD = "jmxPassword"; - private final static String RESOURCE_PATH = "support/http/resources"; - private final static String TEMPLATE_PAGE_RESOURCE_PATH = RESOURCE_PATH + "/template.html"; + public static final String SESSION_USER_KEY = "druid-user"; - private DruidStatService statService = DruidStatService.getInstance(); + private final static String RESOURCE_PATH = "support/http/resources"; + private final static String TEMPLATE_PAGE_RESOURCE_PATH = RESOURCE_PATH + "/template.html"; - public String templatePage; + private DruidStatService statService = DruidStatService.getInstance(); - private List allowList = new ArrayList(); - private List denyList = new ArrayList(); + public String templatePage; - private String username = null; - private String password = null; + private List allowList = new ArrayList(); + private List denyList = new ArrayList(); + + private String username = null; + private String password = null; + + /** web.xml中配置的jmx的连接地址 */ + private String jmxUrl = null; + /** web.xml中配置的jmx的用户名 */ + private String jmxUsername = null; + /** web.xml中配置的jmx的密码 */ + private String jmxPassword = null; + private MBeanServerConnection conn = null; public void init() throws ServletException { initAuthEnv(); @@ -127,6 +146,120 @@ public class StatViewServlet extends HttpServlet { String msg = "initParameter config error, deny : " + getInitParameter(PARAM_NAME_DENY); LOG.error(msg, e); } + + // 获取jmx的连接配置信息 + String param = readInitParam(PARAM_NAME_JMX_URL); + if (param != null) { + jmxUrl = param; + jmxUsername = readInitParam(PARAM_NAME_JMX_USERNAME); + jmxPassword = readInitParam(PARAM_NAME_JMX_PASSWORD); + try { + initJmxConn(); + } catch (IOException e) { + LOG.error("init jmx connection error", e); + } + } + + } + + /** + * 读取servlet中的配置参数. + * + * @param key 配置参数名 + * @return 配置参数值,如果不存在当前配置参数,或者为配置参数长度为0,将返回null + */ + private String readInitParam(String key) { + String value = null; + try { + String param = getInitParameter(key); + if (param != null) { + param = param.trim(); + if (param.length() > 0) { + value = param; + } + } + } catch (Exception e) { + String msg = "initParameter config [" + key + "] error"; + LOG.warn(msg, e); + } + return value; + } + + /** + * 初始化jmx连接 + * + * @throws IOException + */ + private void initJmxConn() throws IOException { + if (jmxUrl != null) { + JMXServiceURL url = new JMXServiceURL(jmxUrl); + Map env = null; + if (jmxUsername != null) { + env = new HashMap(); + String[] credentials = new String[] { jmxUsername, jmxPassword }; + env.put(JMXConnector.CREDENTIALS, credentials); + } + JMXConnector jmxc = JMXConnectorFactory.connect(url, env); + conn = jmxc.getMBeanServerConnection(); + } + } + + /** + * 根据指定的url来获取jmx服务返回的内容. + * + * @param connetion jmx连接 + * @param url url内容 + * @return the jmx返回的内容 + * @throws Exception the exception + */ + private String getJmxResult(MBeanServerConnection connetion, String url) throws Exception { + ObjectName name = new ObjectName(DruidStatService.MBEAN_NAME); + + String result = (String) conn.invoke(name, "service", new String[] { url }, + new String[] { String.class.getName() }); + return result; + } + + /** + * 程序首先判断是否存在jmx连接地址,如果不存在,则直接调用本地的duird服务; 如果存在,则调用远程jmx服务。在进行jmx通信,首先判断一下jmx连接是否已经建立成功,如果已经 + * 建立成功,则直接进行通信,如果之前没有成功建立,则会尝试重新建立一遍。. + * + * @param url 要连接的服务地址 + * @return 调用服务后返回的json字符串 + */ + private String genServiceResponse(String url) { + String resp = null; + if (jmxUrl == null) { + resp = statService.service(url); + } else { + if (conn == null) {// 连接在初始化时创建失败 + try {// 尝试重新连接 + initJmxConn(); + } catch (IOException e) { + LOG.error("init jmx connection error", e); + resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR, + "init jmx connection error" + e.getMessage()); + } + if (conn != null) {// 连接成功 + try { + resp = getJmxResult(conn, url); + } catch (Exception e) { + LOG.error("get jmx data error", e); + resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR, "get data error:" + + e.getMessage()); + } + } + } else {// 连接成功 + try { + resp = getJmxResult(conn, url); + } catch (Exception e) { + LOG.error("get jmx data error", e); + resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR, + "get data error" + e.getMessage()); + } + } + } + return resp; } private void initAuthEnv() { @@ -242,7 +375,7 @@ public class StatViewServlet extends HttpServlet { if (request.getQueryString() != null && request.getQueryString().length() > 0) { fullUrl += "?" + request.getQueryString(); } - response.getWriter().print(statService.service(fullUrl)); + response.getWriter().print(genServiceResponse(fullUrl)); return; } @@ -257,7 +390,7 @@ public class StatViewServlet extends HttpServlet { if (bytes != null) { response.getOutputStream().write(bytes); } - + return; }