1. 切面日志注解
最近看别人的自定义注解还是很优秀,再次一边学习一边解析一下
日志服务用的@Slf4j 作为服务支持
1.1 Log自定义注解
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface AroundLog {
AroundLogMethod method() default AroundLogMethod.DEFAULT;
boolean pre() default true;
boolean post() default false;
}
还定义了一个枚举类型来
public enum AroundLogMethod {
GET,
POST,
DEFAULT
}
1.2 @Around
环绕增强,相当于MethodInterceptor.
* @Before: 标识一个前置增强方法,相当于BeforeAdvice的功能. * @After: final增强,不管是抛出异常或者正常退出都会执行. * @AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行. * @AfterThrowing: 异常抛出增强,相当于ThrowsAdvice. * @Around: 环绕增强,相当于MethodInterceptor.
1.3
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Aspect
@Component
public class AccessLogAscept {
private static final List<String> ignoreUri = Stream.of("***", "***").collect(Collectors.toList());
private static final Logger logger = LoggerFactory.getLogger("access");
@AfterReturning(value = "@annotation(org.springframework.web.bind.annotation.PostMapping)", returning="result")
public void afterReturning(JoinPoint point, Object result){
if(result instanceof RespResult){
accessLog((RespResult)result);
}else{
accessLog(new RespResult(RespCode.SUCC, ""));
}
}
@AfterThrowing(value = "@annotation(org.springframework.web.bind.annotation.PostMapping)", throwing="ex")
public void afterReturning(JoinPoint point, Exception ex){
RespResult respResult = JsonUtils.fromJson(ex.getMessage(), RespResult.class);
if(null == respResult){
accessLog(new RespResult(-1, ex.getMessage() , ""));
}else {
accessLog(respResult);
}
}
private void accessLog(RespResult result) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
String uri = request.getRequestURI();
if(ignoreUri.contains(uri)){ //过滤掉某些接口的日志
return;
}
long inTimeMillis = MyThreadLocal.getInTimeMillis();
String time = DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss.SSS");
String ip = getIpAddr(request);
String userName = null==MyThreadLocal.getUserInfo()?"":MyThreadLocal.getUserInfo().getUserName();
String globalRequestId = MyThreadLocal.getCurGlobalRequestId();
long diff = System.currentTimeMillis() - inTimeMillis;
int rtn = result.getCode();
String msg = result.getMsg();
logger.warn(String.format("%s;%s;%s;%s;%s;%s;%s;%s",time, nonReplace(ip), nonReplace(userName), nonReplace(globalRequestId),
nonReplace(uri), diff, rtn, msg));
}
private String nonReplace(String s) {
return StringUtils.isBlank(s) ? "-" : s;
}
private String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个ip值,第一个ip才是真实ip
if( ip.indexOf(",")!=-1 ){
ip = ip.split(",")[0];
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}