首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Spring AOP与log4j做简单的错误日志处理

2012-08-25 
Spring AOP与log4j做简单的异常日志处理1.在网上看了不少例子,下面自己实践了一下。由于系统开发的时候忘记

Spring AOP与log4j做简单的异常日志处理
1.在网上看了不少例子,下面自己实践了一下。由于系统开发的时候忘记了对异常的日志处理,所以现在考虑加上,经过考虑决定使用spring的aop与log4j来做,这样做的好处就是我不用在每个类里面try{}catch或者抛出异常。因为类已经写了好多好多了。要是一个一个弄工作量是很大的
下面说下简单的实现过程,首先啊,在项目工程中的src目录中加入log4j.properties,内容如下:

###设置日志级别###
###这部分是将info信息输出到控制台###
log4j.rootLogger = info,stdout,F
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{ABSOLUTE} %5p %c{1}:%L - %m%n

###错误日志配置###
log4j.appender.F = org.apache.log4j.DailyRollingFileAppender
##输出格式为自定义的HTML##
log4j.appender.F.layout = com.yale.sys.log.FormatHTMLLayout
log4j.appender.F.Threshold = ERROR
log4j.appender.F.Append=true
##错误文件存放位置##
log4j.appender.F.File=error.html
##每天滚动一次文件,即每天产生一个新的文件,文件名字eg:error.html.2012-06-18.html##
log4j.appender.F.DatePattern='.'yyyy-MM-dd'.html'

-------------------------------耐心的看下去 -----------------------------------
其次呢,看上面红色那部分,因为是要将输出日志信息存储到html文件中,所以重写了下log4j中HTMLLayout类,代码片段:

