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