xieb
2023-10-17 c7adeb1f4c48dfea357e824d69496fcaf1768d52
新增用户操作日志
3 files modified
6 files added
293 ■■■■■ changed files
pom.xml 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/CloudApiSampleApplication.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/log/aspect/LogAspect.java 145 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/log/aspect/SysLogAnnotation.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/log/dao/ISysLogMapper.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/log/model/entity/SysLogEntity.java 57 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/log/service/ISysLogService.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/log/service/impl/SysLogServiceImpl.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/wayline/controller/WaylineJobController.java 7 ●●●●● patch | view | raw | blame | history
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>
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)
src/main/java/com/dji/sample/log/aspect/LogAspect.java
New file
@@ -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;
    }
}
src/main/java/com/dji/sample/log/aspect/SysLogAnnotation.java
New file
@@ -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 "";  // 操作说明
}
src/main/java/com/dji/sample/log/dao/ISysLogMapper.java
New file
@@ -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> {
}
src/main/java/com/dji/sample/log/model/entity/SysLogEntity.java
New file
@@ -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;//描述
}
src/main/java/com/dji/sample/log/service/ISysLogService.java
New file
@@ -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);
}
src/main/java/com/dji/sample/log/service/impl/SysLogServiceImpl.java
New file
@@ -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);
    }
}
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) {