12 changed files with 305 additions and 0 deletions
@ -0,0 +1,16 @@ |
|||||
|
package com.project.operation.annotation; |
||||
|
|
||||
|
import java.lang.annotation.*; |
||||
|
|
||||
|
/** |
||||
|
* 自定义操作日志注解 |
||||
|
*/ |
||||
|
@Target({ElementType.METHOD}) |
||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||
|
@Documented |
||||
|
public @interface OperationLog { |
||||
|
//操作模块
|
||||
|
String module() default ""; |
||||
|
//操作描述
|
||||
|
String description() default ""; |
||||
|
} |
||||
@ -0,0 +1,115 @@ |
|||||
|
package com.project.operation.aop; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
||||
|
import com.project.base.domain.result.Result; |
||||
|
import com.project.ding.domain.dto.LoginDTO; |
||||
|
import com.project.ding.utils.JwtUtils; |
||||
|
import com.project.operation.annotation.OperationLog; |
||||
|
import com.project.operation.application.impl.OperationLogApplicationService; |
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
import jakarta.servlet.http.HttpServletRequest; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||
|
import org.aspectj.lang.annotation.AfterReturning; |
||||
|
import org.aspectj.lang.annotation.Around; |
||||
|
import org.aspectj.lang.annotation.Aspect; |
||||
|
import org.aspectj.lang.annotation.Pointcut; |
||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
import org.springframework.web.context.request.RequestContextHolder; |
||||
|
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
|
|
||||
|
import java.lang.reflect.Method; |
||||
|
|
||||
|
/** |
||||
|
* 操作日志AOP切面 |
||||
|
*/ |
||||
|
@Slf4j |
||||
|
@Aspect |
||||
|
@Component |
||||
|
@RequiredArgsConstructor |
||||
|
public class OperationLogAspect { |
||||
|
|
||||
|
@Autowired |
||||
|
private JwtUtils jwtUtils; |
||||
|
@Autowired |
||||
|
private OperationLogApplicationService operationLogApplicationService; |
||||
|
|
||||
|
private final ThreadLocal<OperationLogDTO> operationLogDTOThreadLocal = new ThreadLocal<>(); |
||||
|
|
||||
|
//定义切点,拦截所有添加@OperationLog注解的方法
|
||||
|
@Pointcut("@annotation(com.project.operation.annotation.OperationLog)") |
||||
|
public void pointcutOperationLog() {} |
||||
|
|
||||
|
//环绕通知,在方法执行前后拦截,收集日志
|
||||
|
@Around("pointcutOperationLog()") |
||||
|
public Object around(ProceedingJoinPoint joinPoint) throws Throwable { |
||||
|
//获取开始时间
|
||||
|
long startTime = System.currentTimeMillis(); |
||||
|
|
||||
|
OperationLogDTO operationLogDTO = new OperationLogDTO(); |
||||
|
//获取客户端IP和操作用户
|
||||
|
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
||||
|
if (requestAttributes != null) { |
||||
|
HttpServletRequest request = requestAttributes.getRequest(); |
||||
|
operationLogDTO.setClientIp(request.getRemoteAddr()); |
||||
|
|
||||
|
String header = request.getHeader("Authorization"); |
||||
|
if (StringUtils.isNotBlank(header) && header.startsWith("Bearer ")) { |
||||
|
String token = header.substring(7); |
||||
|
String userId = jwtUtils.parseToken(token).getSubject(); |
||||
|
operationLogDTO.setCreatorId(Long.parseLong(userId)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//获取方法信息
|
||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); |
||||
|
Method method = signature.getMethod(); |
||||
|
// 方法全路径:包名+类名+方法名
|
||||
|
operationLogDTO.setMethod(method.getDeclaringClass().getName() + "." + method.getName()); |
||||
|
|
||||
|
//获取操作信息
|
||||
|
OperationLog annotation = method.getAnnotation(OperationLog.class); |
||||
|
operationLogDTO.setModule(annotation.module()); |
||||
|
operationLogDTO.setDescription(annotation.description()); |
||||
|
|
||||
|
|
||||
|
Object businessResult; |
||||
|
try { |
||||
|
operationLogDTOThreadLocal.set(operationLogDTO); |
||||
|
businessResult = joinPoint.proceed(); |
||||
|
operationLogDTO.setResult(0); |
||||
|
}catch (Exception e){ |
||||
|
operationLogDTO.setResult(1); |
||||
|
operationLogDTO.setException(e.getMessage()); |
||||
|
throw e; |
||||
|
}finally { |
||||
|
operationLogDTO.setCostTime(System.currentTimeMillis() - startTime); |
||||
|
//保存日志
|
||||
|
operationLogApplicationService.saveOperationLog(operationLogDTO); |
||||
|
} |
||||
|
|
||||
|
return businessResult; |
||||
|
} |
||||
|
|
||||
|
@AfterReturning(returning = "result",pointcut = "pointcutOperationLog()") |
||||
|
public void afterReturning(Object result) throws Throwable { |
||||
|
OperationLogDTO operationLogDTO = operationLogDTOThreadLocal.get(); |
||||
|
if (operationLogDTO == null) { |
||||
|
return; // 无上下文,直接返回
|
||||
|
} |
||||
|
try { |
||||
|
//获取当前登陆用户
|
||||
|
if(operationLogDTO.getMethod().contains("getToken") && result instanceof Result){ |
||||
|
LoginDTO data = ((Result<LoginDTO>) result).getData(); |
||||
|
String userId = jwtUtils.parseToken(data.getToken()).getSubject(); |
||||
|
operationLogDTO.setCreatorId(Long.parseLong(userId)); |
||||
|
} |
||||
|
}finally { |
||||
|
operationLogDTOThreadLocal.remove(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
package com.project.operation.application; |
||||
|
|
||||
|
import com.project.operation.application.impl.OperationLogApplicationService; |
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
import com.project.operation.domain.service.OperationLogBaseService; |
||||
|
import com.project.operation.domain.service.SaveOperationLogDomainService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
@Service |
||||
|
public class OperationLogApplicationServiceImpl implements OperationLogApplicationService { |
||||
|
|
||||
|
@Autowired |
||||
|
private SaveOperationLogDomainService saveOperationLogDomainService; |
||||
|
|
||||
|
/** |
||||
|
* 保存日志 |
||||
|
*/ |
||||
|
@Override |
||||
|
public void saveOperationLog(OperationLogDTO operationLogDTO) { |
||||
|
saveOperationLogDomainService.saveOperationLog(operationLogDTO); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
package com.project.operation.application.impl; |
||||
|
|
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
|
||||
|
public interface OperationLogApplicationService { |
||||
|
/** |
||||
|
* 保存操作日志 |
||||
|
*/ |
||||
|
void saveOperationLog(OperationLogDTO operationLogDTO); |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
package com.project.operation.domain.dto; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||
|
import com.baomidou.mybatisplus.annotation.TableField; |
||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||
|
import com.project.base.domain.dto.BaseDTO; |
||||
|
import jakarta.persistence.Column; |
||||
|
import jakarta.persistence.Id; |
||||
|
import lombok.Data; |
||||
|
import org.hibernate.annotations.Comment; |
||||
|
|
||||
|
@Data |
||||
|
public class OperationLogDTO extends BaseDTO { |
||||
|
private Long id; |
||||
|
|
||||
|
private String module; |
||||
|
|
||||
|
private String description; |
||||
|
|
||||
|
private Integer result; |
||||
|
|
||||
|
private String method; |
||||
|
|
||||
|
private String exception; |
||||
|
|
||||
|
private Long costTime; |
||||
|
|
||||
|
private String clientIp; |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
package com.project.operation.domain.entity; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||
|
import com.baomidou.mybatisplus.annotation.TableField; |
||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||
|
import com.project.base.domain.entity.BaseEntity; |
||||
|
import jakarta.persistence.*; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import org.hibernate.annotations.Comment; |
||||
|
|
||||
|
@Data |
||||
|
@Table(name = "evaluator_operation_log") |
||||
|
@Entity |
||||
|
@TableName(value = "evaluator_operation_log") |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
public class OperationLogEntity extends BaseEntity { |
||||
|
@TableId(value = "id" , type = IdType.ASSIGN_ID) |
||||
|
@Id |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "module", columnDefinition = "varchar(255) comment '操作模块'") |
||||
|
private String module; |
||||
|
|
||||
|
@Column(name = "description" , columnDefinition="varchar(255) comment '操作描述'") |
||||
|
private String description; |
||||
|
|
||||
|
/** 操作结果 */ |
||||
|
@Column(name = "result") |
||||
|
@Comment("操作结果,0-成功, 1-失败") |
||||
|
private Integer result; |
||||
|
|
||||
|
@Column(name = "method", columnDefinition="varchar(255) comment '操作方法路径'") |
||||
|
private String method; |
||||
|
|
||||
|
@Column(name = "exception", columnDefinition="varchar(255) comment '异常信息(失败时记录)'") |
||||
|
private String exception; |
||||
|
|
||||
|
/** 操作耗时(毫秒) */ |
||||
|
@Column(name = "cost_time") |
||||
|
@Comment("操作耗时(毫秒)") |
||||
|
@TableField("cost_time") |
||||
|
private Long costTime; |
||||
|
|
||||
|
@Column(name = "client_ip", columnDefinition="varchar(100) comment '客户端IP'") |
||||
|
@TableField("client_ip") |
||||
|
private String clientIp; |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.project.operation.domain.service; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
import com.project.operation.domain.entity.OperationLogEntity; |
||||
|
|
||||
|
public interface OperationLogBaseService extends IService<OperationLogEntity> { |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
package com.project.operation.domain.service; |
||||
|
|
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
|
||||
|
public interface SaveOperationLogDomainService { |
||||
|
/** |
||||
|
* 保存操作日志 |
||||
|
*/ |
||||
|
void saveOperationLog(OperationLogDTO operationLogDTO); |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
package com.project.operation.domain.service.impl; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
import com.project.operation.domain.entity.OperationLogEntity; |
||||
|
import com.project.operation.domain.service.OperationLogBaseService; |
||||
|
import com.project.operation.mapper.OperationLogMapper; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
@Service |
||||
|
public class OperationLogBaseServiceImpl extends ServiceImpl<OperationLogMapper, OperationLogEntity> implements OperationLogBaseService { |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
package com.project.operation.domain.service.impl; |
||||
|
|
||||
|
import com.project.operation.domain.dto.OperationLogDTO; |
||||
|
import com.project.operation.domain.entity.OperationLogEntity; |
||||
|
import com.project.operation.domain.service.OperationLogBaseService; |
||||
|
import com.project.operation.domain.service.SaveOperationLogDomainService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
@Service |
||||
|
public class SaveOperationLogDomainServiceImpl implements SaveOperationLogDomainService { |
||||
|
|
||||
|
@Autowired |
||||
|
private OperationLogBaseService operationLogBaseService; |
||||
|
|
||||
|
@Override |
||||
|
public void saveOperationLog(OperationLogDTO operationLogDTO) { |
||||
|
OperationLogEntity entity = operationLogDTO.toEntity(OperationLogEntity::new); |
||||
|
operationLogBaseService.save(entity); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
package com.project.operation.mapper; |
||||
|
|
||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
|
import com.project.operation.domain.entity.OperationLogEntity; |
||||
|
import org.apache.ibatis.annotations.Mapper; |
||||
|
|
||||
|
@Mapper |
||||
|
public interface OperationLogMapper extends BaseMapper<OperationLogEntity> { |
||||
|
} |
||||
Loading…
Reference in new issue