当前位置:网站首页>自定义操作日志记录注解
自定义操作日志记录注解
2022-06-10 01:10:00 【加油豪豪】
1、注解
package com.netintech.common.log.annotation;
import com.netintech.common.log.enums.BusinessType;
import com.netintech.common.log.enums.OperatorType;
import java.lang.annotation.*;
/** * 自定义操作日志记录注解 * * @author admin * */
@Target({
ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/** * 模块 */
public String title() default "";
/** * 功能 */
public BusinessType businessType() default BusinessType.OTHER;
/** * 操作人类别 */
public OperatorType operatorType() default OperatorType.MANAGE;
/** * 是否保存请求的参数 */
public boolean isSaveRequestData() default true;
}
2、注解切面实现类
package com.netintech.common.log.aspect;
import java.lang.reflect.Method;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.text.UnicodeUtil;
import cn.hutool.core.util.IdUtil;
import com.netintech.api.system.constant.KafkaConstant;
import com.netintech.common.core.constant.Constants;
import com.netintech.common.kafka.service.KafkaUtil;
import com.netintech.common.security.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSON;
import com.netintech.common.core.constant.CacheConstants;
import com.netintech.common.core.utils.ServletUtils;
import com.netintech.common.core.utils.StringUtils;
import com.netintech.common.core.utils.ip.IpUtils;
import com.netintech.common.log.annotation.Log;
import com.netintech.common.log.enums.BusinessStatus;
import com.netintech.api.system.foundation.domain.SysOperLog;
/** * 操作日志记录处理 * * @author admin */
@Aspect
@Component
public class LogAspect {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
@Resource
private KafkaUtil kafkaUtil;
// 配置织入点
@Pointcut("@annotation(com.netintech.common.log.annotation.Log)")
public void logPointCut() {
}
/** * 处理完请求后执行 * * @param joinPoint 切点 */
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
handleLog(joinPoint, null, jsonResult);
}
/** * 拦截异常操作 * * @param joinPoint 切点 * @param e 异常 */
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e, null);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
try {
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
operLog.setOperId(IdUtil.simpleUUID());
operLog.setOperTime(System.currentTimeMillis());
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
operLog.setOperIp(ip);
// 返回参数
operLog.setJsonResult(JSON.toJSONString(jsonResult));
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
HttpServletRequest request = ServletUtils.getRequest();
String username = request.getHeader(CacheConstants.DETAILS_USERNAME);
username = UnicodeUtil.toString(username);
if (StringUtils.isNotBlank(username)) {
operLog.setOperName(username);
}
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog);
// 保存数据库
//asyncLogService.saveSysLog(operLog);
//保存到es
//AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
//发送到kafka
kafkaUtil.send(KafkaConstant.LOG_SAVE_ES_TOPIC, Constants.OBJECT_MAPPER.writeValueAsString(operLog), SecurityUtils.getUserId());
//kafkaTemplate.send(KafkaConstant.LOG_SAVE_ES_TOPIC, Constants.OBJECT_MAPPER.writeValueAsString(operLog));
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
/** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param log 日志 * @param operLog 操作日志 * @throws Exception */
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception {
// 设置action动作
operLog.setBusinessType(log.businessType().ordinal());
// 设置标题
operLog.setTitle(log.title());
// 设置操作人类别
operLog.setOperatorType(log.operatorType().ordinal());
// 是否需要保存request,参数和值
if (log.isSaveRequestData()) {
// 获取参数的信息,传入到数据库中。
setRequestValue(joinPoint, operLog);
}
}
/** * 获取请求的参数,放到log中 * * @param operLog 操作日志 * @throws Exception 异常 */
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception {
String requestMethod = operLog.getRequestMethod();
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
}
}
/** * 是否存在注解,如果存在就获取 */
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(Log.class);
}
return null;
}
/** * 参数拼装 */
private String argsArrayToString(Object[] paramsArray) {
String params = "";
if (paramsArray != null && paramsArray.length > 0) {
for (int i = 0; i < paramsArray.length; i++) {
if (!isFilterObject(paramsArray[i])) {
try {
Object jsonObj = JSON.toJSON(paramsArray[i]);
params += jsonObj.toString() + " ";
} catch (Exception e) {
}
}
}
}
return params.trim();
}
/** * 判断是否需要过滤的对象。 * * @param o 对象信息。 * @return 如果是需要过滤的对象,则返回true;否则返回false。 */
public boolean isFilterObject(final Object o) {
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
}
}
3、枚举类
package com.netintech.common.log.enums;
/** * 操作状态 * * @author admin * */
public enum BusinessStatus
{
/** * 成功 */
SUCCESS,
/** * 失败 */
FAIL,
}
4、异步处理实现类
package com.netintech.common.log.manager;
import com.netintech.common.core.utils.SpringUtils;
import com.netintech.common.core.utils.Threads;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** * 异步任务管理器 * * @author admin */
public class AsyncManager
{
/** * 操作延迟10毫秒 */
private final int OPERATE_DELAY_TIME = 10;
/** * 异步操作任务调度线程池 */
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/** * 单例模式 */
private AsyncManager()
{
}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me()
{
return me;
}
/** * 执行任务 * * @param task 任务 */
public void execute(TimerTask task)
{
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/** * 停止任务线程池 */
public void shutdown()
{
Threads.shutdownAndAwaitTermination(executor);
}
}
边栏推荐
- Domain Adaptation and Graph Neural Networks
- Dependent auto assembly
- 牛客网——华为题库(1~10)
- 别再重复造轮子了,推荐使用 Google Guava 开源工具类库,真心强大!
- Disorder of flinksql
- Think of GPL as a "virus"? Please stop defaming GPL
- Rhcsa day 7
- Luogu p1220 turn off street light problem solving section DP
- Sunyuchen et al. Acquired poloniex, the two wheel drive wave field ecology of the public chain exchange
- 图片批量下载 +图片马赛克:多张图片组成端午安康!
猜你喜欢

Don't build the wheel again. It is recommended to use Google guava open source tool class library. It is really powerful!

缓解修复Android Studio卡顿,Kotlin代码提示慢

【Multisim仿真】差分比例放大电路

Sunyuchen et al. Acquired poloniex, the two wheel drive wave field ecology of the public chain exchange
window. Open (URL) opens the download link for many times and is blocked by the browser. JS realizes circular access to multiple download links

Application scheme of residual pressure monitoring system in a high-rise residential building

分布式数据库下子查询和 Join 等复杂 SQL 如何实现?

MySQL - isolation level of transactions

Maui + MVVM + Siemens cross platform application practice

From the perspective of advanced automated testing, one article with 7 stages and 5000 words will give you a comprehensive understanding of automated testing
随机推荐
缓解修复Android Studio卡顿,Kotlin代码提示慢
Various utilization forms of map tile data and browsing display of tile data
亚洲首屈一指的Web3盛事“TOKEN2049新加坡”公布冠名赞助商
Flink CDC + Hudi 海量数据入湖在顺丰的实践
Solution to the problem of the greatest common divisor and the least common multiple of Luogu p1029
The IPO meeting of xinghuan science and Technology Innovation Board: the gross profit margin remains at a high level, with Tencent and other major shareholders
【ACL 2022】Hallucinated but Factual! Inspecting the Factuality of Hallucinations
My creation anniversary
A junior college programmer in hupiao, he worked out with liuzhenhong while taking 22K offers
梯度下降引发AI大牛们“激辩”,网友:每个人的答案都值得一看
视频汇聚平台EasyCVR级联EasyCVR出现通道频繁掉线是什么原因?
What is the difference between encryptors and database encryption products?
Host computer development -- how fast is MODBUS
【LeetCode】338. 比特位计数
漫谈测试覆盖率
Teaching Broad Reasoning Skills via Decomposition-Guided Contexts
Teaching Broad Reasoning Skills via Decomposition-Guided Contexts
Luogu p1220 turn off street light problem solving section DP
1265_FreeRTOS中向任务就绪链表增加任务的实现分析
Never far away, five programming languages that may be doomed to decline