利用AOP实现在controller层实现日志记录,往日志文件里写相应日志信息。
先在log4j进行log功能的一些配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
threshold="all" debug="false">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %c %x - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="DEBUG" />
<param name="levelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<appender name="file" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="${webapp.root}logs/api/api-log-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] %m%n" />
</layout>
</appender>
<appender name="exceptionAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="${webapp.root}logs/api/api-error-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] %m%n" />
</layout>
</appender>
<appender name="chargeAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="${webapp.root}logs/api/api-charge-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %m%n" />
</layout>
</appender>
<appender name="userBehaviorAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern"
value="${webapp.root}logs/api/api-user-behavior-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<appender name="inOutPutAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern"
value="${webapp.root}logs/api/api-inOutPut-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<appender name="httpAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="${webapp.root}logs/api/api-http-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] %m%n" />
</layout>
</appender>
<appender name="accessAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern"
value="${webapp.root}logs/api/api-access-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<appender name="serviceAppender" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern"
value="${webapp.root}logs/api/api-servitization-%d{yyyyMMdd}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] %m%n" />
</layout>
</appender>
<logger name="exceptionLog" additivity="false">
<level value="INFO" />
<appender-ref ref="exceptionAppender" />
</logger>
<logger name="chargeLog" additivity="false">
<level value="INFO" />
<appender-ref ref="chargeAppender" />
</logger>
<logger name="userBehaviorLog" additivity="false">
<level value="INFO" />
<appender-ref ref="userBehaviorAppender" />
</logger>
<logger name="inOutPutLog" additivity="false">
<level value="INFO" />
<appender-ref ref="inOutPutAppender" />
</logger>
<logger name="httpLog" additivity="false">
<level value="INFO" />
<appender-ref ref="httpAppender" />
</logger>
<logger name="accessLog" additivity="false">
<level value="INFO" />
<appender-ref ref="accessAppender" />
<!-- <appender-ref ref="accessAppenderScribe" /> -->
</logger>
<logger name="serviceLog" additivity="false">
<level value="INFO" />
<appender-ref ref="serviceAppender" />
</logger>
<root>
<priority value="error" />
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
</log4j:configuration>
再创建一个Java文件(LogHelper),作为工具类,往日志表里写入日志或输出到控制台等等。
package com.warehouse.controller.api.log;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import com.alibaba.fastjson.JSON;
import com.warehouse.controller.util.RegexUtil;
/**
* @author Meng
*/
public class LogHelper {
protected static final Log log = LogFactory.getLog(LogHelper.class);
private static boolean isInit = false;
private final Object lock = new Object();
protected static Class LogHelper; /* synthetic field */
private static String logXml = "/log4j.xml";
private Logger logger;
private static HashMap<String, LogHelper> logHelperMap = new HashMap<String, LogHelper>();
/**
* 初始化log4j配置文件
*
* @param logXmlConfigFile
*/
public static void init(String logXmlConfigFile) {
log.debug("init log");
if ((logXmlConfigFile != null) && (!logXmlConfigFile.equals(""))) {
logXml = logXmlConfigFile;
}
}
/**
* constructor init the Log4j only one time
*/
private LogHelper() {
synchronized (lock) {
if (!isInit) {
String file = null;
try {
// file = SystemConfig.getProperty("log.file.path");
if (StringUtils.isBlank(file)) {
URL res = super.getClass().getResource(logXml);
if (res == null) {
file = "." + logXml;
} else {
file = res.getPath();
}
}
DOMConfigurator.configure(file);
isInit = true;
} catch (Exception e) {
e.printStackTrace();
log.error("Log4j init fail:" + e.toString());
}
}
}
}
/**
* get a LogHelper instance by the log name.
*
* @param logName
* @return
*/
public static LogHelper getInstatnce(String logName) {
if (!logHelperMap.containsKey(logName)) {
LogHelper tmphelper = new LogHelper();
tmphelper.logger = Logger.getLogger(logName);
logHelperMap.put(logName, tmphelper);
return tmphelper;
}
return logHelperMap.get(logName);
}
/**
* for log4j ,the log level is info
*
* @param str
*/
public void write(String str) {
logger.info(str);
}
public void trace(Exception e) {
logger.info(LogHelper.class, e);
}
public void trace(Exception e, String str) {
logger.info(str);
logger.info(LogHelper.class, e);
}
public static String getLogClass() {
return "";
}
/**
* 输出到控制台
*
* @param str
*/
public static void stdout(String str) {
System.out.println(getLogDate() + getLogClass() + str);
}
public static void stderr(String str) {
System.err.println(getLogDate() + getLogClass() + str);
}
public static void stderrTrace(Exception e) {
System.err.println(getLogDate() + getLogClass() + e.toString());
e.printStackTrace();
}
private static String getLogDate() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return "[" + df.format(new Date()) + "] ";
}
public static void studioLog(String str) {
log.info(str);
getInstatnce("studioLog").logger.fatal(getLogClass() + str);
}
public static String locate(String esc) {
StringWriter sw = new StringWriter();
(new Exception()).printStackTrace(new PrintWriter(sw));
StringTokenizer st = new StringTokenizer(sw.toString(), "\n");
do {
if (!st.hasMoreTokens()) {
break;
}
String str = st.nextToken();
if (str.indexOf("Exception") != -1 || str.indexOf((LogHelper != null ? LogHelper
: (LogHelper = class$("com.ihandy.yuncai.studio.util.IhandyLogHelper"))).getName()) != -1 || esc != null && str
.indexOf(esc) != -1) {
continue;
}
if (esc == "!@*#~^?'/\"") {
return str;
}
int i = str.indexOf(40);
int j = str.indexOf(41);
if (i != -1 && j != -1) {
return str.substring(i, j + 1);
}
break;
} while (true);
return "";
}
protected static Class class$(String x1) {
try {
return Class.forName(x1);
} catch (ClassNotFoundException x2) {
throw new NoClassDefFoundError(x2.getMessage());
}
}
public static void exceptionLog(Throwable t) {
try {
String str = getTrace(t);
str = "\r\n>>>>>>>>>>>\r\n" + getLogDate() + "\r\n" + getLogClass() + str + "\r\n<<<<<<<<<";
System.out.println(str);
getInstatnce("exceptionLog").logger.fatal(str);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void exceptionLog(String msg, Throwable t) {
try {
String str = getTrace(t);
str = "\r\n>>>>>>>>>>>" + getLogDate() + "\r\n" + getLogClass() + "\r\n" + msg + "\r\n" + str + "\r\n<<<<<<<<<";
System.out.println(str);
getInstatnce("exceptionLog").logger.fatal(str);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void exceptionLog(String description, String errorMsg) {
try {
String str = "\r\n>>>>>>>>>>>" + getLogDate() + "\r\n" + getLogClass() + "\r\n" + description + "\r\n" + errorMsg + "\r\n<<<<<<<<<";
System.out.println(str);
getInstatnce("exceptionLog").logger.fatal(str);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void exceptionLog(String description) {
exceptionLog(description, "");
}
public static String getTrace(Throwable t) {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
t.printStackTrace(writer);
StringBuffer buffer = stringWriter.getBuffer();
return buffer.toString();
}
/**
* 访问日志参数添加方法,参数需要以键值对的形式传入
* 调用示例LogHelper.addAccessLogAttribute(request, "rechargeType", cardType, "rechargeAmount", amount.toString());
* @param request
* @param paramNames 参数及值对
*/
public static void addAccessLogAttribute(HttpServletRequest request, Object... paramNames) {
if ((paramNames.length % 2) == 0) {
for (int i = 0; i < paramNames.length / 2; i++) {
request.setAttribute(String.valueOf(paramNames[2 * i]), paramNames[2 * i + 1]);
}
} else {
String msg = "向访问日志传递日志参数不成对,属性无法添加";
exceptionLog(msg, new RuntimeException());
}
}
/**
* 请求参数
* @return
*/
public static String requestParamsJson(HttpServletRequest req) {
String paramsJson = "";
Map<String, Object> map = new HashMap<String, Object>();
Enumeration<String> paramNames = req.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
//进行屏蔽,不记录到日志
if (RegexUtil.validate("\\w*password\\w*", paramName)) {
continue;
}
//oios1.30需求中,屏蔽掉vip验证和恢复接口的参数
if ("jsondata".equals(paramName)) {
continue;
}
String paramValue = req.getParameter(paramName);
//参数的值超过500个字节时做截断
if (paramValue.length() > 500) {
paramValue = paramValue.substring(0, 500);
}
map.put(paramName, paramValue);
}
if (map != null && map.size() > 0) {
paramsJson = JSON.toJSONString(map);
//对“][”日志分割符进行转码成"]_["
paramsJson = paramsJson.replaceAll("]\\[", "]_[");
}
return paramsJson;
}
/**
* 处理参数
* @param request
* @param paramNames
*/
public static void addProcessingParams(HttpServletRequest request, Object... paramNames) {
Map<String, Object> map = new HashMap<String, Object>();
if ((paramNames.length % 2) == 0) {
for (int i = 0; i < paramNames.length / 2; i++) {
map.put(String.valueOf(paramNames[2 * i]), paramNames[2 * i + 1]);
}
} else {
String msg = "处理参数:向访问日志传递日志参数不成对,属性无法添加";
exceptionLog(msg, new RuntimeException());
}
request.setAttribute("processingParams", JSON.toJSONString(map));
}
}
接下来配置AOP-----------------------------------
第一种配置方法:使用@AspectJ标签
- 在配置文件中添加<aop:aspectj-autoproxy/>注解(注:SpringMVC的配置文件中完成,不要在spring的配置文件中完成)
- 创建一个Java文件,使用@Aspect注解修饰该类(LogHandler)
- 创建一个方法,使用@Before、@After、@Around等进行修饰,在注解中写上切入点的表达式(LogHandler中的方法)
说明:上述Java文件创建好后,需要将其在Spring的容器中进行声明,可以在配置文件中定义<bean/>节点,也可以使用@Component组件进行修饰
1、在SpringMVC配置文件中添加AOP注解的相关配置信息
<!--注解实现AOP切面 -->
<!-- 启动对@AspectJ注解的支持,通知spring使用cglib而不是jdk的来生成代理方法 -->
<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
<!--将Aspect类注册为Bean,@AfterReturning时需要使用此配置 -->
<context:component-scan base-package="com.warehouse.util">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
注意:proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。即使你未声明 proxy-target-class="true" ,但运行类没有继承接口,spring也会自动使用CGLIB代理。高版本spring自动根据运行类选择 JDK 或 CGLIB 代理
2、建一个文件进行相关的代理操作
package com.warehouse.controller.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.warehouse.controller.api.log.LogHelper;
@Component //注解实现AOP切面
@Aspect //注解实现AOP切面
public class LogHandler {
static{
System.out.println("-----------已加载LogHandler-----------");//查看LogHandler是否加载
}
//方法执行的前调用
@Before("execution(* com.warehouse.controller.*.*.*(..))") //注解实现AOP切面
public void doBeforeInServiceLayer(JoinPoint joinPoint) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date())+"====================================@Before:doBeforeInServiceLayer====================================");
StringBuilder sb = new StringBuilder();
sb.append(df.format(new Date())+"====================================@Before:doBeforeInServiceLayer====================================");
LogHelper.getInstatnce("inOutPutLog").write(sb.toString());
}
//方法执行的后调用
@After("execution(* com.warehouse.controller.*.*.*(..))") //注解实现AOP切面
public void doAfterInServiceLayer(JoinPoint joinPoint) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date())+"====================================@After:doAfterInServiceLayer====================================");
StringBuilder sb = new StringBuilder();
sb.append(df.format(new Date())+"====================================@After:doAfterInServiceLayer====================================");
LogHelper.getInstatnce("inOutPutLog").write(sb.toString());
}
//方法执行的前后调用
@Around("execution(* com.warehouse.controller.*.*(..))") //注解实现AOP切面
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
StringBuilder sb = new StringBuilder();
sb.append(df.format(new Date())+"====================================@Around:doAround====================================");
System.out.println(df.format(new Date())+"====================================@Around:doAround====================================");
LogHelper.getInstatnce("inOutPutLog").write(sb.toString());
}
//方法运行出现异常时调用
@AfterThrowing(pointcut = "execution (* com.warehouse.controller.*.*(..))",throwing = "ex") //注解实现AOP切面
public void doAfterThrowing(Exception ex){
System.out.println("====================================@AfterThrowing:doAfterThrowing====================================");
System.out.println(ex);
}
/**
* ControllerLayer
* 方法执行的后返回值
* @param joinPoint
* @param returnValue
*/
@AfterReturning(pointcut = "execution (* com.warehouse.controller.*.*.*(..))", returning = "returnValue")
public void doAfterReturnInControllerLayer(JoinPoint joinPoint, Object returnValue) {
if(logSwitch){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(df.format(new Date())+" INFO "+joinPoint.getTarget().getClass().getName()+":"+joinPoint.getSignature().getName()+" [Warehouse] - ");
stringBuilder.append(returnValue);
stringBuilder.append("\n");
// System.out.println(stringBuilder.toString());
LogHelper.getInstatnce("inOutPutLog").write(stringBuilder.toString());
}
}
/**
* ServiceLayer
* 方法执行的前调用
* @param joinPoint
*/
@Before("execution(* com.warehouse.service.impl.*.*(..))")
public void doBeforeInServiceLayer(JoinPoint joinPoint) {
if(logSwitch){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(df.format(new Date())+" INFO "+joinPoint.getTarget().getClass().getName()+":"+joinPoint.getSignature().getName()+" [Warehouse] - ");
for (int i = 0; i < joinPoint.getArgs().length; i++) {
JSONObject data = new JSONObject();
data.put("requestParameter", joinPoint.getArgs()[i]);
stringBuilder.append(data);
}
stringBuilder.append("\n");
//System.out.println(stringBuilder.toString());
LogHelper.getInstatnce("inOutPutLog").write(stringBuilder.toString());
}
}
/**
* ServiceLayer
* 方法执行的后返回值
* @param joinPoint
* @param returnValue
*/
@AfterReturning(pointcut = "execution (* com.warehouse.service.impl.*.*(..))", returning = "returnValue")
public void doAfterReturnInServiceLayer(JoinPoint joinPoint, Object returnValue) {
if(logSwitch){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(df.format(new Date())+" INFO "+joinPoint.getTarget().getClass().getName()+":"+joinPoint.getSignature().getName()+" [Warehouse] - ");
JSONObject data = new JSONObject();
data.put("returnValue", returnValue);
stringBuilder.append(data);
stringBuilder.append("\n");
//System.out.println(stringBuilder.toString());
LogHelper.getInstatnce("inOutPutLog").write(stringBuilder.toString());
}
}
/**
* ServiceLayer
* 方法执行的后调用
* @param joinPoint
*/
@After("execution(* com.warehouse.service.impl.*.*(..))")
public void doAfterInServiceLayer(JoinPoint joinPoint) {
if(logSwitch){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//System.out.println(df.format(new Date())+" @After:doAfterInServiceLayer ");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(df.format(new Date())+" @After:doAfterInServiceLayer ");
LogHelper.getInstatnce("inOutPutLog").write(stringBuilder.toString());
}
}
/**
* Debug日志
* @param className 类名称
* @param funName 方法名称
* @param content debug内容
*/
public void logRecordForDebug(String className, String funName, String content) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(df.format(new Date())+" DEBUG "+className+":"+funName+" [Warehouse] - ");
stringBuilder.append(content);
System.out.println(stringBuilder.toString());
LogHelper.getInstatnce("inOutPutLog").write(stringBuilder.toString());
}
}
第二种配置方法:基于配置文件的配置
- 创建一个Java文件,并指定一个用于执行拦截的方法(LogHandler)
- 在SpringMVC配置文件中注册该Java类为一个Bean
- 在SpringMVC使用<aop:config/>、<aop:aspect/>等标签进行配置
package com.warehouse.controller.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import com.warehouse.controller.api.log.LogHelper;
public class LogHandler {
static{
System.out.println("-----------已加载LogHandler-----------");//查看LogHandler是否加载
}
//方法执行的前调用
public void doBeforeInServiceLayer(JoinPoint joinPoint) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date())+"====================================@Before:doBeforeInServiceLayer====================================");
StringBuilder sb = new StringBuilder();
sb.append(df.format(new Date())+"====================================@Before:doBeforeInServiceLayer====================================");
LogHelper.getInstatnce("inOutPutLog").write(sb.toString());
}
//方法执行的后调用
public void doAfterInServiceLayer(JoinPoint joinPoint) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(df.format(new Date())+"====================================@After:doAfterInServiceLayer====================================");
StringBuilder sb = new StringBuilder();
sb.append(df.format(new Date())+"====================================@After:doAfterInServiceLayer====================================");
LogHelper.getInstatnce("inOutPutLog").write(sb.toString());
}
//方法执行的前后调用
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
StringBuilder sb = new StringBuilder();
sb.append(df.format(new Date())+"====================================@Around:doAround====================================");
System.out.println(df.format(new Date())+"====================================@Around:doAround====================================");
LogHelper.getInstatnce("inOutPutLog").write(sb.toString());
}
//方法运行出现异常时调用
public void doAfterThrowing(Exception ex){
System.out.println("====================================@AfterThrowing:doAfterThrowing====================================");
System.out.println(ex);
}
}
2、在SpringMVC配置文件中注册该Java类为一个Bean,使用<aop:config/>、<aop:aspect/>等标签进行配置
<!--配置文件实现AOP切面 -->
<bean id="logHandler" class="com.warehouse.controller.util.LogHandler" />
<aop:config>
<aop:aspect id="addInOutPutLog" ref="logHandler">
<aop:pointcut id="addAllMethod" expression="execution(* com.warehouse.controller.*.*.*(..))" />
<aop:before method="doBeforeInServiceLayer" pointcut-ref="addAllMethod" />
<aop:after method="doAfterInServiceLayer" pointcut-ref="addAllMethod" />
</aop:aspect>
</aop:config>
log4j MDC用户操作日志追踪配置
http://blog.csdn.net/userwyh/article/details/52862216
一种解决的办法是采用自定义的日志格式,把用户的信息采用某种方式编码在日志记录中。这种方式的问题在于要求在每个使用日志记录器的类中,都可以访问到用户相关的信息。这样才可能在记录日志时使用。这样的条件通常是比较难以满足的。MDC 的作用是解决这个问题。
MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。