利用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 應用來說,通常是在請求被處理的最開始保存這些數據。