使用 AOP 打印全局日志
这是第一次使用 AOP 打印全局日志 , 直接展示代码 。 步骤如下 :
一 : 导入需要的依赖
-
使用springboot项目
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
-
使用springMVC , 需要xml配置文件的项目
<context:component-scan base-package="com.cmrh.mas.moa.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!-- 开启自动代理 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <bean id="restControllerLogAspect" class="com.cmrh.mas.base.filter.RestControllerLogAspect" />
-
增加了 检查列表 功能。
二 : 自定义注解
可以使用spring自带注解 : 如 org.springframework.web.bind.annotation.RequestMapping
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface HttpLog {
}
三 : 日志逻辑
-
执行前的特殊处理器
public interface RequestMessageSpecialLogProcessor { void process(ProceedingJoinPoint proceedingJoinPoint, StringBuilder logSB); }
2.请求头信息
方式1 :
@Aspect
public class RestControllerLogAspect {
//用于控制一次请求只打印一次日志
private static ThreadLocal<Boolean> hasLog = new ThreadLocal<Boolean>();
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
private void httpLogPointcut() {
}
@Pointcut("execution(* com.cmrh.mas.base.web.TokenController.login(..))")
private void loginLogPointcut() {
}
@Pointcut("execution(* com.cmrh.mas.base.web.FaceImagesV2Controller.isTheSamePerson(..))")
private void aiipLogPointcut() {
}
@Around("httpLogPointcut() && !aiipLogPointcut() && !loginLogPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
boolean needLog = false;
if(hasLog.get() == null || !hasLog.get()){
needLog = hasLog.get() == null || !hasLog.get();
hasLog.set(true);
}
if(!needLog){
return proceedingJoinPoint.proceed();
}
try{
return MethodLogUtil.aroundLog(proceedingJoinPoint, "accept http request", new RequestMessageSpecialLogProcessor() {
@Override
public void process(ProceedingJoinPoint proceedingJoinPoint, StringBuilder logSB) {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
logSB.append("\r\n\turl: ");
logSB.append(request.getRequestURL());
logSB.append("\r\n\treferer: ");
logSB.append(request.getHeader("referer"));
logSB.append("\r\n\ttRequestId: ");
logSB.append(request.getHeader("tRequestId"));
logSB.append("\r\n\tuser-Agent: ");
logSB.append(request.getHeader("user-Agent"));
logSB.append("\r\n\tsession: ");
Enumeration<String> names = session.getAttributeNames();
String name = null;
// 列举所有session attr
if(names != null){
while(names.hasMoreElements()){
name = names.nextElement();
logSB.append("\r\n\t\t");
logSB.append(name);
logSB.append(":");
logSB.append(session.getAttribute(name));
}
}
logSB.append("\r\n\trequestParam: ");
// 列举所有req param
names = request.getParameterNames();
if(names != null) {
while(names.hasMoreElements()) {
name = names.nextElement();
logSB.append("\r\n\t\t");
logSB.append(name);
logSB.append(": ");
logSB.append(request.getParameter(name));
}
}
}
});
}finally{
hasLog.set(false);
}
}
方式2 :
@Aspect
@Component
public class HttpLogAspect {
@Pointcut("@annotation(com.cmft.filter.HttpLog)")
private void restOperationPointcut() {
}
@Around(value = "restOperationPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
return MethodLogUtil.aroundLog(proceedingJoinPoint, "invoke http request");
}
}
3.工具类
public class MethodLogUtil {
private static final Logger logger = LoggerFactory.getLogger(RestControllerLogAspect.class);
/**
* arount advice日志记录
* @param proceedingJoinPoint
* @param actionName
* @return
* @throws Throwable
*/
public static Object aroundLog(ProceedingJoinPoint proceedingJoinPoint, String actionName) throws Throwable{
return MethodLogUtil.aroundLog(proceedingJoinPoint, actionName, null);
}
/**
* arount advice日志记录
* @param proceedingJoinPoint
* @param actionName
* @param beforeExecLogProcessor
* @return
* @throws Throwable
*/
public static Object aroundLog(ProceedingJoinPoint proceedingJoinPoint, String actionName, RequestMessageSpecialLogProcessor beforeExecLogProcessor) throws Throwable{
StringBuilder logSB = new StringBuilder();
logSB.append(MessageFormat.format("\r\n\r\n---------------{0} start---------------", actionName));
long startTimestamp = System.currentTimeMillis();
logSB.append("\r\ncurrent time: ");
logSB.append(DateFormatUtils.format(new Date(), "yyyy-MM-dd hh:mm:ss"));
logSB.append("\r\nmethod: ");
logSB.append(proceedingJoinPoint.getSignature().toLongString());
logSB.append("\r\nrequest message");
if(beforeExecLogProcessor != null){
beforeExecLogProcessor.process(proceedingJoinPoint, logSB);
}
logSB.append("\r\n\targs: ");
Object[] args = proceedingJoinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
String[] parameterNames = methodSignature.getParameterNames();
for(int i=0, len=args.length; i< len; i++){
logSB.append("\r\n\t\t");
if(parameterNames == null){
logSB.append(i);
}else{
logSB.append(parameterNames[i]);
logSB.append("[");
logSB.append(parameterNames[i].getClass());
logSB.append("]");
}
logSB.append(":");
if(args[i] == null){
logSB.append(args[i]);
}else if(args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse
|| args[i] instanceof HttpSession){
//logSB.append(args[i]);
}else{
logSB.append(JSON.toJSONString(args[i]));
}
}
try {
Object object = proceedingJoinPoint.proceed();
logSB.append(StringUtils.join("\r\nresponse message"));
logSB.append("\r\n\t");
if(object != null){
String jsonString = JSON.toJSONString(object);
logSB.append(jsonString.length() > 1000 ? jsonString.substring(0, 1000) + "..." : jsonString);
}
return object;
} catch (Throwable e) {
logSB.append("\r\nexception:" + e.getMessage());
throw e;
} finally {
logSB.append("\r\nuse time(ms):" + (System.currentTimeMillis() - startTimestamp));
logSB.append(MessageFormat.format("\r\n---------------{0} end---------------\r\n\r\n", actionName));
logger.info(logSB.toString());
}
}