直接上干货,不墨迹。。。
一、日志实体类 "SysLogEntity"
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_log")
@ApiModel(value="SysLogEntity", description="系统日志表")
public class SysLogEntity extends BaseMode {
private static final long serialVersionUID = 1329584865926666163L;
/**
* 主键id
*/
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 日志分类(1=登录日志;2=内部接口操作日志;3=对外接口操作日志)
*/
@ApiModelProperty(value = "日志分类(1=登录日志;2=内部接口操作日志;3=对外接口操作日志)")
private Integer category;
/**
* 用户id
*/
@ApiModelProperty(value="用户id")
private Long userId;
/**
* 登录账号
*/
@ApiModelProperty(value="登录账号")
private String loginName;
/**
* 用户姓名
*/
@ApiModelProperty(value="用户姓名")
private String fullName;
/**
* IP地址
*/
@ApiModelProperty(value="IP地址")
private String ipAddress;
/**
* 类名
*/
@ApiModelProperty(value="类名")
private String className;
/**
* 方法名
*/
@ApiModelProperty(value="方法名")
private String methodName;
/**
* 请求url
*/
@ApiModelProperty(value="请求url")
private String requestUri;
/**
* 中文模块名
*/
@ApiModelProperty(value="中文模块名")
private String moduleName;
/**
* 中文方法名
*/
@ApiModelProperty(value="中文方法名")
private String opName;
/**
* 结果编码
*/
@ApiModelProperty(value="结果编码")
private String resultCode;
/**
* 结果消息
*/
@ApiModelProperty(value="结果消息")
private String resultMsg;
/**
* 请求时间
*/
@ApiModelProperty(value="请求时间")
private Date requestTime;
/**
* 耗时
*/
@ApiModelProperty(value="耗时")
private Long execTime;
/**
* 用户代理
*/
@ApiModelProperty(value="用户代理")
private String userAgent;
}
二、日志注解类 "OpLog"。
/**
* 操作日志的控制
* 优先级高于配置文件中的相关配置
* 只有这里面没有配置的项目,才使用配置文件中的配置值
*
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OpLog {
/**
* 用在class上时为模块名称,
* 用在method上时为操作名称
*/
String name() default "";
/**
* 日志分类(1=登录日志;2=内部接口操作日志;3=对外接口操作日志)
*/
int type() default 2;
}
三、日志切面类 "LogAspect" 注意:使用切面时,要添加切面依赖。
<!-- 切面依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
@Aspect
@Component
public class LogAspect {
/**
* 统计请求的处理时间
*/
Date startTime = null;
Object[] params= null;
@Resource
private ISysLogService sysLogService;
@Resource
private SysUserService sysUserService;
/**
* 设置操作日志切入点
*/
@Pointcut("@annotation(com.jinmao.marketdev.common.logging.OpLog)")
public void logPoinCut() {
}
@Before("logPoinCut()")
public void doBefore(JoinPoint joinPoint) {
// 接收到请求,记录请求开始时间
startTime = new Date();
params = joinPoint.getArgs();
}
/**
* 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行
*
* @param joinPoint ProceedingJoinPoint
* @param obj Object
*/
@AfterReturning(value = "logPoinCut()", returning = "obj")
public void doAfterReturning(JoinPoint joinPoint, Object obj) {
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
if (request == null) {
return;
}
String userName = request.getHeader("userName");
SysLogEntity logEntity = new SysLogEntity();
if (StringUtils.isNotBlank(userName)) {
SysUser user = sysUserService.getUserByUserName(userName);
if (user != null) {
logEntity.setUserId(user.getId());
logEntity.setLoginName(user.getUserName());
logEntity.setFullName(user.getJmName());
}
}
logEntity.setIpAddress(getRequestIp(request));
try {
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
logEntity.setClassName(className);
// 获取操作
OpLog log = method.getAnnotation(OpLog.class);
logEntity.setCategory(log.type());
logEntity.setMethodName(method.getName());
logEntity.setOpName(log.name());
logEntity.setRequestUri(request.getRequestURI());
Result result = (Result) obj;
logEntity.setResultCode(result.getCode());
logEntity.setResultMsg(result.getMsg());
logEntity.setRequestTime(startTime);
logEntity.setExecTime(System.currentTimeMillis() - startTime.getTime());
// 登录时,取用户信息
if(logEntity.getCategory() == 1) {
String param1 = (String) params[0];
logEntity.setLoginName(param1);
if ("200".equals(logEntity.getResultCode())) {
SysUser user = sysUserService.getUserByUserName(userName);
if (user != null) {
logEntity.setUserId(user.getId());
logEntity.setLoginName(user.getUserName());
logEntity.setFullName(user.getJmName());
}
}
}
sysLogService.save(logEntity);
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}
public static String getRequestIp(HttpServletRequest request) {
String ip = request.getHeader("x-original-forwarded-for");
if (StringUtils.isEmpty(ip)) {
ip = request.getHeader("x-forwarded-for");
}
if (ip != null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
int idx = ip.indexOf(",");
if (idx != -1) {
ip = ip.substring(0, idx);
}
//有时候会带有端口,把端口去掉
idx = ip.indexOf(':');
if (idx > 0) {
ip = ip.substring(0, idx);
}
return ip;
}
ip = request.getHeader("X-Real-IP");
if (ip != null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
ip = request.getHeader("Proxy-Client-IP");
if (ip != null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
ip = request.getHeader("WL-Proxy-Client-IP");
if (ip != null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
ip = request.getHeader("HTTP_CLIENT_IP");
if (ip != null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
if (ip != null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
return request.getRemoteAddr();
}
}
四、在每一个功能接口处,加上@OpLog注解,这样就在页面操作的时候把操作日志记录了下来。一个日志保存功能呢就实现了。
注意:这只是操作页面相关功能的一个保存日志机制,具体系统开发可能不一样,请参考。
创作不易,请点赞!!!