package com.alibaba.druid.support; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.DruidStatManagerFacade; import com.alibaba.druid.support.http.stat.WebAppStatManager; import com.alibaba.druid.support.spring.stat.SpringStatManager; import com.alibaba.druid.util.MapComparator; import com.alibaba.druid.util.StringUtils; import com.alibaba.fastjson.JSON; /** * 注意:避免直接调用Druid相关对象例如DruidDataSource等,相关调用要到DruidStatManagerFacade里用反射实现 * * @author sandzhang */ public class JSONDruidStatService { private final static JSONDruidStatService instance = new JSONDruidStatService(); private static DruidStatManagerFacade druidStatManager = DruidStatManagerFacade.getInstance(); public final static int RESULT_CODE_SUCCESS = 1; public final static int RESULT_CODE_ERROR = -1; private final static int DEFAULT_PAGE = 1; private final static int DEFAULT_PER_PAGE_COUNT = Integer.MAX_VALUE; private static final String DEFAULT_ORDER_TYPE = "asc"; private static final String DEFAULT_ORDERBY = "SQL"; private JSONDruidStatService(){ } public static JSONDruidStatService getInstance() { return instance; } public String service(String url) { Map parameters = StringUtils.getParameters(url); if (url.equals("/basic.json")) { return returnJSONResult(RESULT_CODE_SUCCESS, druidStatManager.returnJSONBasicStat()); } if (url.equals("/reset-all.json")) { druidStatManager.resetAll(); SpringStatManager.getInstance().resetStat(); WebAppStatManager.getInstance().resetStat(); return returnJSONResult(RESULT_CODE_SUCCESS, null); } if (url.equals("/datasource.json")) { return returnJSONResult(RESULT_CODE_SUCCESS, druidStatManager.getDataSourceStatList()); } if (url.startsWith("/datasource-")) { Integer id = StringUtils.subStringToInteger(url, "datasource-", "."); Object result = druidStatManager.getDataSourceStatData(id); return returnJSONResult(result == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS, result); } if (url.startsWith("/connectionInfo-") && url.endsWith(".json")) { Integer id = StringUtils.subStringToInteger(url, "connectionInfo-", "."); List connectionInfoList = druidStatManager.getPoolingConnectionInfoByDataSourceId(id); return returnJSONResult(connectionInfoList == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS, connectionInfoList); } if (url.startsWith("/activeConnectionStackTrace-") && url.endsWith(".json")) { Integer id = StringUtils.subStringToInteger(url, "activeConnectionStackTrace-", "."); return returnJSONActiveConnectionStackTrace(id); } if (url.startsWith("/sql.json")) { return returnJSONResult(RESULT_CODE_SUCCESS, getSqlStatDataList(parameters)); } if (url.startsWith("/sql-") && url.indexOf(".json") > 0) { Integer id = StringUtils.subStringToInteger(url, "sql-", ".json"); return returnJSONSqlInfo(id); } if (url.startsWith("/weburi.json")) { return returnJSONResult(RESULT_CODE_SUCCESS, getWebURIStatDataList(parameters)); } if (url.startsWith("/websession.json")) { return returnJSONResult(RESULT_CODE_SUCCESS, getWebSessionStatDataList(parameters)); } if (url.startsWith("/spring.json")) { return returnJSONResult(RESULT_CODE_SUCCESS, getSpringStatDataList(parameters)); } return returnJSONResult(RESULT_CODE_ERROR, "Do not support this request, please contact with administrator."); } private List> getSpringStatDataList(Map parameters) { List> array = SpringStatManager.getInstance().getMethodStatData(); return comparatorOrderBy(array, parameters); } private List> getWebURIStatDataList(Map parameters) { List> array = WebAppStatManager.getInstance().getURIStatData(); return comparatorOrderBy(array, parameters); } private List> getWebSessionStatDataList(Map parameters) { List> array = WebAppStatManager.getInstance().getSessionStatData(); return array; } private List> comparatorOrderBy(List> array,Map parameters){ // when open the stat page before executing some sql if (array == null || array.isEmpty()) return null; // when parameters is null String orderBy, orderType = null; Integer page, perPageCount = null; if (parameters == null) { orderBy = DEFAULT_ORDER_TYPE; orderType = DEFAULT_ORDER_TYPE; page = DEFAULT_PAGE; perPageCount = DEFAULT_PER_PAGE_COUNT; } else { orderBy = parameters.get("orderBy"); orderType = parameters.get("orderType"); page = Integer.parseInt(parameters.get("page")); perPageCount = Integer.parseInt(parameters.get("perPageCount")); } // others,such as order orderBy = orderBy == null ? DEFAULT_ORDERBY : orderBy; orderType = orderType == null ? DEFAULT_ORDER_TYPE : orderType; page = page == null ? DEFAULT_PAGE : page; perPageCount = perPageCount == null ? DEFAULT_PER_PAGE_COUNT : perPageCount; if (!"desc".equals(orderType)) orderType = DEFAULT_ORDER_TYPE; // orderby the statData array if (orderBy != null && orderBy.trim().length() != 0) { Collections.sort(array, new MapComparator(orderBy, DEFAULT_ORDER_TYPE.equals(orderType))); } // page int fromIndex = (page - 1) * perPageCount; int toIndex = page * perPageCount; if (toIndex > array.size()) toIndex = array.size(); return array.subList(fromIndex, toIndex); } private List> getSqlStatDataList(Map parameters) { List> array = druidStatManager.getSqlStatDataList(); return comparatorOrderBy(array, parameters); } private String returnJSONSqlInfo(Integer id) { Map map = druidStatManager.getSqlStatData(id); if (map == null) { return returnJSONResult(RESULT_CODE_ERROR , null); } map.put("formattedSql",SQLUtils.format((String) map.get("SQL"),(String) map.get("DbType"))); List statementList = SQLUtils.parseStatements((String) map.get("SQL"), (String) map.get("DbType")); if (!statementList.isEmpty()) { SQLStatement statemen = statementList.get(0); SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(statementList, (String) map.get("DbType")); statemen.accept(visitor); map.put("parsedTable", visitor.getTables().toString()); map.put("parsedFields", visitor.getColumns().toString()); map.put("parsedConditions", visitor.getConditions().toString()); map.put("parsedRelationships", visitor.getRelationships().toString()); map.put("parsedOrderbycolumns", visitor.getOrderByColumns().toString()); } DateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS"); Date maxTimespanOccurTime = (Date)map.get("MaxTimespanOccurTime"); if (maxTimespanOccurTime != null) { map.put("MaxTimespanOccurTime", format.format(maxTimespanOccurTime)); } return returnJSONResult(map == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS, map); } private String returnJSONActiveConnectionStackTrace(Integer id) { List result = druidStatManager.getActiveConnectionStackTraceByDataSourceId(id); if (result == null) { return returnJSONResult(RESULT_CODE_ERROR, "require set removeAbandoned=true"); } return returnJSONResult(RESULT_CODE_SUCCESS, result); } private String returnJSONResult(int resultCode, Object content) { Map dataMap = new LinkedHashMap(); dataMap.put("ResultCode", resultCode); dataMap.put("Content", content); return JSON.toJSONStringWithDateFormat(dataMap, "yyyy-MM-dd hh:mm:ss"); } }