log4j.properties文件java
#根設置,輸出級別爲DEBUG級別, 輸出文件爲 ERRORA,stdout,DEBUGA log4j.rootLogger=DEBUG,ERRORA,stdout,DEBUGA #過濾掉spring框架下的額外日誌 #log4j.category.org.springframework = WARN #輸出到控制檯 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c{1}:%L - %m%n #輸出DEBUG信息到指定文件 log4j.appender.DEBUGA=org.apache.log4j.DailyRollingFileAppender log4j.appender.DEBUGA.layout=org.apache.log4j.PatternLayout log4j.appender.DEBUGA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.DEBUGA.datePattern=yyyy-MM-dd'.log' log4j.appender.DEBUGA.Threshold = DEBUG log4j.appender.DEBUGA.append=true log4j.appender.DEBUGA.File=d:/log/debug_log.log log4j.appender.DEBUGA.filter.F1=org.apache.log4j.varia.LevelRangeFilter log4j.appender.DEBUGA.filter.F1.LevelMin=DEBUG log4j.appender.DEBUGA.filter.F1.LevelMax=INFO #輸出error到指定文件 log4j.appender.ERRORA=org.apache.log4j.DailyRollingFileAppender log4j.appender.ERRORA.layout=org.apache.log4j.PatternLayout log4j.appender.ERRORA.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.ERRORA.datePattern=yyyy-MM-dd'.log' log4j.appender.ERRORA.Threshold = ERROR log4j.appender.ERRORA.append=true log4j.appender.ERRORA.File=d:/errorlog/error_log.log #打印sql語句 log4j.logger.com.ibatis=DEBUG log4j.logger.java.sql.ResultSet=INFO log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
爲了對每一個請求的進行日誌輸出,咱們須要配置攔截器spring
<!-- 攔截器配置,攔截順序:先執行後定義的,排在第一位的最後執行。--> <mvc:interceptors> <!-- API訪問日誌記錄攔截器 --> <mvc:interceptor> <mvc:mapping path="/user/**" /> <bean class="com.utils.ApiLogInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/childs/**" /> <bean class="com.utils.ApiLogInterceptor" /> </mvc:interceptor> </mvc:interceptors>
開發自定義的攔截器,實現 HandlerInterceptor 接口sql
public class ApiLogInterceptor implements HandlerInterceptor { private static final Logger logger = org.apache.log4j.Logger.getLogger(ApiLogInterceptor.class); private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (logger.isDebugEnabled()){ long beginTime = System.currentTimeMillis();//一、開始時間 startTimeThreadLocal.set(beginTime); //線程綁定變量(該數據只有當前請求的線程可見) logger.debug("開始計時: {"+new SimpleDateFormat("HH:mm:ss.SSS").format(beginTime)+"} URI: {"+request.getRequestURI()+"}"); } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (modelAndView != null){ logger.info("ViewName: " + modelAndView.getViewName()); } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { logger.debug("Header: " + request.getHeader("user-agent")); logger.debug("RequestURI: " + request.getRequestURI()); logger.debug("Method: " + request.getMethod()); logger.debug("ParameterMap: " + request.getParameterMap().toString()); // 打印JVM信息 if (logger.isDebugEnabled()){ long beginTime = startTimeThreadLocal.get();//獲得線程綁定的局部變量(開始時間) long endTime = System.currentTimeMillis(); //二、結束時間 logger.debug("計時結束:{"+new SimpleDateFormat("HH:mm:ss.SSS").format(endTime)+"} 耗時:{"+DateUtils.formatDateTime(endTime - beginTime)+"} URI: {"+request.getRequestURI()+"} 最大內存: {"+(Runtime.getRuntime().maxMemory()/1024/1024)+"}m 已分配內存: {"+(Runtime.getRuntime().totalMemory()/1024/1024)+"}m 已分配內存中的剩餘空間: {"+(Runtime.getRuntime().freeMemory()/1024/1024+"}m 最大可用內存: {"+(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024)+"}m") ; } } }
自定義攔截器會針對 /user/** 和 /childs/** 的請求進行攔截,輸出日誌。apache
測試後發現,錯誤日誌既沒有在控制檯打印出來也沒有輸出到文件,由於咱們須要配置spring-mvc的全局異常處理器,實現 HandlerExceptionResolver 接口api
public class DefaultExceptionHandler implements HandlerExceptionResolver { private static final Logger logger = org.apache.log4j.Logger.getLogger(DefaultExceptionHandler.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { logger.error("異常信息", ex); String url = request.getRequestURL().toString(); if (url.contains("api")) { try { /** * 來自app的請求異常處理 */ response.setStatus(HttpStatus.OK.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.getWriter().write(new Gson().toJson("系統錯誤")); } catch (IOException e) { logger.error("", e); } } else { ModelAndView mv = new ModelAndView(); mv.setViewName("error"); return mv; } return null; } }
還須要在spring-mvc.xml中配置這個beanspring-mvc
<bean id="exceptionHandler" class="com.utils.DefaultExceptionHandler" />
再次運行項目,系統出現錯誤的時候,會跳轉到 error.jsp,錯誤信息會被輸出到 error_log 文件。mvc