From c7adeb1f4c48dfea357e824d69496fcaf1768d52 Mon Sep 17 00:00:00 2001
From: xieb <vip_xiaobin810@163.com>
Date: Tue, 17 Oct 2023 17:39:52 +0800
Subject: [PATCH] 新增用户操作日志
---
src/main/java/com/dji/sample/log/service/ISysLogService.java | 14 ++
src/main/java/com/dji/sample/log/service/impl/SysLogServiceImpl.java | 26 +++++
src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java | 7 +
src/main/java/com/dji/sample/log/dao/ISysLogMapper.java | 13 ++
src/main/java/com/dji/sample/log/aspect/LogAspect.java | 145 +++++++++++++++++++++++++++++
src/main/java/com/dji/sample/log/aspect/SysLogAnnotation.java | 21 ++++
src/main/java/com/dji/sample/log/model/entity/SysLogEntity.java | 57 +++++++++++
src/main/java/com/dji/sample/CloudApiSampleApplication.java | 3
pom.xml | 7 +
9 files changed, 293 insertions(+), 0 deletions(-)
diff --git a/pom.xml b/pom.xml
index 070d3ea..c1e34d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -185,6 +185,13 @@
<version>1.2.33</version>
</dependency>
+
+ <!-- aop依赖 -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-aop</artifactId>
+ </dependency>
+
</dependencies>
<build>
diff --git a/src/main/java/com/dji/sample/CloudApiSampleApplication.java b/src/main/java/com/dji/sample/CloudApiSampleApplication.java
index 6eb857b..5a667dc 100644
--- a/src/main/java/com/dji/sample/CloudApiSampleApplication.java
+++ b/src/main/java/com/dji/sample/CloudApiSampleApplication.java
@@ -5,6 +5,8 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
@@ -12,6 +14,7 @@
import java.util.TimeZone;
@MapperScan("com.dji.sample.*.dao")
+@EnableAspectJAutoProxy(proxyTargetClass = true)
@SpringBootApplication
@EnableScheduling
//@EnableConfigurationProperties(OssConfiguration.class)
diff --git a/src/main/java/com/dji/sample/log/aspect/LogAspect.java b/src/main/java/com/dji/sample/log/aspect/LogAspect.java
new file mode 100644
index 0000000..b88d050
--- /dev/null
+++ b/src/main/java/com/dji/sample/log/aspect/LogAspect.java
@@ -0,0 +1,145 @@
+package com.dji.sample.log.aspect;
+
+import com.alibaba.druid.support.json.JSONUtils;
+import com.alibaba.fastjson.JSON;
+import com.dji.sample.common.model.CustomClaim;
+import com.dji.sample.common.model.ResponseResult;
+import com.dji.sample.log.model.entity.SysLogEntity;
+import com.dji.sample.log.service.ISysLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+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.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
+
+/**
+ * @PROJECT_NAME: iot_drone_api
+ * @DESCRIPTION: 操作日志切面处理类
+ * @USER: aix
+ * @DATE: 2023/10/17 16:02
+ */
+
+@Aspect
+@Component
+@Slf4j
+public class LogAspect {
+
+ @Autowired
+ private ISysLogService sysLogService;
+
+ /**
+ * 设置操作日志切入点 在注解的位置切入代码
+ */
+ @Pointcut("@annotation(com.dji.sample.log.aspect.SysLogAnnotation)")
+ public void operLogPoinCut() { }
+
+ @AfterReturning(returning = "result", value = "operLogPoinCut()")
+ public void saveOperLog(JoinPoint joinPoint, ResponseResult result) {
+
+ // 获取RequestAttributes
+ RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
+ // 从获取RequestAttributes中获取HttpServletRequest的信息
+ HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
+ try {
+
+ SysLogEntity sysLog = new SysLogEntity();
+
+ // 从切面织入点处通过反射机制获取织入点处的方法
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ //获取切入点所在的方法
+ Method method = signature.getMethod();
+ //获取操作
+ SysLogAnnotation annotation = method.getAnnotation(SysLogAnnotation.class);
+ if (annotation != null) {
+ sysLog.setModel(annotation.operModul());
+ sysLog.setType(annotation.operType());
+ sysLog.setDescription(annotation.operDesc());
+ }
+
+ // 获取请求的类名
+ String className = joinPoint.getTarget().getClass().getName();
+ // 获取请求的方法名
+ String methodName = method.getName();
+ methodName = className + "." + methodName;
+ sysLog.setMethod(methodName); // 类名.请求方法
+
+ //操作用户
+ CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
+ sysLog.setUsername(customClaim.getUsername());
+
+ String ipAddress = request.getHeader("X-Forwarded-For");
+ if (ipAddress == null) {
+ ipAddress = request.getRemoteAddr();
+ }
+ sysLog.setIp(ipAddress); //操作IP
+ sysLog.setUrl(request.getRequestURI()); // 请求URI
+
+ // 方法请求的参数
+ Map<String, String> rtnMap = converMap(request.getParameterMap());
+ // 将参数所在的数组转换成json
+ String params = JSONUtils.toJSONString(rtnMap);
+ //获取json的请求参数
+ if (rtnMap == null || rtnMap.size() == 0) {
+ params = getJsonStrByRequest(request);
+ }
+ sysLog.setParams(params); // 请求参数
+
+ sysLog.setResult(JSON.toJSONString(result));
+
+ sysLogService.saveSysLog(sysLog);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("日志记录异常,请检查返回值是否统一");
+ }
+ }
+
+ /**
+ * 转换request 请求参数
+ *
+ * @param paramMap request获取的参数数组
+ */
+ public Map<String, String> converMap(Map<String, String[]> paramMap) {
+ Map<String, String> rtnMap = new HashMap<>();
+ for (String key : paramMap.keySet()) {
+ rtnMap.put(key, paramMap.get(key)[0]);
+ }
+ return rtnMap;
+ }
+
+ /**
+ * 获取json格式 请求参数
+ */
+ public String getJsonStrByRequest(HttpServletRequest request) {
+ String param = null;
+ try {
+ BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
+ StringBuilder responseStrBuilder = new StringBuilder();
+ String inputStr;
+ while ((inputStr = streamReader.readLine()) != null) {
+ responseStrBuilder.append(inputStr);
+ }
+
+ param = JSONUtils.toJSONString(responseStrBuilder);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return param;
+ }
+
+}
diff --git a/src/main/java/com/dji/sample/log/aspect/SysLogAnnotation.java b/src/main/java/com/dji/sample/log/aspect/SysLogAnnotation.java
new file mode 100644
index 0000000..6e4ecca
--- /dev/null
+++ b/src/main/java/com/dji/sample/log/aspect/SysLogAnnotation.java
@@ -0,0 +1,21 @@
+package com.dji.sample.log.aspect;
+
+import java.lang.annotation.*;
+
+/**
+ * @PROJECT_NAME: iot_drone_api
+ * @DESCRIPTION: 自定义操作日志注解
+ * @USER: aix
+ * @DATE: 2023/10/17 16:08
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SysLogAnnotation {
+
+ String operModul() default ""; // 操作模块
+
+ String operType() default ""; // 操作类型
+
+ String operDesc() default ""; // 操作说明
+}
diff --git a/src/main/java/com/dji/sample/log/dao/ISysLogMapper.java b/src/main/java/com/dji/sample/log/dao/ISysLogMapper.java
new file mode 100644
index 0000000..3e0e883
--- /dev/null
+++ b/src/main/java/com/dji/sample/log/dao/ISysLogMapper.java
@@ -0,0 +1,13 @@
+package com.dji.sample.log.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dji.sample.log.model.entity.SysLogEntity;
+
+/**
+ * @PROJECT_NAME: iot_drone_api
+ * @DESCRIPTION: 日志dao
+ * @USER: aix
+ * @DATE: 2023/10/17 15:58
+ */
+public interface ISysLogMapper extends BaseMapper<SysLogEntity> {
+}
diff --git a/src/main/java/com/dji/sample/log/model/entity/SysLogEntity.java b/src/main/java/com/dji/sample/log/model/entity/SysLogEntity.java
new file mode 100644
index 0000000..03b4fca
--- /dev/null
+++ b/src/main/java/com/dji/sample/log/model/entity/SysLogEntity.java
@@ -0,0 +1,57 @@
+package com.dji.sample.log.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @PROJECT_NAME: iot_drone_api
+ * @DESCRIPTION: 日志实体类
+ * @USER: aix
+ * @DATE: 2023/10/17 15:42
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "sys_log")
+public class SysLogEntity implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @TableField(value = "username")
+ private String username;
+
+ @TableField(value = "method")
+ private String method; //方法名
+
+ @TableField(value = "params")
+ private String params; //参数
+
+ @TableField(value = "ip")
+ private String ip; //ip地址
+
+ @TableField(value = "url")
+ private String url; //请求url
+
+ @TableField(value = "type")
+ private String type; //操作类型 :新增、删除等等
+
+ @TableField(value = "model")
+ private String model; //模块
+
+ @TableField(value = "create_time", fill = FieldFill.INSERT)
+ private Long createTime;
+
+ @TableField(value = "result")
+ private String result; //操作结果
+
+ @TableField(value = "description")
+ private String description;//描述
+
+}
diff --git a/src/main/java/com/dji/sample/log/service/ISysLogService.java b/src/main/java/com/dji/sample/log/service/ISysLogService.java
new file mode 100644
index 0000000..e2712c2
--- /dev/null
+++ b/src/main/java/com/dji/sample/log/service/ISysLogService.java
@@ -0,0 +1,14 @@
+package com.dji.sample.log.service;
+
+import com.dji.sample.log.model.entity.SysLogEntity;
+
+/**
+ * @PROJECT_NAME: iot_drone_api
+ * @DESCRIPTION: 保存用户日志接口
+ * @USER: aix
+ * @DATE: 2023/10/17 15:56
+ */
+public interface ISysLogService {
+
+ void saveSysLog(SysLogEntity sysLog);
+}
diff --git a/src/main/java/com/dji/sample/log/service/impl/SysLogServiceImpl.java b/src/main/java/com/dji/sample/log/service/impl/SysLogServiceImpl.java
new file mode 100644
index 0000000..35ab04f
--- /dev/null
+++ b/src/main/java/com/dji/sample/log/service/impl/SysLogServiceImpl.java
@@ -0,0 +1,26 @@
+package com.dji.sample.log.service.impl;
+
+import com.dji.sample.log.dao.ISysLogMapper;
+import com.dji.sample.log.model.entity.SysLogEntity;
+import com.dji.sample.log.service.ISysLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @PROJECT_NAME: iot_drone_api
+ * @DESCRIPTION:
+ * @USER: aix
+ * @DATE: 2023/10/17 15:59
+ */
+@Service
+public class SysLogServiceImpl implements ISysLogService {
+
+ @Autowired
+ private ISysLogMapper mapper;
+
+ @Override
+ public void saveSysLog(SysLogEntity sysLog) {
+ mapper.insert(sysLog);
+ }
+
+}
diff --git a/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java b/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
index ef9ef82..788dee3 100644
--- a/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
+++ b/src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java
@@ -3,6 +3,7 @@
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
+import com.dji.sample.log.aspect.SysLogAnnotation;
import com.dji.sample.wayline.model.dto.WaylineJobDTO;
import com.dji.sample.wayline.model.param.CreateJobParam;
import com.dji.sample.wayline.model.param.UpdateJobParam;
@@ -39,6 +40,7 @@
* @throws SQLException
*/
@PostMapping("/{workspace_id}/flight-tasks")
+ @SysLogAnnotation(operModul = "计划库", operType = "新增", operDesc = "创建计划")
public ResponseResult createJob(HttpServletRequest request, @Valid @RequestBody CreateJobParam param,
@PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
@@ -57,6 +59,7 @@
* @throws SQLException
*/
@PostMapping("/{workspace_id}/flight-tasks-condition")
+ @SysLogAnnotation(operModul = "计划库", operType = "新增", operDesc = "创建航路任务(重复定时和连续执行)")
public ResponseResult createJobCondition(HttpServletRequest request, @Valid @RequestBody CreateJobParam param,
@PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
@@ -73,6 +76,7 @@
* @return
*/
@GetMapping("/{workspace_id}/jobs")
+ @SysLogAnnotation(operModul = "计划库", operType = "查询", operDesc = "分页查询")
public ResponseResult<PaginationData<WaylineJobDTO>> getJobs(@RequestParam(defaultValue = "1") Long page,
@RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
@PathVariable(name = "workspace_id") String workspaceId, WaylineJobQueryParam waylineJobQueryParam){
@@ -88,6 +92,7 @@
* @throws SQLException
*/
@DeleteMapping("/{workspace_id}/jobs")
+ @SysLogAnnotation(operModul = "计划库", operType = "删除", operDesc = "发送命令取消作业")
public ResponseResult publishCancelJob(@RequestParam(name = "job_id") Set<String> jobIds,
@PathVariable(name = "workspace_id") String workspaceId) throws SQLException {
waylineJobService.cancelFlightTask(workspaceId, jobIds);
@@ -101,6 +106,7 @@
* @return
*/
@PostMapping("/{workspace_id}/jobs/{job_id}/media-highest")
+ @SysLogAnnotation(operModul = "计划库", operType = "修改", operDesc = "将此作业的媒体文件设置为立即上传")
public ResponseResult uploadMediaHighestPriority(@PathVariable(name = "workspace_id") String workspaceId,
@PathVariable(name = "job_id") String jobId) {
waylineJobService.uploadMediaHighestPriority(workspaceId, jobId);
@@ -108,6 +114,7 @@
}
@PutMapping("/{workspace_id}/jobs/{job_id}")
+ @SysLogAnnotation(operModul = "计划库", operType = "修改", operDesc = "修改")
public ResponseResult updateJobStatus(@PathVariable(name = "workspace_id") String workspaceId,
@PathVariable(name = "job_id") String jobId,
@Valid @RequestBody UpdateJobParam param) {
--
Gitblit v1.9.3