使用spring aop结合log4j做日志

整理一下逻辑,一个类中的一个方法被调用时,AOP配置文件会去检查你是否对此方法配置了日志切面,如果配置了,这儿是后向切入,他会在
执行此方法之后执行切入类的一个方法(AOP配置此方法),切入类得到了此方法的完整路径名称,他会到一个配置文件中去读取方法描述,然后用log4j记录此描述信息,后面的工作就交给log4j了,log4j会把信息从屏幕输出,并记录到一个日志文件,位一WEB-INF/log下,还会把数据插入到数据库,但是还需要用户信息,不过Filter已经为我准备好了,系统可以记录一条日志信息类似:


2010-01-01 17:34   用户dreamsover[id号]添加了审核信息


这是log4j的配置文件,定义了3个输出域,此文件位于WEB-INF/conif/log4j(因为我定义了一个输出域为文件,而且要存储到本项目的WEB-INF子目录下,要用到${webapp.root}变量,把log4j配置文件放到WEB-INF下最好,在系统启动时用spring加载,下面贴上web.xml中的配置,包括加载此文件)

[java]  view plain copy
  1. ERROR>INFO>DEBUG  
  2. log4j.properties    
  3. log4j.rootLogger=INFO,stdout,logfile,db  
  4.               
  5. #spring log  
  6. log4j.logger.org.springframework=ERROR  
  7.   
  8.   
  9. #Console  
  10. log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
  11. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
  12. log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}   %X{id},%X{name},%m %C%l%n  
  13.   
  14. #Filelogfile  
  15. log4j.appender.logfile=org.apache.log4j.FileAppender  
  16. log4j.appender.logfile.File=${webapp.root.webtools}/WEB-INF/logs/system.log  
  17. log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
  18. log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}   %X{name},%m %n  
  19.   
  20. #JDBC Appender  
  21. log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender  
  22. log4j.appender.db.BufferSize=2  
  23. log4j.appender.db.driver=sun.jdbc.odbc.JdbcOdbcDriver  
  24. log4j.appender.db.URL=jdbcdbc:report  
  25. log4j.appender.db.user=loveus  
  26. log4j.appender.db.password=123456  
  27. log4j.appender.db.sql=insert into LOG (USERID,NAME,[TIME],INFO) values ('%X{id}','%X{name}','%d{yyyy-MM-dd HH\:mm\:ss}','%m')  

web.xml配置文件,此文件加载了struts,spring,并用spring加载了log4j,注意里面配置了一个Filter : GetUserFilter ,他的作用是从SESSION中获取当前登录用户的信息,在Log4j配置文件中用到了, 比如%X{name}是获取用户姓名,但是要在此Filter中先设置name属性。GetUserFilter是关键所在,因为等一下用AOP切入的方法已经得不到用户信息了,就要靠他了。GetUserFilter我会在最后贴出来。

[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  3.   
  4. <context-param>  
  5. <param-name>webAppRootKey</param-name>  
  6. <param-value>webapp.root.webtools</param-value>  
  7. </context-param>  
  8.   
  9. <!-- Spring ApplicationContext配置文件的路径,可使用通配符。多个路径用逗号分隔。此参数用于后面的Spring-Context loader -->  
  10. <context-param>  
  11.     <param-name>contextConfigLocation</param-name>  
  12.     <param-value>/WEB-INF/conif/spring/applicationContext-*.xml</param-value>  
  13. </context-param>  
  14.   
  15.    <!--由Spring载入的Log4j配置文件位置-->  
  16.    <context-param>  
  17.     <param-name>log4jConfigLocation</param-name>  
  18.     <param-value>/WEB-INF/conif/log4j/log4j.properties</param-value>  
  19. </context-param>  
  20.   
  21.    <!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond-->  
  22. <context-param>  
  23.     <param-name>log4jRefreshInterval</param-name>  
  24.     <param-value>60000</param-value>  
  25. </context-param>  
  26.   
  27. <!-- Log4jConfigListener会去log4j.propeties 读取配置文件;开一条watchdog线程每60秒扫描一下配置文件的变化 -->  
  28. <listener>  
  29.     <listener-class>  
  30.       org.springframework.web.util.Log4jConfigListener  
  31.     </listener-class>  
  32. </listener>  
  33.   
  34. <!-- 根据spring的配置文件加载spring -->  
  35. <listener>  
  36.     <listener-class>  
  37.       org.springframework.web.context.ContextLoaderListener  
  38.     </listener-class>  
  39. </listener>  
  40.   
  41. <!-- Spring 刷新Introspector防止内存泄露 -->  
  42. <listener>  
  43.     <listener-class>  
  44.       org.springframework.web.util.IntrospectorCleanupListener  
  45.     </listener-class>  
  46. </listener>  
  47.   
  48.    <servlet>  
  49. <servlet-name>action</servlet-name>  
  50. <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>  
  51. <init-param>  
  52.    <param-name>config</param-name>  
  53.    <param-value>/WEB-INF/conif/struts/struts-config.xml</param-value>  
  54. </init-param>  
  55. <init-param>  
  56.    <param-name>debug</param-name>  
  57.    <param-value>3</param-value>  
  58. </init-param>  
  59. <init-param>  
  60.    <param-name>detail</param-name>  
  61.    <param-value>3</param-value>  
  62. </init-param>  
  63. <load-on-startup>0</load-on-startup>  
  64.    </servlet>  
  65.   
  66.    <servlet-mapping>  
  67. <servlet-name>action</servlet-name>  
  68. <url-pattern>*.do</url-pattern>  
  69.    </servlet-mapping>  
  70.    <welcome-file-list>  
  71. <welcome-file>index.jsp</welcome-file>  
  72.    </welcome-file-list>  
  73.    <filter>  
  74. <filter-name>Filter</filter-name>  
  75. <filter-class>util.Filter</filter-class>  
  76.    </filter>  
  77.    <filter-mapping>  
  78. <filter-name>Filter</filter-name>  
  79. <url-pattern>/*</url-pattern>  
  80.    </filter-mapping>  
  81.   
  82. <filter>  
  83. <filter-name>GetUserFilter</filter-name>  
  84. <filter-class>util.GetUserFilter</filter-class>  
  85.    </filter>  
  86.    <filter-mapping>  
  87. <filter-name>GetUserFilter</filter-name>  
  88. <url-pattern>/*</url-pattern>  
  89.    </filter-mapping>  
  90.   
  91.     
  92.    <error-page>  
  93. <error-code>404</error-code>  
  94. <location>/jsp/error/404.jsp</location>  
  95.    </error-page>  
  96.   
  97. </web-app>  

AOP的切面类,他是一个普通类,这个类很简单,这么多代码其实就是为了读取一个配置文件WEB-INF/conif/log4j/Log.properties, 这个文件中配置了方法的具体描述信息:
com.dreamsover.report.assessManage.bs.impl.AssessBsImpl.addAssess=\u6DFB\u52A0\u6BCF\u6708\u5BA1\u6838\u4FE1\u606F
com.dreamsover.report.assessManage.bs.impl.AssessBsImpl.getLineAssesssThisMonth=\u67E5\u8BE2\u672C\u6708\u6240\u6709\u5BA1\u6838\u60C5\u51B5
com.dreamsover.report.checkManage.bs.impl.CheckBsImpl.addCheck=\u6DFB\u52A0\u672C\u6708\u68C0\u67E5\u62A5\u8868


系统记录的就是这些描述信息,AOP用到的方法是addLog,这个方法读取相应的方法名(com.dreamsover.report.assessManage.bs.impl.AssessBsImpl.addAssess),从配置文件得到描述信息,然后用log4j记录。稍候贴出AOP的配置。

[java]  view plain copy
  1. /** 
  2. * 文件名: addLog.java 
  3. * 描述: TODO(日志AOP切面类) 
  4. * 修改人: dreamsover 
  5. * 修改时间: 2010-1-19 
  6. * 修改内容:创建类 
  7. * @author: lio 
  8. * @date: 2010-1-19 
  9. * @version V1.0 
  10. */  
  11.   
  12. package util;  
  13.   
  14. import java.io.BufferedInputStream;  
  15. import java.io.File;  
  16. import java.io.FileInputStream;  
  17. import java.io.FileNotFoundException;  
  18. import java.io.IOException;  
  19. import java.io.InputStream;  
  20. import java.util.Properties;  
  21.   
  22. import javax.servlet.http.HttpServletRequest;  
  23.   
  24. import org.apache.log4j.Logger;  
  25. import org.aspectj.lang.JoinPoint;  
  26. import org.springframework.core.io.ClassPathResource;  
  27. import org.springframework.jdbc.core.JdbcTemplate;  
  28.   
  29. import com.dreamsover.report.systemManage.vo.Employee;  
  30.   
  31. /** 
  32. * 类名:addLog 
  33.  
  34. * @author: lio 
  35. * @version 1.0 
  36. */  
  37. public class AddLog {  
  38.   
  39. // 定义LOG4J对象  
  40. static Logger logger = Logger.getLogger(AddLog.class.getName());  
  41.   
  42. // 日志配置文件  
  43. static Properties properties = null;  
  44. // 读取日志配置文件  
  45. static {  
  46. properties = new Properties();  
  47.   
  48. try {  
  49.   
  50. FileInputStream in = new FileInputStream("/" + getWEBINFAddress()  
  51. + File.separator + "conif/log4j/Log.properties");  
  52.   
  53. properties.load(in);  
  54. catch (FileNotFoundException e) {  
  55. logger.error("没有找到日志配置文件,请确认你的路径是否正确。");  
  56. catch (IOException e) {  
  57. logger.error("日志配置文件读写错误");  
  58. }  
  59. }  
  60.   
  61. /** 
  62.     * 描述: 记录系统安全日志的方法 
  63.     *  
  64.     * @author: lio 
  65.     * @param joinPoint 
  66.     * @version: 1.0 
  67.     */  
  68. @SuppressWarnings("unused")  
  69. private void addLog(JoinPoint joinPoint) {  
  70.   
  71. String key = joinPoint.getTarget().getClass().getName() + "."  
  72. + joinPoint.getSignature().getName();  
  73. // 得到方法描述信息  
  74. String info = properties.getProperty(key);  
  75. if (info != null && !info.equals("") && !info.equals(" ")) {  
  76. logger.info(info);  
  77. else {  
  78. /* System.out.println("请检查您的日志配置文件,AOP" + 
  79. "中配置了此方法记录日志,但是没有在配置文件中找到该方法的描述,方法名:" + key); 
  80. */   
  81. }  
  82.   
  83. }  
  84.   
  85.   
  86. /** 
  87.     * 处理路径 
  88.     * @return 
  89.     */  
  90. public static String getWEBINFAddress() {  
  91. Class theClass = AddLog.class;  
  92. java.net.URL u = theClass.getResource("");  
  93. // str会得到这个函数所在类的路径  
  94. String str = u.toString();  
  95. // 截去一些前面6个无用的字符  
  96. str = str.substring(6, str.length());  
  97. // 将%20换成空格(如果文件夹的名称带有空格的话,会在取得的字符串上变成%20)  
  98. str = str.replaceAll("%20"" ");  
  99. // 查找“WEB-INF”在该字符串的位置  
  100. int num = str.indexOf("WEB-INF");  
  101. // 截取即可  
  102. str = str.substring(0, num + "WEB-INF".length());  
  103. return str;  
  104. }  
  105. }  

AOP配置文件,AOP实现全靠他了,我就留了一个模块的配置,需要可以轻松的添加,但是记得在WEB-INF/conif/log4j/Log.properties文件中添加相应的描述信息

[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans  
  3. xmlns="http://www.springframework.org/schema/beans"  
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5. xmlns:p="http://www.springframework.org/schema/p"  
  6. xmlns:tx="http://www.springframework.org/schema/tx"  
  7. xmlns:aop="http://www.springframework.org/schema/aop"  
  8. xsi:schemaLocation="http://www.springframework.org/schema/beans   
  9. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  10. http://www.springframework.org/schema/aop  
  11. http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
  12. http://www.springframework.org/schema/tx  
  13. http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
  14.   
  15.   
  16. <!-- 日志配置 -->  
  17.   
  18.   
  19. <bean id="logClass" class="util.AddLog" />  
  20. <!-- AOP配置 -->  
  21. <aop:aspectj-autoproxy proxy-target-class="true"/>  
  22. <aop:config>  
  23. <aop:aspect id="log" ref="logClass">  
  24.   
  25.                      <!-- 审核模块BS层 -->  
  26. <aop:pointcut expression="execution (* com.dreamsover.report.assessManage.bs..*.*(..))" id="logbsAssessPoint"/>  
  27. <aop:after method="addLog" pointcut-ref="logbsAssessPoint"/>  
  28.   
  29. </aop:aspect>  
  30. </aop:config>  
  31.   
  32. </beans>  

至此,只差一个得到用户的Filter了,其中最重要的是MDC,在log4j中得到用户信息就靠他了
[html]  view plain copy
  1. /**  
  2. * 文件名: GetUserFilter.java  
  3. * 描述: TODO(得到SESSION中的用户)  
  4. * 修改人: lio   
  5. * 修改时间: 2010-1-20  
  6. * 修改内容:创建类  
  7. * @author: lio  
  8. * @date: 2010-1-20  
  9. * @version V1.0  
  10. */  
  11.   
  12. package util;  
  13.   
  14. import java.io.IOException;  
  15. import javax.servlet.Filter;  
  16. import javax.servlet.FilterChain;  
  17. import javax.servlet.FilterConfig;  
  18. import javax.servlet.ServletException;  
  19. import javax.servlet.ServletRequest;  
  20. import javax.servlet.ServletResponse;  
  21. import javax.servlet.http.HttpServletRequest;  
  22. import javax.servlet.http.HttpSession;  
  23. import org.apache.log4j.MDC;  
  24.   
  25. import com.dreamsover.report.systemManage.vo.Employee;  
  26.   
  27. /**  
  28. * 类名:GetUserFilter  
  29. *   
  30. * @author: dreamsover  
  31. * @version 1.0  
  32. */  
  33.   
  34. public class GetUserFilter implements Filter {  
  35.   
  36. //定义默认用户姓名  
  37. private final static String DEFAULT_USER = "guest";  
  38.   
  39. public void destroy() {  
  40. }  
  41.   
  42. public void doFilter(ServletRequest request, ServletResponse response,  
  43. FilterChain chain) throws IOException, ServletException {  
  44. HttpServletRequest req = (HttpServletRequest) request;  
  45. HttpSession session = req.getSession();  
  46. if (session == null) {  
  47. MDC.put("id", (int) (Math.random() * 1000));  
  48. MDC.put("name", DEFAULT_USER);  
  49. MDC.put("username", DEFAULT_USER);  
  50. } else {  
  51. Employee user = (Employee) session.getAttribute("user");  
  52. if (user == null) {  
  53. MDC.put("id", (int) (Math.random() * 1000));  
  54. MDC.put("name", DEFAULT_USER);  
  55. MDC.put("username", DEFAULT_USER);  
  56. } else {  
  57. MDC.put("id", user.getId());  
  58. MDC.put("name", user.getName());  
  59. MDC.put("username", user.getUsername());  
  60. }  
  61. }  
  62.   
  63. chain.doFilter(request, response);  
  64. }  
  65.   
  66. public void init(FilterConfig Config) throws ServletException {  
  67.   
  68. }  
  69. }  

[java]  view plain copy
  1. /** 
  2. * 文件名: GetUserFilter.java 
  3. * 描述: TODO(得到SESSION中的用户) 
  4. * 修改人: lio  
  5. * 修改时间: 2010-1-20 
  6. * 修改内容:创建类 
  7. * @author: lio 
  8. * @date: 2010-1-20 
  9. * @version V1.0 
  10. */  
  11.   
  12. package util;  
  13.   
  14. import java.io.IOException;  
  15. import javax.servlet.Filter;  
  16. import javax.servlet.FilterChain;  
  17. import javax.servlet.FilterConfig;  
  18. import javax.servlet.ServletException;  
  19. import javax.servlet.ServletRequest;  
  20. import javax.servlet.ServletResponse;  
  21. import javax.servlet.http.HttpServletRequest;  
  22. import javax.servlet.http.HttpSession;  
  23. import org.apache.log4j.MDC;  
  24.   
  25. import com.dreamsover.report.systemManage.vo.Employee;  
  26.   
  27. /** 
  28. * 类名:GetUserFilter 
  29.  
  30. * @author: dreamsover 
  31. * @version 1.0 
  32. */  
  33.   
  34. public class GetUserFilter implements Filter {  
  35.   
  36. //定义默认用户姓名  
  37. private final static String DEFAULT_USER = "guest";  
  38.   
  39. public void destroy() {  
  40. }  
  41.   
  42. public void doFilter(ServletRequest request, ServletResponse response,  
  43. FilterChain chain) throws IOException, ServletException {  
  44. HttpServletRequest req = (HttpServletRequest) request;  
  45. HttpSession session = req.getSession();  
  46. if (session == null) {  
  47. MDC.put("id", (int) (Math.random() * 1000));  
  48. MDC.put("name", DEFAULT_USER);  
  49. MDC.put("username", DEFAULT_USER);  
  50. else {  
  51. Employee user = (Employee) session.getAttribute("user");  
  52. if (user == null) {  
  53. MDC.put("id", (int) (Math.random() * 1000));  
  54. MDC.put("name", DEFAULT_USER);  
  55. MDC.put("username", DEFAULT_USER);  
  56. else {  
  57. MDC.put("id", user.getId());  
  58. MDC.put("name", user.getName());  
  59. MDC.put("username", user.getUsername());  
  60. }  
  61. }  
  62.   
  63. chain.doFilter(request, response);  
  64. }  
  65.   
  66. public void init(FilterConfig Config) throws ServletException {  
  67.   
  68. }  
  69. }  


好了,所有代码已经完成了,再整理一下逻辑,一个类中的一个方法被调用时,AOP配置文件会去检查你是否对此方法配置了日志切面,如果配置了,这儿是后向切入,他会在执行此方法之后执行切入类的一个方法(AOP配置此方法),切入类得到了此方法的完整路径名称,他会到一个配置文件中去读取方法描述,然后用log4j记录此描述信息,后面的工作就交给log4j了,log4j会把信息从屏幕输出,并记录到一个日志文件,位一WEB-INF/log下,还会把数据插入到数据库,但是还需要用户信息,不过Filter已经为我准备好了,系统可以记录一条日志信息类似:


2010-01-01 17:34   用户dreamsover[id号]添加了审核信息

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值