自定义注解
@Inherited
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
String value() default "";
}
定义切面
@Aspect
@Component
@Slf4j
public class LogAop {
// 定义识别自定义注解的切点
@Pointcut("@annotation(com.jxy.MyLog)")
public void logger(){}
/**
*
* @param point
* @return
*/
@Around("logger()")
public Object around(ProceedingJoinPoint point) {
Object obj = null;
String ip_port = "";
String uri = "";
String value="";
HttpServletResponse response = null;
ControllerLogMapper bip2NCLogMapper = null;
bip2NCLogMapper = AppContext.getBean(ControllerLogMapper.class);
Signature methodName = point.getSignature();
String name = point.getSignature().getName();
log.error(methodName + "....running");
//Long start = System.currentTimeMillis();
Object[] argArray = point.getArgs();
if (argArray != null && argArray.length > 0) {
for (Object object : argArray) {
if (object instanceof HttpServletResponse) {
response = (HttpServletResponse) object;
}
}
}
// 目标方法执行
try {
Object res = point.proceed(point.getArgs());
obj = res ;
} catch (Throwable throwable) {
obj = "【" + name + "方法异常,异常信息:" + throwable + "】";
log.error("【环绕异常通知】【" + name + "方法异常,异常信息:" + throwable + "】");
throw new GlobalException(throwable.getMessage());
} finally {
try {
if (response != null) {
PrintWriter writerToBeRead = response.getWriter();
CoyoteWriter cw = (CoyoteWriter) writerToBeRead.append("");
Class<?> clazz = cw.getClass();
Field declaredField = clazz.getDeclaredField("ob");
declaredField.setAccessible(true);
OutputBuffer ob = (OutputBuffer) declaredField.get(cw);
Class<?> classOutputBuffer = ob.getClass();
//获取IP和端口 start
Class<?> responseClass = response.getClass();
Field requestField = responseClass.getDeclaredField("request");
requestField.setAccessible(true);
HttpServletRequest request = (HttpServletRequest) requestField.get(response);
String ip = request.getRemoteAddr();
//获取请求地址
uri = request.getRequestURI();
Field coyoteResponseField = classOutputBuffer.getDeclaredField("coyoteResponse");
coyoteResponseField.setAccessible(true);
Response coyoteResponse = (Response) coyoteResponseField.get(ob);
Class<?> coyoteResponseClass = coyoteResponse.getClass();
Field reqField = coyoteResponseClass.getDeclaredField("req");
reqField.setAccessible(true);
Request request1 = (Request) reqField.get(coyoteResponse);
int port = request1.getServerPort();
ip_port = ip + ":" + port;
//获取IP和端口 end
Field fieldOutputChunk = classOutputBuffer.getDeclaredField("cb");
fieldOutputChunk.setAccessible(true);
obj = fieldOutputChunk.get(ob) == null ? "" : fieldOutputChunk.get(ob).toString();
}
MethodSignature signature = (MethodSignature) point.getSignature();
MyLog declaredAnnotation = signature.getMethod().getDeclaredAnnotation(MyLog.class);
value = declaredAnnotation.value();
log.error("==注解@MyLog的value=="+ value);
//记录到日志表
String loginUser = AppContext.getCurrentUser() == null ? "第三方调用" : AppContext.getCurrentUser().getId().toString();
String YTenantId = com.yonyou.eforship.common.utils.yms.AppContextUtil.getCurrentOrDefaultTenantId() == null ? "" : com.yonyou.eforship.common.utils.yms.AppContextUtil.getCurrentOrDefaultTenantId().toString();
bip2NCLogMapper.add(String.valueOf(IdManager.getInstance().nextId()), loginUser, ArrayUtils.toString(argArray, ","), obj == null?"":obj.toString(), methodName.toString(), YTenantId, ip_port,uri,value);
} catch (Exception e) {
log.error("ControllerLog接口日志创建异常:" + e.getMessage());
}
log.error("【环绕后置通知】【" + name + "方法结束】");
}
//Long end = System.currentTimeMillis();
//log.info(methodName + "....stop" + "\t耗时:" + (end - start));
return obj;
}
public String getResponseContent(HttpServletResponse response) throws IOException, NoSuchFieldException, IllegalAccessException {
String responseContent = null;
CoyoteOutputStream outputStream = (CoyoteOutputStream) response.getOutputStream();
Class<CoyoteOutputStream> coyoteOutputStreamClass = CoyoteOutputStream.class;
Field obField = coyoteOutputStreamClass.getDeclaredField("ob");
if (obField.getType().toString().endsWith("OutputBuffer")) {
obField.setAccessible(true);
org.apache.catalina.connector.OutputBuffer outputBuffer = (org.apache.catalina.connector.OutputBuffer) obField.get(outputStream);
Class<org.apache.catalina.connector.OutputBuffer> opb = org.apache.catalina.connector.OutputBuffer.class;
Field outputChunkField = opb.getDeclaredField("outputChunk");
outputChunkField.setAccessible(true);
if (outputChunkField.getType().toString().endsWith("ByteChunk")) {
ByteChunk bc = (ByteChunk) outputChunkField.get(outputBuffer);
Integer length = bc.getLength();
if (length == 0) return null;
responseContent = new String(bc.getBytes(), "UTF-8");
Integer responseLength = StringUtils.isBlank(responseContent) ? 0 : responseContent.length();
if (responseLength < length) {
responseContent = responseContent.substring(0, responseLength);
} else {
responseContent = responseContent.substring(0, length);
}
}
}
return responseContent;
}
/**
* 如果程序出现了异常,则需要拦截,打印异常信息
* @param joinPoint
* @param throwable
*/
@AfterThrowing
(pointcut = "logger()",
throwing = "throwable")
public void afterThrow(JoinPoint joinPoint, Throwable throwable) {
Class<?> targetClass = joinPoint.getTarget().getClass();
String methodName = joinPoint.getSignature().getName();
Class<?> throwClass = throwable.getClass();
String msg = throwable.getMessage();
log.error("目标对象类型:" + targetClass);
log.error("目标方法:" + methodName);
log.error("异常类型:" + throwClass);
log.error("异常信息:" + msg);
}
}
使用
该自定义注解作用于方法上,如果需要日志处理,直接使用注解即可。