package com.yale.sys.log;import java.text.SimpleDateFormat;import org.apache.log4j.HTMLLayout;import org.apache.log4j.Layout;import org.apache.log4j.Level;import org.apache.log4j.helpers.Transform;import org.apache.log4j.spi.LocationInfo;import org.apache.log4j.spi.LoggingEvent;/** * log4j输出到html格式重写 * @author yale * */public class FormatHTMLLayout extends HTMLLayout {         public FormatHTMLLayout() {       }   [/size]      protected final int BUF_SIZE = 256;         protected final int MAX_CAPACITY = 1024;         static String TRACE_PREFIX = "<br>&nbsp;&nbsp;&nbsp;&nbsp;";         // output buffer appended to when format() is invoked       private StringBuffer sbuf = new StringBuffer(BUF_SIZE);              String title="系统错误日志";         /**       * A string constant used in naming the option for setting the the HTML       * document title. Current value of this string constant is <b>Title</b>.       */      public static final String TITLE_OPTION = "Title";         // Print no location info by default       boolean locationInfo = true;              public String format(LoggingEvent event) {           if (sbuf.capacity() > MAX_CAPACITY) {               sbuf = new StringBuffer(BUF_SIZE);           } else {               sbuf.setLength(0);           }           sbuf.append(Layout.LINE_SEP + "<tr>" + Layout.LINE_SEP);                         sbuf.append("<td>");           sbuf.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));           sbuf.append("</td>" + Layout.LINE_SEP);              sbuf.append("<td title="级别">");           if (event.getLevel().equals(Level.FATAL)) {               sbuf.append("<font color="#339933">");               sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));               sbuf.append("</font>");           } else if (event.getLevel().isGreaterOrEqual(Level.WARN)) {               sbuf.append("<font color="#993300"><strong>");               sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));               sbuf.append("</strong></font>");           } else {               sbuf.append("<font color="green">");               sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));               sbuf.append("</font>");           }           sbuf.append("</td>" + Layout.LINE_SEP);                      if (locationInfo) {               LocationInfo locInfo = event.getLocationInformation();               sbuf.append("<td title="错误">");             sbuf.append("<font color="red">");             sbuf.append(Transform.escapeTags(locInfo.getFileName()));              sbuf.append(':');              sbuf.append(locInfo.getMethodName()).append("()方法中第");            sbuf.append(locInfo.getLineNumber()).append("行出现错误");             sbuf.append("</font>");             sbuf.append("</td>" + Layout.LINE_SEP);          }                                        sbuf.append("<td title="错误信息">");           sbuf.append(Transform.escapeTags(event.getRenderedMessage()));           sbuf.append("</td>" + Layout.LINE_SEP);           sbuf.append("</tr>" + Layout.LINE_SEP);             if (event.getNDC() != null) {               sbuf.append("<tr><td bgcolor="#EEEEEE" style="font-size : xx-small;" colspan="6" title="Nested Diagnostic Context">");               sbuf.append("NDC: " + Transform.escapeTags(event.getNDC()));               sbuf.append("</td></tr>" + Layout.LINE_SEP);           }             String[] s = event.getThrowableStrRep();           if (s != null) {               sbuf.append("<tr><td bgcolor="#993300" style="color:White; font-size : xx-small;" colspan="4">");               appendThrowableAsHTML(s, sbuf);               sbuf.append("</td></tr>" + Layout.LINE_SEP);           }           return sbuf.toString();       }         private void appendThrowableAsHTML(String[] s, StringBuffer sbuf) {           if (s != null) {               int len = s.length;               if (len == 0)                   return;               sbuf.append(Transform.escapeTags(s[0]));               sbuf.append(Layout.LINE_SEP);               for (int i = 1; i < len; i++) {                   sbuf.append(TRACE_PREFIX);                   sbuf.append(Transform.escapeTags(s[i]));                   sbuf.append(Layout.LINE_SEP);               }           }       }         /**       * Returns appropriate HTML headers.       */      public String getHeader() {           sbuf.append("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">" + Layout.LINE_SEP);           sbuf.append("<html>" + Layout.LINE_SEP);           sbuf.append("<head>" + Layout.LINE_SEP);           sbuf.append("<title>" + title + "</title>" + Layout.LINE_SEP);           sbuf.append("<style type="text/css">" + Layout.LINE_SEP);           sbuf.append("<!--" + Layout.LINE_SEP);           sbuf.append("body, table {font-family: '宋体',arial,sans-serif; font-size: 12px;}" + Layout.LINE_SEP);           sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}" + Layout.LINE_SEP);           sbuf.append("-->" + Layout.LINE_SEP);           sbuf.append("</style>" + Layout.LINE_SEP);           sbuf.append("</head>" + Layout.LINE_SEP);           sbuf.append("<body bgcolor="#FFFFFF" topmargin="6" leftmargin="6">" + Layout.LINE_SEP);           sbuf.append("<table cellspacing="0" cellpadding="4" border="1" bordercolor="#224466" width="100%">" + Layout.LINE_SEP);           sbuf.append("<tr>" + Layout.LINE_SEP);           sbuf.append("<th>执行时间</th>" + Layout.LINE_SEP);           sbuf.append("<th>级别</th>" + Layout.LINE_SEP);           if (locationInfo) {               sbuf.append("<th>所在行</th>" + Layout.LINE_SEP);           }           sbuf.append("<th>错误信息</th>" + Layout.LINE_SEP);           sbuf.append("</tr>" + Layout.LINE_SEP);           sbuf.append("<br></br>" + Layout.LINE_SEP);           return sbuf.toString();       }     } 

----------------------------耐心点往下看,就要没了 --------------------------------------------------
再来就是错误文件error.html的存储位置,想要放在项目的WebRoot下,于是就写了个servlet,代码片段:
package com.yale.sys.log;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.util.Properties;import javax.servlet.Servlet;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.apache.log4j.PropertyConfigurator;/** * 初始化日志错误文件存放的路径 */public class LogFileSavePathServlet extends HttpServlet {private static final long serialVersionUID = 1L;           /**     * @see HttpServlet#HttpServlet()     */    public LogFileSavePathServlet() {        super();        // TODO Auto-generated constructor stub    }/** * @see Servlet#init(ServletConfig) */public void init() throws ServletException {//获得系统的路径 /WebRoot String rootPath = this.getServletContext().getRealPath("/"); //获得log4j.properties的输入流 InputStream is =this.getClass().getClassLoader().getResourceAsStream("log4j.properties");        Properties prop = new Properties();             try {prop.load(is);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}  //设置日志文件的输出路径   prop.setProperty("log4j.appender.F.File",rootPath+prop.getProperty("log4j.appender.F.File"));prop.setProperty("log4j.appender.F.DatePattern",rootPath+prop.getProperty("log4j.appender.F.DatePattern"));//加载配置项           PropertyConfigurator.configure(prop);         super.init();}}

注意啦,错误文件存储的路径不允许空格上面乱码七糟的,一定要注意哦。
写完这个servlet,我们不能忘记初始化,您说对不对啊,所以啊,web.xml就像下面这个样子了:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><!-- 日志文件存储路径初始化-->    <servlet>    <servlet-name>LogFileSavePathServlet</servlet-name>    <display-name>LogFileSavePathServlet</display-name>    <description></description>    <servlet-class>com.peoplespot.sys.log.LogFileSavePathServlet</servlet-class>    <load-on-startup>0</load-on-startup>     </servlet>      <servlet-mapping>    <servlet-name>LogFileSavePathServlet</servlet-name>    <url-pattern>/LogFileSavePathServlet</url-pattern>    </servlet-mapping></web-app>

--------------------------------下面就开始和spring aop相关啦,看吧,看吧-----------------------
再一次首先,写一个系统异常日志拦截器类,您看:
package com.yale.sys.log;import org.apache.log4j.Logger;import org.aspectj.lang.ProceedingJoinPoint;/** * 系统异常日志拦截器 * @author yale * */public class LogInterceptor { static Logger logger = Logger.getLogger(LogInterceptor.class); public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {       StringBuffer sb = new StringBuffer();        try{              Object result = joinPoint.proceed();              return result;          }catch(Exception e){          sb.append("开始方法:"+joinPoint.getTarget().getClass() + "." + joinPoint.getSignature().getName()+ "()  ");        sb.append("错误信息如下:["+e.getMessage()+"]");        logger.error(sb.toString());         }        return "error";//因为用到了strut2,所以出现异常会返回到<result name="error">/erreo.jsp</result>这个页面中,当然啦,你也可以配置成全局的异常返回页。    }  }

上面这个类,主要用到了aspectj中的ProceedingJoinPoint,支持的是<aop:around />。
类写完了,但是spring配置文件applicationContext.xml还没有搞啊,所以搞一下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"><!-- 配置日志拦截器 --><bean id="logInterceptor" ref="logInterceptor"><aop:around method="invoke" pointcut="execution(public * com.yale.live.action..*.*(..))" /></aop:aspect><aop:aspect id="logAspectDNA" ref="logInterceptor"><aop:around method="invoke" pointcut="execution(public * com.yale.sys.action..*.*(..))" /></aop:aspect></aop:config></beans>

小插曲:看见<aop:config>节点中proxy-target-/>
启动项目开始运行吧,模拟了下一个异常,输出到html最终这样啦

热点排行