springboot 项目中自定义注解,实现对日志的记录

作者 : admin 本文共4687个字,预计阅读时间需要12分钟 发布时间: 2024-06-12 共1人阅读

第一步自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogEntry {
    LogLevel value() default LogLevel.INFO;// 日志级别

    LogCzlxEnum logCzlx() default LogCzlxEnum.QUERY;// 日志类型

    String logContent() default "";// 日志内容

    String inputKey() default "";// 输入参数的主键记录,格式如上所示

    String outputKey() default "";// 输出参数

    boolean showArgs() default true;// 显示输入参数

    boolean showResult() default true;// 显示输出参数
}

第二步设置切面

@Aspect
@Component
public class LogEntryAspect {
@Autowired
private LogServiceImpl logService;
@Resource
private PurviewServiceImpl purviewService;
@Around("@annotation(LogEntry)")
public Object log(ProceedingJoinPoint point) throws Throwable {
Exception innerException = null;
var codeSignature = (CodeSignature) point.getSignature();
var methodSignature = (MethodSignature) point.getSignature();
Method method = methodSignature.getMethod();
Logger logger = LoggerFactory.getLogger(method.getDeclaringClass());
LogEntry annotation = method.getAnnotation(LogEntry.class);
LogLevel level = annotation.value();
boolean showArgs = annotation.showArgs();
boolean showResult = annotation.showResult();
LogCzlxEnum logCzlx = annotation.logCzlx();
String logContent = annotation.logContent();
String methodName = method.getName();
Class<?> declaringClass = method.getDeclaringClass();
String className = declaringClass.getSimpleName();
methodName = className + "#" + methodName;
// 切入点方法的参数对应的值
Object[] methodArgs = point.getArgs();
// 方法的参数
String[] methodParams = codeSignature.getParameterNames();
String input = "";
if (showArgs && Objects.nonNull(methodParams) && Objects.nonNull(methodArgs) && methodParams.length == methodArgs.length) {
Map<String, Object> values = new HashMap<>(methodParams.length);
for (int i = 0; i < methodParams.length; i++) {
values.put(methodParams[i], methodArgs[i]);
}
// 输入值
input = values.toString();
}
MethodExpressionEvaluator evaluator = new MethodExpressionEvaluator(point);
String inputkey = String.valueOf(evaluator.getValue(annotation.inputKey()));
logContent = String.valueOf(evaluator.getValue(logContent));
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
String sessionId = "";
if (requestAttributes != null) {
sessionId = requestAttributes.getSessionId();
}
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();
String remoteHost = request.getRemoteHost();
String requestURI = request.getRequestURI();
User sessionUser = ScopeUtil.getSessionUser();
String courtNo = "";
String userid = "";
String username = "";
if (sessionUser != null) {
courtNo = sessionUser.getCourtNo();
userid = sessionUser.getUserid();
username = sessionUser.getUsername();
}
Czjg jg = Czjg.SUCCESS;
//执行注解的方法
Object response = null;
try {
response = point.proceed();
if(null!=response && response instanceof Result) {
if(!((Result)response).isSuccess()) {
jg = Czjg.FAILED;
}
}
} catch (Exception e) {
innerException = e;
jg = Czjg.FAILED;
}
boolean isTempRole = purviewService.userIsRole(userid, "数字化档案补录");
if(isTempRole) return response;
String date = SysTools.formatDate(new Date(), "yyyy-MM-dd hh:mm:ss");
StringJoiner stringJoiner = new StringJoiner(" ");
String message = stringJoiner.add(" 日志记录访问时间=").add(date)
.add("用户名=").add(username)
.add("用户id=").add(userid)
.add("法院编号=").add(courtNo)
.add("方法名=").add(methodName)
.add("方法入参=").add(input)
.add("ywpk=").add(inputkey)
.add("操作类型=").add(logCzlx.getText())
.add("操作结果=").add(jg.getInfo())
.add("方法内容=").add(logContent)
.add("sessionid=").add(sessionId)
.add("remoteHost=").add(remoteHost)
.add("requestURI=").add(requestURI)
.toString();
Log log = new Log();
log.setCzlx(logCzlx.getValue())
.setCznr(logContent)
.setCzsj(new Date())
.setCourtNo(courtNo)
.setMethodname(methodName)
.setSessionid(sessionId)
.setUserhost(remoteHost)
.setUserid(userid)
.setUsername(username)
.setYwpk(inputkey)
.setInputs(input)
.setJg(jg.getCode());
// 顺序:先日志log文件,再数据库和 ELK
log(logger, level, message);
logService.save(log);
if (null != innerException) {
throw innerException;
}
return response;
}
static void log(Logger logger, LogLevel level, String message) {
switch (level) {
case DEBUG:
System.out.println(message);
logger.debug(message);
case TRACE:
logger.trace(message);
case WARN:
logger.warn(message);
case ERROR:
logger.error(message);
case FATAL:
logger.error(message);
default:
logger.info(message);
}
}
}

第三步在controller层进行设置即可

 @GetMapping("/{id}")
@LogEntry(logCzlx = LogCzlxEnum.QUERY, inputKey = "'TbgdRef:id='+#id", logContent = "'根据收集设置主键 id 获取一条收集设置'+ #id")
@ApiOperation("根据主键获取一条收集设置表")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "主键", paramType = "path", dataTypeClass = String.class, required = true)})
public TbgdRef getSjsz(@PathVariable("id") String id) {
return sjszService.getSjszById(id);
}

Java中,切面通知(Aspect Notifications)是由AOP(面向切面编程)框架提供的一种机制,用于在特定的切点(Join Points)执行某些操作,比如日志记录、事务管理、权限检查等。

在Spring框架中,切面通知类型主要有以下五种:

Before:在目标方法执行之前进行通知。

After:在目标方法执行之后进行通知,无论方法是否执行成功。

After Returning:在目标方法成功执行后进行通知。

After Throwing:在目标方法抛出异常后进行通知。

Around:可以在目标方法调用前后执行自定义的行为。

本站无任何商业行为
个人在线分享 » springboot 项目中自定义注解,实现对日志的记录
E-->