Commit e9b7ccb8 authored by zengtianlai3's avatar zengtianlai3

增加操作日志

parent 40a7b230
package iot.sixiang.license.controller;
import com.alibaba.fastjson.JSONObject;
import iot.sixiang.license.log.BusinessType;
import iot.sixiang.license.log.MyLog;
import iot.sixiang.license.model.BaseResult;
import iot.sixiang.license.service.SysOperLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
@RestController
@RequestMapping("/iot_license/sys_oper_log")
public class SysOperLogController {
@Autowired
SysOperLogService sysOperLogService;
@GetMapping("get/test/{id}")
@MyLog(title = "get方式日志测试", optParam = "#{id},#{pageNo}", businessType = BusinessType.OTHER)
public BaseResult getTest(@PathVariable Long id, @RequestParam("pageNo") int pageNo) {
return BaseResult.success();
}
@PostMapping("post/test/{id}")
@MyLog(title = "post方式操作日志测试", optParam = "#{jsonObject}", businessType = BusinessType.OTHER)
public BaseResult postTest(@PathVariable Long id, @RequestBody JSONObject jsonObject) {
return BaseResult.success();
}
}
package iot.sixiang.license.device;
import iot.sixiang.license.consts.Consts;
import iot.sixiang.license.model.PageInfoModel;
import iot.sixiang.license.model.SessionContext;
import iot.sixiang.license.model.vo.DeviceVo;
......@@ -10,10 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
@Component
......@@ -103,24 +101,20 @@ public class DeviceManager {
return false;
}
public synchronized boolean removeSession(String appId, int offPort) {
if (sessionContexts.containsKey(appId)) {
public boolean changeSessionOffline(String channelId) {
SessionContext session = sessionContexts.get(appId);
if (session.getRemotePort() == offPort) {
sessionContexts.remove(appId);
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
targetSession.setStatus(Consts.DEVICE_STATE_OFFLINE);
targetSession.setOnline(new Date());
return true;
} else {
log.warn("client disconnect has a warning!");
return false;
}
} else {
log.warn("client disconnect,don't found the session");
return false;
}
return false;
}
}
......@@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
import java.util.Date;
@Component
@ChannelHandler.Sharable
......@@ -180,6 +181,8 @@ public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
session.setAppId(appId);
session.setChannelId(channelId);
session.setClientChannel(channel);
session.setStatus(Consts.DEVICE_STATE_ONLINE);
session.setOnline(new Date());
DeviceManager deviceManager = SpringUtil.getBean(DeviceManager.class);
deviceManager.putSession(appId, session);
......
package iot.sixiang.license.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 操作日志记录
* </p>
*
* @author lai
* @since 2022-06-13
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SysOperLog implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 日志主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 模块标题
*/
private String title;
/**
* 参数
*/
private String optParam;
/**
* 业务类型(0其它 1新增 2修改 3删除)
*/
private Integer businessType;
/**
* 方法名称
*/
private String method;
/**
* 操作状态(0正常 1异常)
*/
private Integer status;
/**
* 错误消息
*/
private String errorMsg;
/**
* 操作时间
*/
private Date operTime;
}
......@@ -30,15 +30,16 @@ public class DeviceClientInactiveEventHandler {
if (session == null) {
log.debug("device client inactive undo ..." );
return;
}else{
} else {
String appId = session.getAppId();
boolean result = deviceManager.removeSessionByChannelId(channelId);
// boolean result = deviceManager.removeSessionByChannelId(channelId);
boolean result = deviceManager.changeSessionOffline(channelId);
if (result) {
// TODO device client 离线需要强制中断该设备对应的forward client
ForwardClientBeForcedOfflineEvent forwardClientBeForcedOfflineEvent = new ForwardClientBeForcedOfflineEvent();
forwardClientBeForcedOfflineEvent.setAppId(appId);
eventPublisher.publishEvent(forwardClientBeForcedOfflineEvent);
log.debug("device client inactive success ..." );
log.debug("device client inactive success ...");
}
}
......
......@@ -67,5 +67,10 @@ public class ForwardManager {
return false;
}
public void getSession(){
}
}
\ No newline at end of file
package iot.sixiang.license.log;
public enum BusinessType {
/**
* 其它
*/
OTHER,
/**
* 新增
*/
INSERT,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
}
package iot.sixiang.license.log;
import com.alibaba.fastjson.JSONObject;
import iot.sixiang.license.entity.SysOperLog;
import iot.sixiang.license.service.SysOperLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
@Slf4j
public class LogAspect {
@Autowired
private SysOperLogService sysOperLogService;
// 配置织入点
@Pointcut("@annotation(iot.sixiang.license.log.MyLog)")
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 {
// 获得注解
MyLog controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
SysOperLog operLog = new SysOperLog();
operLog.setStatus(0);
operLog.setOperTime(new Date());
if (e != null) {
operLog.setStatus(1);
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog);
// 保存数据库
sysOperLogService.addOperlog(operLog.getTitle(), operLog.getBusinessType(), operLog.getMethod(), operLog.getStatus(), operLog.getOptParam(), operLog.getErrorMsg(), operLog.getOperTime());
} catch (Exception exp) {
log.error("==前置通知异常==");
log.error("日志异常信息 {}", exp);
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param myLog 日志
* @param operLog 操作日志
* @throws Exception
*/
public void getControllerMethodDescription(JoinPoint joinPoint, MyLog myLog, SysOperLog operLog) {
// 设置action动作
operLog.setBusinessType(myLog.businessType().ordinal());
// 设置标题
operLog.setTitle(myLog.title());
String optParam = getAnnotationValue(joinPoint, myLog.optParam());
operLog.setOptParam(optParam);
}
/**
* 是否存在注解,如果存在就获取
*/
private MyLog getAnnotationLog(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(MyLog.class);
}
return null;
}
public String getAnnotationValue(JoinPoint joinPoint, String name) {
String paramName = name;
// 获取方法中所有的参数
Map<String, Object> params = getParams(joinPoint);
// 参数是否是动态的:#{paramName}
if (paramName.matches("^#\\{\\D*\\}")) {
// 获取参数名
paramName = paramName.replace("#{", "").replace("}", "");
// 是否是复杂的参数类型:对象.参数名
if (paramName.contains(".")) {
String[] split = paramName.split("\\.");
// 获取方法中对象的内容
Object object = getValue(params, split[0]);
// 转换为JsonObject
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(object);
// 获取值
Object o = jsonObject.get(split[1]);
return String.valueOf(o);
} else {// 简单的动态参数直接返回
StringBuilder str = new StringBuilder();
String[] paraNames = paramName.split(",");
for (int i = 0; i < paraNames.length; i++) {
String paraName = paraNames[i];
String val = String.valueOf(getValue(params, paraName));
str.append(paraName + "=" + val + ",");
}
if (str.toString().endsWith(",")) {
String substring = str.substring(0, str.length() - 1);
return substring;
} else {
return str.toString();
}
}
}
// 非动态参数直接返回
return name;
}
public Map<String, Object> getParams(JoinPoint joinPoint) {
Map<String, Object> params = new HashMap<>(8);
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] names = signature.getParameterNames();
for (int i = 0; i < args.length; i++) {
params.put(names[i], args[i]);
}
return params;
}
public Object getValue(Map<String, Object> map, String paramName) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals(paramName)) {
return entry.getValue();
}
}
return null;
}
}
\ No newline at end of file
package iot.sixiang.license.log;
import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyLog {
String title() default ""; // 模块
String optParam() default ""; // 参数
BusinessType businessType() default BusinessType.OTHER; // 功能
}
\ No newline at end of file
package iot.sixiang.license.mapper;
import iot.sixiang.license.entity.SysOperLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.time.LocalDateTime;
import java.util.Date;
/**
* <p>
* 操作日志记录 Mapper 接口
* </p>
*
* @author lai
* @since 2022-06-13
*/
public interface SysOperLogMapper extends BaseMapper<SysOperLog> {
boolean addOperlog(String title, Integer businessType, String method, Integer status, String optParam, String errorMsg, Date operTime);
}
......@@ -3,6 +3,8 @@ package iot.sixiang.license.model;
import io.netty.channel.socket.SocketChannel;
import lombok.Data;
import java.util.Date;
@Data
public class SessionContext {
......@@ -11,7 +13,9 @@ public class SessionContext {
private String appId;//设备序列号
private String appKey;//设备key/授权ID
private String token;//连接标识
private int device_status;//0 offline,1 online
private int status;//0 offline,1 online
private Date online;//上线时间
private Date offline;//下线时间
private String channelId;
private SocketChannel clientChannel;
......
package iot.sixiang.license.service;
import iot.sixiang.license.entity.SysOperLog;
import com.baomidou.mybatisplus.extension.service.IService;
import java.time.LocalDateTime;
import java.util.Date;
/**
* <p>
* 操作日志记录 服务类
* </p>
*
* @author lai
* @since 2022-06-13
*/
public interface SysOperLogService extends IService<SysOperLog> {
boolean addOperlog(String title, Integer businessType, String method, Integer status, String optParam, String errorMsg, Date operTime);
}
package iot.sixiang.license.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import iot.sixiang.license.entity.Server;
import iot.sixiang.license.entity.SysOperLog;
import iot.sixiang.license.mapper.ServerMapper;
import iot.sixiang.license.mapper.SysOperLogMapper;
import iot.sixiang.license.service.SysOperLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.license.util.JsonUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
/**
* <p>
* 操作日志记录 服务实现类
* </p>
*
* @author lai
* @since 2022-06-13
*/
@Service
public class SysOperLogServiceImpl extends ServiceImpl<SysOperLogMapper, SysOperLog> implements SysOperLogService {
@Resource
SysOperLogMapper sysOperLogMapper;
@Override
public boolean addOperlog(String title, Integer businessType, String method, Integer status, String optParam, String errorMsg, Date operTime) {
return sysOperLogMapper.addOperlog(title, businessType, method, status, optParam, errorMsg, operTime);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="iot.sixiang.license.mapper.SysOperLogMapper">
<insert id="addOperlog" parameterType="iot.sixiang.license.entity.SysOperLog">
insert into sys_oper_log(title, business_type, method, status, opt_param, error_msg, oper_time) values (#{title},#{businessType},#{method},#{status},#{optParam},#{errorMsg},#{operTime})
</insert>
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment