您的位置:首页 > 编程语言 > Java开发

使用spring aop结合log4j做日志

2015-12-06 00:20 609 查看
整理一下逻辑,一个类中的一个方法被调用时,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
plaincopy

ERROR>INFO>DEBUG

log4j.properties

log4j.rootLogger=INFO,stdout,logfile,db

#spring log

log4j.logger.org.springframework=ERROR

#Console

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %X{id},%X{name},%m %C%l%n

#Filelogfile

log4j.appender.logfile=org.apache.log4j.FileAppender

log4j.appender.logfile.File=${webapp.root.webtools}/WEB-INF/logs/system.log

log4j.appender.logfile.layout=org.apache.log4j.PatternLayout

log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %X{name},%m %n

#JDBC Appender

log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender

log4j.appender.db.BufferSize=2

log4j.appender.db.driver=sun.jdbc.odbc.JdbcOdbcDriver

log4j.appender.db.URL=jdbcdbc:report

log4j.appender.db.user=loveus

log4j.appender.db.password=123456

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
plaincopy

<?xml version="1.0" encoding="UTF-8"?>

<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">
<context-param>

<param-name>webAppRootKey</param-name>

<param-value>webapp.root.webtools</param-value>

</context-param>

<!-- Spring ApplicationContext配置文件的路径,可使用通配符。多个路径用逗号分隔。此参数用于后面的Spring-Context loader -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/conif/spring/applicationContext-*.xml</param-value>

</context-param>

<!--由Spring载入的Log4j配置文件位置-->

<context-param>

<param-name>log4jConfigLocation</param-name>

<param-value>/WEB-INF/conif/log4j/log4j.properties</param-value>

</context-param>

<!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond-->

<context-param>

<param-name>log4jRefreshInterval</param-name>

<param-value>60000</param-value>

</context-param>

<!-- Log4jConfigListener会去log4j.propeties 读取配置文件;开一条watchdog线程每60秒扫描一下配置文件的变化 -->

<listener>

<listener-class>

org.springframework.web.util.Log4jConfigListener

</listener-class>

</listener>

<!-- 根据spring的配置文件加载spring -->

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<!-- Spring 刷新Introspector防止内存泄露 -->

<listener>

<listener-class>

org.springframework.web.util.IntrospectorCleanupListener

</listener-class>

</listener>

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/conif/struts/struts-config.xml</param-value>

</init-param>

<init-param>

<param-name>debug</param-name>

<param-value>3</param-value>

</init-param>

<init-param>

<param-name>detail</param-name>

<param-value>3</param-value>

</init-param>

<load-on-startup>0</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<filter>

<filter-name>Filter</filter-name>

<filter-class>util.Filter</filter-class>

</filter>

<filter-mapping>

<filter-name>Filter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter>

<filter-name>GetUserFilter</filter-name>

<filter-class>util.GetUserFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>GetUserFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<error-page>

<error-code>404</error-code>

<location>/jsp/error/404.jsp</location>

</error-page>

</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
plaincopy

/**

* 文件名: addLog.java

* 描述: TODO(日志AOP切面类)

* 修改人: dreamsover

* 修改时间: 2010-1-19

* 修改内容:创建类

* @author: lio

* @date: 2010-1-19

* @version V1.0

*/

package util;

import java.io.BufferedInputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import org.aspectj.lang.JoinPoint;

import org.springframework.core.io.ClassPathResource;

import org.springframework.jdbc.core.JdbcTemplate;

import com.dreamsover.report.systemManage.vo.Employee;

/**

* 类名:addLog

*

* @author: lio

* @version 1.0

*/

public class AddLog {

// 定义LOG4J对象

static Logger logger = Logger.getLogger(AddLog.class.getName());

// 日志配置文件

static Properties properties = null;

// 读取日志配置文件

static {

properties = new Properties();

try {

FileInputStream in = new FileInputStream("/" + getWEBINFAddress()

+ File.separator + "conif/log4j/Log.properties");

properties.load(in);

} catch (FileNotFoundException e) {

logger.error("没有找到日志配置文件,请确认你的路径是否正确。");

} catch (IOException e) {

logger.error("日志配置文件读写错误");

}

}

/**

* 描述: 记录系统安全日志的方法

*

* @author: lio

* @param joinPoint

* @version: 1.0

*/

@SuppressWarnings("unused")

private void addLog(JoinPoint joinPoint) {

String key = joinPoint.getTarget().getClass().getName() + "."

+ joinPoint.getSignature().getName();

// 得到方法描述信息

String info = properties.getProperty(key);

if (info != null && !info.equals("") && !info.equals(" ")) {

logger.info(info);

} else {

/* System.out.println("请检查您的日志配置文件,AOP" +

"中配置了此方法记录日志,但是没有在配置文件中找到该方法的描述,方法名:" + key);

*/

}

}

/**

* 处理路径

* @return

*/

public static String getWEBINFAddress() {

Class theClass = AddLog.class;

java.net.URL u = theClass.getResource("");

// str会得到这个函数所在类的路径

String str = u.toString();

// 截去一些前面6个无用的字符

str = str.substring(6, str.length());

// 将%20换成空格(如果文件夹的名称带有空格的话,会在取得的字符串上变成%20)

str = str.replaceAll("%20", " ");

// 查找“WEB-INF”在该字符串的位置

int num = str.indexOf("WEB-INF");

// 截取即可

str = str.substring(0, num + "WEB-INF".length());

return str;

}

}

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

[html] view
plaincopy

<?xml version="1.0" encoding="UTF-8"?>

<beans

xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 日志配置 -->

<bean id="logClass" class="util.AddLog" />

<!-- AOP配置 -->

<aop:aspectj-autoproxy proxy-target-class="true"/>

<aop:config>

<aop:aspect id="log" ref="logClass">

<!-- 审核模块BS层 -->

<aop:pointcut expression="execution (* com.dreamsover.report.assessManage.bs..*.*(..))" id="logbsAssessPoint"/>

<aop:after method="addLog" pointcut-ref="logbsAssessPoint"/>

</aop:aspect>

</aop:config>

</beans>

至此,只差一个得到用户的Filter了,其中最重要的是MDC,在log4j中得到用户信息就靠他了

[html] view
plaincopy

/**

* 文件名: GetUserFilter.java

* 描述: TODO(得到SESSION中的用户)

* 修改人: lio

* 修改时间: 2010-1-20

* 修改内容:创建类

* @author: lio

* @date: 2010-1-20

* @version V1.0

*/

package util;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.log4j.MDC;

import com.dreamsover.report.systemManage.vo.Employee;

/**

* 类名:GetUserFilter

*

* @author: dreamsover

* @version 1.0

*/

public class GetUserFilter implements Filter {

//定义默认用户姓名

private final static String DEFAULT_USER = "guest";

public void destroy() {

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;

HttpSession session = req.getSession();

if (session == null) {

MDC.put("id", (int) (Math.random() * 1000));

MDC.put("name", DEFAULT_USER);

MDC.put("username", DEFAULT_USER);

} else {

Employee user = (Employee) session.getAttribute("user");

if (user == null) {

MDC.put("id", (int) (Math.random() * 1000));

MDC.put("name", DEFAULT_USER);

MDC.put("username", DEFAULT_USER);

} else {

MDC.put("id", user.getId());

MDC.put("name", user.getName());

MDC.put("username", user.getUsername());

}

}

chain.doFilter(request, response);

}

public void init(FilterConfig Config) throws ServletException {

}

}

[java] view
plaincopy

/**

* 文件名: GetUserFilter.java

* 描述: TODO(得到SESSION中的用户)

* 修改人: lio

* 修改时间: 2010-1-20

* 修改内容:创建类

* @author: lio

* @date: 2010-1-20

* @version V1.0

*/

package util;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.log4j.MDC;

import com.dreamsover.report.systemManage.vo.Employee;

/**

* 类名:GetUserFilter

*

* @author: dreamsover

* @version 1.0

*/

public class GetUserFilter implements Filter {

//定义默认用户姓名

private final static String DEFAULT_USER = "guest";

public void destroy() {

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;

HttpSession session = req.getSession();

if (session == null) {

MDC.put("id", (int) (Math.random() * 1000));

MDC.put("name", DEFAULT_USER);

MDC.put("username", DEFAULT_USER);

} else {

Employee user = (Employee) session.getAttribute("user");

if (user == null) {

MDC.put("id", (int) (Math.random() * 1000));

MDC.put("name", DEFAULT_USER);

MDC.put("username", DEFAULT_USER);

} else {

MDC.put("id", user.getId());

MDC.put("name", user.getName());

MDC.put("username", user.getUsername());

}

}

chain.doFilter(request, response);

}

public void init(FilterConfig Config) throws ServletException {

}

}

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

2010-01-01 17:34 用户dreamsover[id号]添加了审核信息
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: