From aff071b607fd193b58088c484d1e58e8c91df9cb Mon Sep 17 00:00:00 2001 From: xsx Date: Wed, 19 Jun 2019 22:44:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + pom.xml | 164 ++++++++++ .../xsx/core/config/LogAutoConfiguration.java | 23 ++ src/main/java/wiki/xsx/core/log/Level.java | 26 ++ src/main/java/wiki/xsx/core/log/Log.java | 26 ++ .../java/wiki/xsx/core/log/LogProcessor.java | 284 ++++++++++++++++++ src/main/java/wiki/xsx/core/log/ParamLog.java | 26 ++ .../java/wiki/xsx/core/log/ResultLog.java | 26 ++ .../java/wiki/xsx/core/log/ThrowingLog.java | 20 ++ .../wiki/xsx/core/support/MethodInfo.java | 39 +++ .../wiki/xsx/core/support/MethodParser.java | 74 +++++ src/main/resources/META-INF/spring.factories | 2 + 12 files changed, 714 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java create mode 100644 src/main/java/wiki/xsx/core/log/Level.java create mode 100644 src/main/java/wiki/xsx/core/log/Log.java create mode 100644 src/main/java/wiki/xsx/core/log/LogProcessor.java create mode 100644 src/main/java/wiki/xsx/core/log/ParamLog.java create mode 100644 src/main/java/wiki/xsx/core/log/ResultLog.java create mode 100644 src/main/java/wiki/xsx/core/log/ThrowingLog.java create mode 100644 src/main/java/wiki/xsx/core/support/MethodInfo.java create mode 100644 src/main/java/wiki/xsx/core/support/MethodParser.java create mode 100644 src/main/resources/META-INF/spring.factories diff --git a/.gitignore b/.gitignore index a1c2a23..109980d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,7 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +#others +*.idea +*.iml \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a891873 --- /dev/null +++ b/pom.xml @@ -0,0 +1,164 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.5.RELEASE + + + wiki.xsx + spring-boot-starter-slf4j + 1.0.0 + jar + spring-boot-starter-slf4j + http://www.xsx.wiki + log project for Spring Boot + + + 1.8 + 2.1.5.RELEASE + 3.25.0-GA + 1.18.8 + + true + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + https://gitee.com/xsxgit/spring-boot-starter-slf4j + git@gitee.com:xsxgit/spring-boot-starter-slf4j.git + https://gitee.com/xsxgit/spring-boot-starter-slf4j.git + + + + xsx + xsx344646090@vip.qq.com + http://www.xsx.wiki + + + + + + release + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + oss + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-source-plugin + 3.1.0 + + + package + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.0 + + + -Xdoclint:none + + + + + package + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + verify + + sign + + + + + + + + + oss + https://oss.sonatype.org/content/repositories/snapshots + + + oss + https://oss.sonatype.org/service/local/staging/deploy/maven2 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + UTF-8 + + + + + + + + org.springframework.boot + spring-boot-starter + ${spring-boot.version} + + + + org.springframework.boot + spring-boot-starter-aop + ${spring-boot.version} + + + + org.javassist + javassist + ${javassist.version} + + + + org.projectlombok + lombok + ${lombok.version} + true + + + diff --git a/src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java b/src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java new file mode 100644 index 0000000..d5fe478 --- /dev/null +++ b/src/main/java/wiki/xsx/core/config/LogAutoConfiguration.java @@ -0,0 +1,23 @@ +package wiki.xsx.core.config; + +import org.slf4j.Logger; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import wiki.xsx.core.log.LogProcessor; + +/** + * 日志自动装配 + * @author xsx + * @date 2019/6/19 + * @since 1.8 + */ +@Configuration +@ConditionalOnClass({Logger.class}) +public class LogAutoConfiguration { + + @Bean + public LogProcessor logProcessor() { + return new LogProcessor(); + } +} diff --git a/src/main/java/wiki/xsx/core/log/Level.java b/src/main/java/wiki/xsx/core/log/Level.java new file mode 100644 index 0000000..399c8af --- /dev/null +++ b/src/main/java/wiki/xsx/core/log/Level.java @@ -0,0 +1,26 @@ +package wiki.xsx.core.log; + +/** + * 日志级别 + * @author xsx + * @date 2019/6/19 + * @since 1.8 + */ +public enum Level { + /** + * 调试级别 + */ + DEBUG, + /** + * 信息级别 + */ + INFO, + /** + * 警告级别 + */ + WARN, + /** + * 错误级别 + */ + ERROR; +} diff --git a/src/main/java/wiki/xsx/core/log/Log.java b/src/main/java/wiki/xsx/core/log/Log.java new file mode 100644 index 0000000..fb38152 --- /dev/null +++ b/src/main/java/wiki/xsx/core/log/Log.java @@ -0,0 +1,26 @@ +package wiki.xsx.core.log; + +import java.lang.annotation.*; + +/** + * 综合日志 + * @author xsx + * @date 2019/6/18 + * @since 1.8 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log { + /** + * 业务名称 + * @return + */ + String value(); + + /** + * 日志级别 + * @return + */ + Level level() default Level.DEBUG; +} diff --git a/src/main/java/wiki/xsx/core/log/LogProcessor.java b/src/main/java/wiki/xsx/core/log/LogProcessor.java new file mode 100644 index 0000000..ec9c9a7 --- /dev/null +++ b/src/main/java/wiki/xsx/core/log/LogProcessor.java @@ -0,0 +1,284 @@ +package wiki.xsx.core.log; + +import javassist.CtMethod; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.*; +import wiki.xsx.core.support.MethodInfo; +import wiki.xsx.core.support.MethodParser; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 日志处理器 + * @author xsx + * @date 2019/6/17 + * @since 1.8 + */ +@Aspect +@Slf4j +public class LogProcessor { + + /** + * 打印参数日志 + * @param joinPoint 切入点 + */ + @Before("@annotation(ParamLog)") + public void beforPrint(JoinPoint joinPoint) { + Object[] args = joinPoint.getArgs(); + Signature signature = joinPoint.getSignature(); + String methodName = signature.getName(); + try { + CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName); + ParamLog paramLogAnnotation; + try { + paramLogAnnotation = (ParamLog) method.getAnnotation(ParamLog.class); + } catch (ClassNotFoundException e) { + paramLogAnnotation = null; + } + if (paramLogAnnotation!=null) { + this.print( + paramLogAnnotation.level(), + this.getBeforeInfo( + paramLogAnnotation.value(), + signature, + MethodParser.getMethodInfo(method), + args + ) + ); + } + } catch (Exception e) { + log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName); + } + } + + /** + * 打印返回值日志 + * @param joinPoint 切入点 + * @param result 返回结果 + */ + @AfterReturning(value = "@annotation(ResultLog)", returning = "result") + public void afterPrint(JoinPoint joinPoint, Object result) { + Signature signature = joinPoint.getSignature(); + String methodName = signature.getName(); + try { + CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName); + ResultLog resultLogAnnotation; + try { + resultLogAnnotation = (ResultLog) method.getAnnotation(ResultLog.class); + } catch (ClassNotFoundException e) { + resultLogAnnotation = null; + } + if (resultLogAnnotation!=null) { + this.print( + resultLogAnnotation.level(), + this.getAfterInfo( + resultLogAnnotation.value(), + signature, + MethodParser.getMethodInfo(method), + result + ) + ); + } + } catch (Exception e) { + log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName); + } + } + + /** + * 打印异常日志 + * @param joinPoint 切入点 + * @param throwable 异常 + */ + @AfterThrowing(value = "@annotation(ThrowingLog)||@annotation(Log)", throwing = "throwable") + public void throwingPrint(JoinPoint joinPoint, Throwable throwable) { + Signature signature = joinPoint.getSignature(); + String methodName = signature.getName(); + try { + CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName); + ThrowingLog throwingAnnotation; + try { + throwingAnnotation = (ThrowingLog) method.getAnnotation(ThrowingLog.class); + } catch (ClassNotFoundException e) { + throwingAnnotation = null; + } + if (throwingAnnotation!=null) { + log.error( + this.getThrowingInfo( + throwingAnnotation.value(), + signature, + MethodParser.getMethodInfo(method) + ), + throwable + ); + }else { + Log logAnnotation; + try { + logAnnotation = (Log) method.getAnnotation(Log.class); + } catch (ClassNotFoundException e) { + logAnnotation = null; + } + if (logAnnotation!=null) { + log.error( + this.getThrowingInfo( + logAnnotation.value(), + signature, + MethodParser.getMethodInfo(method) + ), + throwable + ); + } + } + } catch (Exception e) { + log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName); + } + } + + /** + * 打印环绕日志 + * @param joinPoint 切入点 + * @return 返回方法返回值 + * @throws Throwable 异常 + */ + @Around(value = "@annotation(Log)") + public Object aroundPrint(ProceedingJoinPoint joinPoint) throws Throwable { + Object[] args = joinPoint.getArgs(); + Signature signature = joinPoint.getSignature(); + String methodName = signature.getName(); + try { + CtMethod method = MethodParser.getMethod(signature.getDeclaringTypeName(), methodName); + Log logAnnotation; + try { + logAnnotation = (Log) method.getAnnotation(Log.class); + } catch (ClassNotFoundException e) { + logAnnotation = null; + } + if (logAnnotation!=null) { + this.print( + logAnnotation.level(), + this.getBeforeInfo( + logAnnotation.value(), + signature, + MethodParser.getMethodInfo(method), + args + ) + ); + } + Object result = joinPoint.proceed(args); + if (logAnnotation!=null) { + this.print( + logAnnotation.level(), + this.getAfterInfo( + logAnnotation.value(), + signature, + MethodParser.getMethodInfo(method), + result + ) + ); + } + return result; + } catch (Throwable e) { + log.error("{}.{}方法错误", signature.getDeclaringTypeName(), methodName); + throw e; + } + } + + /** + * 获取日志信息字符串 + * @param busName 业务名 + * @param signature 签名信息 + * @param methodInfo 方法信息 + * @param params 参数值 + * @return 返回日志信息字符串 + */ + private String getBeforeInfo(String busName, Signature signature, MethodInfo methodInfo, Object[] params) { + StringBuilder builder = new StringBuilder(); + builder.append("调用方法:【").append(this.createMethodStack(signature, methodInfo)).append("】,") + .append("业务名称:【").append(busName).append("】,").append("接收参数:【"); + List paramNames = methodInfo.getParamNames(); + int count = paramNames.size(); + if (count>0) { + Map paramMap = new HashMap<>(count); + for (int i = 0; i < count; i++) { + paramMap.put(paramNames.get(i), params[i]); + } + return builder.append(paramMap).append("】").toString(); + } + return builder.append("{}】").toString(); + } + + /** + * 获取日志信息字符串 + * @param busName 业务名 + * @param signature 签名信息 + * @param methodInfo 方法信息 + * @param result 返回结果 + * @return 返回日志信息字符串 + */ + private String getAfterInfo(String busName, Signature signature, MethodInfo methodInfo, Object result) { + StringBuilder builder = new StringBuilder(); + builder.append("调用方法:【").append(this.createMethodStack(signature, methodInfo)).append("】,") + .append("业务名称:【").append(busName).append("】,").append("返回结果:【").append(result).append("】"); + return builder.toString(); + } + + /** + * 获取日志信息字符串 + * @param busName 业务名 + * @param signature 签名信息 + * @param methodInfo 方法信息 + * @return 返回日志信息字符串 + */ + private String getThrowingInfo(String busName, Signature signature, MethodInfo methodInfo) { + StringBuilder builder = new StringBuilder(); + builder.append("调用方法:【").append(this.createMethodStack(signature, methodInfo)).append("】,") + .append("业务名称:【").append(busName).append("】,").append("异常信息:"); + return builder.toString(); + } + + /** + * 创建方法栈 + * @param signature 签名信息 + * @param methodInfo 方法信息 + * @return 返回栈信息 + */ + private StackTraceElement createMethodStack(Signature signature, MethodInfo methodInfo) { + return new StackTraceElement( + signature.getDeclaringTypeName(), + methodInfo.getMethodName(), + String.format("%s.java", signature.getDeclaringType().getSimpleName()), + methodInfo.getLineNumber() + ); + } + + /** + * 打印信息 + * @param level 日志级别 + * @param msg 输出信息 + */ + private void print(Level level, String msg) { + switch (level) { + case DEBUG: { + log.debug(msg); + break; + } + case INFO: { + log.info(msg); + break; + } + case WARN: { + log.warn(msg); + break; + } + case ERROR: { + log.error(msg); + break; + } + default: + } + } +} diff --git a/src/main/java/wiki/xsx/core/log/ParamLog.java b/src/main/java/wiki/xsx/core/log/ParamLog.java new file mode 100644 index 0000000..e1795ed --- /dev/null +++ b/src/main/java/wiki/xsx/core/log/ParamLog.java @@ -0,0 +1,26 @@ +package wiki.xsx.core.log; + +import java.lang.annotation.*; + +/** + * 参数日志 + * @author xsx + * @date 2019/6/17 + * @since 1.8 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ParamLog { + /** + * 业务名称 + * @return + */ + String value(); + + /** + * 日志级别 + * @return + */ + Level level() default Level.DEBUG; +} diff --git a/src/main/java/wiki/xsx/core/log/ResultLog.java b/src/main/java/wiki/xsx/core/log/ResultLog.java new file mode 100644 index 0000000..19ee72b --- /dev/null +++ b/src/main/java/wiki/xsx/core/log/ResultLog.java @@ -0,0 +1,26 @@ +package wiki.xsx.core.log; + +import java.lang.annotation.*; + +/** + * 结果日志 + * @author xsx + * @date 2019/6/18 + * @since 1.8 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ResultLog { + /** + * 业务名称 + * @return + */ + String value(); + + /** + * 日志级别 + * @return + */ + Level level() default Level.DEBUG; +} diff --git a/src/main/java/wiki/xsx/core/log/ThrowingLog.java b/src/main/java/wiki/xsx/core/log/ThrowingLog.java new file mode 100644 index 0000000..08ad280 --- /dev/null +++ b/src/main/java/wiki/xsx/core/log/ThrowingLog.java @@ -0,0 +1,20 @@ +package wiki.xsx.core.log; + +import java.lang.annotation.*; + +/** + * 异常日志 + * @author xsx + * @date 2019/6/19 + * @since 1.8 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ThrowingLog { + /** + * 业务名称 + * @return + */ + String value(); +} diff --git a/src/main/java/wiki/xsx/core/support/MethodInfo.java b/src/main/java/wiki/xsx/core/support/MethodInfo.java new file mode 100644 index 0000000..6e0351c --- /dev/null +++ b/src/main/java/wiki/xsx/core/support/MethodInfo.java @@ -0,0 +1,39 @@ +package wiki.xsx.core.support; + +import lombok.Data; + +import java.util.List; + +/** + * 方法信息 + * @author xsx + * @date 2019/6/19 + * @since 1.8 + */ +@Data +public class MethodInfo { + /** + * 方法名称 + */ + private String methodName; + /** + * 参数列表 + */ + private List paramNames; + /** + * 方法行号 + */ + private Integer lineNumber; + + /** + * 构造 + * @param methodName 方法名称 + * @param paramNames 参数列表 + * @param lineNumber 方法行号 + */ + MethodInfo(String methodName, List paramNames, Integer lineNumber) { + this.methodName = methodName; + this.paramNames = paramNames; + this.lineNumber = lineNumber; + } +} diff --git a/src/main/java/wiki/xsx/core/support/MethodParser.java b/src/main/java/wiki/xsx/core/support/MethodParser.java new file mode 100644 index 0000000..68a8950 --- /dev/null +++ b/src/main/java/wiki/xsx/core/support/MethodParser.java @@ -0,0 +1,74 @@ +package wiki.xsx.core.support; + +import javassist.ClassPool; +import javassist.CtMethod; +import javassist.NotFoundException; +import javassist.bytecode.LocalVariableAttribute; + +import java.util.ArrayList; +import java.util.List; + +/** + * 方法解析器 + * @author xsx + * @date 2019/6/19 + * @since 1.8 + */ +public class MethodParser { + + /** + * 类池 + */ + private final static ClassPool POOL = ClassPool.getDefault(); + + /** + * 获取调用方法 + * @param className 全类名 + * @param methodName 方法名称 + * @return 返回对应方法 + * @throws NotFoundException 未知方法异常 + */ + public static CtMethod getMethod(String className, String methodName) throws NotFoundException { + return POOL.get(className).getDeclaredMethod(methodName); + } + + /** + * 获取方法信息 + * @param className 全类名 + * @param methodName 方法名称 + * @return 返回方法信息 + */ + public static MethodInfo getMethodInfo(String className, String methodName) { + try { + return getMethodInfo(getMethod(className, methodName)); + } catch (Exception e) { + return new MethodInfo(methodName, new ArrayList<>(0), -1); + } + } + + /** + * 获取方法信息 + * @param method 方法对象 + * @return 返回方法信息 + */ + public static MethodInfo getMethodInfo(CtMethod method) { + try { + javassist.bytecode.MethodInfo methodInfo = method.getMethodInfo(); + int lineNumber = methodInfo.getLineNumber(0); + List paramNames; + LocalVariableAttribute attribute = (LocalVariableAttribute) methodInfo.getCodeAttribute().getAttribute(LocalVariableAttribute.tag); + if (attribute!=null) { + int count = method.getParameterTypes().length; + paramNames = new ArrayList<>(count); + for (int i = 1; i <= count; i++) { + paramNames.add(attribute.variableName(i)); + } + }else { + paramNames = new ArrayList<>(0); + } + return new MethodInfo(method.getName(), paramNames, lineNumber); + } catch (Exception e) { + return new MethodInfo(method.getName(), new ArrayList<>(0), -1); + } + } +} diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..ed41837 --- /dev/null +++ b/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +#log自动装配 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=wiki.xsx.core.config.LogAutoConfiguration \ No newline at end of file -- Gitee From 2a572e703c73d3904b7466ec86f7ef283f5d6515 Mon Sep 17 00:00:00 2001 From: xsx Date: Wed, 19 Jun 2019 22:45:31 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6README.?= =?UTF-8?q?en.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en.md | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 README.en.md diff --git a/README.en.md b/README.en.md deleted file mode 100644 index b44bb95..0000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# spring-boot-starter-slf4j - -#### Description -一个注解搞定日志 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) \ No newline at end of file -- Gitee