springboot 增加接口访问日志打印
import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Arrays; import java.util.Map; @Component @Log4j2 public class TimeCostInterceptor implements HandlerInterceptor { // before the actual handler will be executed public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long startTime = System.currentTimeMillis(); request.setAttribute("startTime", startTime); if (handler instanceof HandlerMethod) { StringBuilder sb = new StringBuilder(1000); sb.append("--start-----------------------------------\n"); HandlerMethod h = (HandlerMethod) handler; sb.append("URI : ").append(request.getRequestURI()).append("\n"); sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n"); sb.append("Method : ").append(h.getMethod().getName()).append("\n"); sb.append("Params : ").append(getParamString(request.getParameterMap())).append("\n"); log.info(sb.toString()); } return true; } // after the handler is executed public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { long startTime = (Long) request.getAttribute("startTime"); long endTime = System.currentTimeMillis(); long executeTime = endTime - startTime; if(handler instanceof HandlerMethod){ StringBuilder sb = new StringBuilder(1000); HandlerMethod h = (HandlerMethod) handler; sb.append("URI : ").append(request.getRequestURI()).append("\n"); sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n"); sb.append("Method : ").append(h.getMethod().getName()).append("\n"); sb.append("Params : ").append(getParamString(request.getParameterMap())).append("\n"); sb.append("cost time : ").append(executeTime).append("ms").append("\n"); sb.append("--end------------------------------------\n"); log.info(sb.toString()); } } private String getParamString(Map<String, String[]> map) { StringBuilder sb = new StringBuilder(); for(Map.Entry<String,String[]> e:map.entrySet()){ sb.append(e.getKey()).append("="); String[] value = e.getValue(); if(value != null && value.length == 1){ sb.append(value[0]).append("\t"); }else{ sb.append(Arrays.toString(value)).append("\t"); } } return sb.toString(); } public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { }
import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @Configuration public class CustomWebMvcConfigurer implements WebMvcConfigurer { @Resource private TimeCostInterceptor timeCostInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeCostInterceptor); } @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.defaultContentType(MediaType.APPLICATION_JSON); }
打印sql执行时间:
import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.plugin.*; import org.apache.ibatis.session.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.sql.Statement; import java.util.List; import java.util.Properties; /** * Sql执行时间记录拦截器 * * @author zero * 2019年12月13日17:05:28 */ @Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}), @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}), @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})}) @Component public class SqlExecuteTimeCountInterceptor implements Interceptor { private static Logger logger = LoggerFactory.getLogger(SqlExecuteTimeCountInterceptor.class); /** * 打印的参数字符串的最大长度 */ private final static int MAX_PARAM_LENGTH = 50; /** * 记录的最大SQL长度 */ private final static int MAX_SQL_LENGTH = 20000; @Override public Object intercept(Invocation invocation) throws Throwable { Object target = invocation.getTarget(); long startTime = System.currentTimeMillis(); StatementHandler statementHandler = (StatementHandler) target; try { return invocation.proceed(); } finally { long endTime = System.currentTimeMillis(); long timeCount = endTime - startTime; BoundSql boundSql = statementHandler.getBoundSql(); String sql = boundSql.getSql(); Object parameterObject = boundSql.getParameterObject(); List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings(); // 格式化Sql语句,去除换行符,替换参数 sql = formatSQL(sql, parameterObject, parameterMappingList); if(timeCount < 50) { logger.info("SQL执行耗时[{}ms], SQL语句:[ {} ]", timeCount, sql); }else if(timeCount < 100){ logger.info("SQL执行耗时[{}ms,level=1], SQL语句:[ {} ]", timeCount, sql); }else if(timeCount < 200){ logger.info("SQL执行耗时[{}ms,level=2], SQL语句:[ {} ]", timeCount, sql); }else if(timeCount < 300){ logger.info("SQL执行耗时[{}ms,level=3], SQL语句:[ {} ]", timeCount, sql); }else if(timeCount < 500){ logger.info("SQL执行耗时[{}ms,level=4], SQL语句:[ {} ]", timeCount, sql); }else if(timeCount < 1000){ logger.info("SQL执行耗时[{}ms,level=5], SQL语句:[ {} ]", timeCount, sql); }else { logger.info("SQL执行耗时[{}ms,level=6], SQL语句:[ {} ]", timeCount, sql); } } } /** * 格式化/美化 SQL语句 * * @param sql sql 语句 * @param parameterObject 参数的Map * @param parameterMappingList 参数的List * @return 格式化之后的SQL */ private String formatSQL(String sql, Object parameterObject, List<ParameterMapping> parameterMappingList) { // 输入sql字符串空判断 if (sql == null || sql.length() == 0) { return ""; } // 美化sql sql = beautifySql(sql); // 不传参数的场景,直接把sql美化一下返回出去 if (parameterObject == null || parameterMappingList == null || parameterMappingList.size() == 0) { return sql; } return LimitSQLLength(sql); } /** * 返回限制长度之后的SQL语句 * * * @param sql 原始SQL语句 */ private String LimitSQLLength(String sql) { if (sql == null || sql.length() == 0) { return ""; } if (sql.length() > MAX_SQL_LENGTH) { return sql.substring(0, MAX_SQL_LENGTH); } else { return sql; } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } /** * 替换SQL 中? 所对应的值, 只保留前50个字符 * * @param sql sql语句 * @param valueOf ?对应的值 */ private String replaceValue(String sql, String valueOf) { //超过50个字符只取前50个 if (valueOf != null && valueOf.length() > MAX_PARAM_LENGTH) { valueOf = valueOf.substring(0, MAX_PARAM_LENGTH); } sql = sql.replaceFirst("\\?", valueOf); return sql; } /** * 美化sql * * @param sql sql语句 */ private String beautifySql(String sql) { sql = sql.replaceAll("[\\s\n ]+", " "); return sql; }