SpringBoot利用AOP實現(xiàn)一個日志管理詳解
1. 需求
目前有這么個問題,有兩個系統(tǒng)CSP和OMS,這倆系統(tǒng)共用的是同一套日志操作:Log;目前想?yún)^(qū)分下這倆系統(tǒng)的日志操作,那沒辦法了,只能重寫一份Log的日志操作;
你也可以參照若依框架的日志系統(tǒng)實現(xiàn)。
2. 新建一張日志表
sys_oper_csp_log
/* Navicat Premium Data Transfer Source Server : jp-csc-admin Source Server Type : MySQL Source Server Version : 50728 Source Host : rm-uf6miy84gu8u433x9.mysql.rds.aliyuncs.com:3306 Source Schema : jp_oms Target Server Type : MySQL Target Server Version : 50728 File Encoding : 65001 Date: 08/09/2022 09:21:45 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for sys_oper_csp_log -- ---------------------------- DROP TABLE IF EXISTS `sys_oper_csp_log`; CREATE TABLE `sys_oper_csp_log` ( `oper_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主鍵', `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '模塊標(biāo)題', `business_type` int(2) NULL DEFAULT 0 COMMENT '業(yè)務(wù)類型(0=其它,1=新增,2=修改,3=刪除,4=授權(quán),5=導(dǎo)出,6=導(dǎo)入,7=強(qiáng)退,8=生成代碼,9=清空數(shù)據(jù))', `method` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '方法名稱', `request_method` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '請求方式', `operator_type` int(1) NULL DEFAULT 0 COMMENT '操作類別(0其它 1后臺用戶 2手機(jī)端用戶)', `oper_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作人員', `dept_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '部門名稱', `oper_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '請求URL', `oper_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '主機(jī)地址', `oper_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作地點', `oper_param` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '請求參數(shù)', `json_result` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '返回參數(shù)', `status` int(1) NULL DEFAULT 0 COMMENT '操作狀態(tài)(0正常 1異常)', `error_msg` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '錯誤消息', `oper_time` datetime NULL DEFAULT NULL COMMENT '操作時間', PRIMARY KEY (`oper_id`) USING BTREE, INDEX `idx_time`(`oper_time`, `title`, `oper_name`) USING BTREE ) ENGINE = InnoD CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'CSP系統(tǒng)操作日志記錄';
3. 寫相應(yīng)的Controller層
package com.juepeiscm.csp.controller.csplog;
import com.juepeiscm.admin.api.domain.SysOperLog;
import com.juepeiscm.common.core.controller.BaseController;
import com.juepeiscm.common.core.domain.AjaxResult;
import com.juepeiscm.common.core.page.TableDataInfo;
import com.juepeiscm.common.enums.BusinessType;
import com.juepeiscm.common.utils.poi.ExcelUtil;
import com.juepeiscm.csp.annotation.CspLog;
import com.juepeiscm.csp.domain.csplog.SysOperCspLog;
import com.juepeiscm.csp.service.csplog.ISysOperCspLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 操作CSP系統(tǒng)日志
* @Author: py.sun
* @Date: 2022/9/7 14:51
*/
@RestController
@RequestMapping({"/csplog/opercsplog"})
public class SysOperCsplogController extends BaseController {
@Autowired
private ISysOperCspLogService operCspLogService;
public SysOperCsplogController() {
}
/**
* 查詢操作日志列表
* @param sysOperCspLog
* @return
*/
@PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
@GetMapping({"/list"})
public TableDataInfo list(SysOperCspLog sysOperCspLog) {
this.startPage();
List<SysOperCspLog> list = this.operCspLogService.selectOperLogList(sysOperCspLog);
return this.getDataTable(list);
}
/**
* 查詢系統(tǒng)模塊的分類
* @param
* @return
*/
@GetMapping({"/listTitle"})
public TableDataInfo listTitle() {
this.startPage();
List<String> list = this.operCspLogService.selectOperLogListTitle();
return this.getDataTable(list);
}
@CspLog(
title = "導(dǎo)出CSP系統(tǒng)日志",
businessType = BusinessType.EXPORT
)
@PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
@GetMapping({"/export"})
public AjaxResult export(SysOperCspLog operLog) {
List<SysOperCspLog> list = this.operCspLogService.selectOperLogList(operLog);
ExcelUtil<SysOperCspLog> util = new ExcelUtil(SysOperLog.class);
return util.exportExcel(list, "操作CSP系統(tǒng)日志");
}
@CspLog(
title = "操作CSP系統(tǒng)日志",
businessType = BusinessType.DELETE
)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping({"/{operIds}"})
public AjaxResult remove(@PathVariable Long[] operIds) {
return this.toAjax(this.operCspLogService.deleteOperLogByIds(operIds));
}
@CspLog(
title = "清除CSP系統(tǒng)日志",
businessType = BusinessType.CLEAN
)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping({"/clean"})
public AjaxResult clean() {
this.operCspLogService.cleanOperLog();
return AjaxResult.success();
}
}4.Service接口層
package com.juepeiscm.csp.service.csplog;
import com.juepeiscm.admin.api.domain.SysOperLog;
import com.juepeiscm.csp.domain.csplog.SysOperCspLog;
import java.util.List;
/**
* @Author: py.sun
* @Date: 2022/9/7 15:02
*/
public interface ISysOperCspLogService {
void insertOperlog(SysOperCspLog var1);
List<SysOperCspLog> selectOperLogList(SysOperCspLog var1);
List<String> selectOperLogListTitle();
int deleteOperLogByIds(Long[] var1);
SysOperLog selectOperLogById(Long var1);
void cleanOperLog();
}5.Service實現(xiàn)
package com.juepeiscm.csp.service.impl.csplog;
import com.juepeiscm.admin.api.domain.SysOperLog;
import com.juepeiscm.common.core.domain.AjaxResult;
import com.juepeiscm.common.core.domain.entity.SysDept;
import com.juepeiscm.common.core.domain.entity.SysUser;
import com.juepeiscm.common.core.domain.model.LoginUser;
import com.juepeiscm.common.exception.CustomException;
import com.juepeiscm.common.utils.SecurityUtils;
import com.juepeiscm.common.utils.ServletUtils;
import com.juepeiscm.common.utils.StringUtils;
import com.juepeiscm.csp.domain.csplog.SysOperCspLog;
import com.juepeiscm.csp.mapper.csplog.SysOperCspLogMapper;
import com.juepeiscm.csp.service.csplog.ISysOperCspLogService;
import com.juepeiscm.framework.web.service.TokenService;
import com.juepeiscm.uam.service.ISysDeptService;
import com.juepeiscm.uam.version.UamVersion;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Author: py.sun
* @Date: 2022/9/7 15:03
*/
@Service
public class SysOperCspLogServiceImpl implements ISysOperCspLogService {
@Autowired
private SysOperCspLogMapper operLogMapper;
@Autowired
private TokenService tokenService;
@Reference(version = UamVersion.idV)
public ISysDeptService deptService;
@Override
public void insertOperlog(SysOperCspLog sysOperCspLog) {
try {
this.operLogMapper.insertOperlog(sysOperCspLog);
} catch (Exception e) {
e.printStackTrace();
throw new CustomException("CSP系統(tǒng)日志插入失敗,請聯(lián)系管理員?。?!");
}
}
@Override
public List<SysOperCspLog> selectOperLogList(SysOperCspLog sysOperCspLog) {
return this.operLogMapper.selectOperLogList(sysOperCspLog);
}
@Override
public List<String> selectOperLogListTitle() {
return this.operLogMapper.selectOperLogListTitle();
}
@Override
public int deleteOperLogByIds(Long[] operIds) {
return this.operLogMapper.deleteOperLogByIds(operIds);
}
@Override
public SysOperLog selectOperLogById(Long operId) {
return this.operLogMapper.selectOperLogById(operId);
}
@Override
public void cleanOperLog() {
this.operLogMapper.cleanOperLog();
}
}
6.Mapper接口
package com.juepeiscm.csp.mapper.csplog;
import com.juepeiscm.admin.api.domain.SysOperLog;
import com.juepeiscm.csp.domain.csplog.SysOperCspLog;
import java.util.List;
/**
* @Author: py.sun
* @Date: 2022/9/7 15:06
*/
public interface SysOperCspLogMapper {
void insertOperlog(SysOperCspLog var1);
List<SysOperCspLog> selectOperLogList(SysOperCspLog sysOperCspLog);
List<String> selectOperLogListTitle();
int deleteOperLogByIds(Long[] var1);
SysOperLog selectOperLogById(Long var1);
void cleanOperLog();
}7.Mapper.xml(我用的是Mybatis)
<?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="com.juepeiscm.csp.mapper.csplog.SysOperCspLogMapper">
<resultMap type="SysOperCspLog" id="SysOperLogResult">
<id property="operId" column="oper_id" />
<result property="title" column="title" />
<result property="businessType" column="business_type" />
<result property="method" column="method" />
<result property="requestMethod" column="request_method" />
<result property="operatorType" column="operator_type" />
<result property="operName" column="oper_name" />
<result property="deptName" column="dept_name" />
<result property="operUrl" column="oper_url" />
<result property="operIp" column="oper_ip" />
<result property="operLocation" column="oper_location" />
<result property="operParam" column="oper_param" />
<result property="jsonResult" column="json_result" />
<result property="status" column="status" />
<result property="errorMsg" column="error_msg" />
<result property="operTime" column="oper_time" />
</resultMap>
<sql id="selectOperLogVo">
select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time
from sys_oper_csp_log
</sql>
<insert id="insertOperlog" parameterType="SysOperCspLog">
insert into sys_oper_csp_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time)
values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, sysdate())
</insert>
<select id="selectOperLogList" parameterType="SysOperCspLog" resultMap="SysOperLogResult">
<include refid="selectOperLogVo"/>
<where>
<if test="title != null and title != ''">
AND title like concat('%', #{title}, '%')
</if>
<if test="businessType != null and businessType != ''">
AND business_type = #{businessType}
</if>
<if test="businessTypes != null and businessTypes.length > 0">
AND business_type in
<foreach collection="businessTypes" item="businessType" open="(" separator="," close=")">
#{businessType}
</foreach>
</if>
<if test="status != null">
AND status = #{status}
</if>
<if test="operName != null and operName != ''">
AND oper_name like concat('%', #{operName}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 開始時間檢索 -->
and date_format(oper_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 結(jié)束時間檢索 -->
and date_format(oper_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
order by oper_id desc
</select>
<delete id="deleteOperLogByIds" parameterType="Long">
delete from sys_oper_csp_log where oper_id in
<foreach collection="array" item="operId" open="(" separator="," close=")">
#{operId}
</foreach>
</delete>
<select id="selectOperLogById" parameterType="Long" resultMap="SysOperLogResult">
<include refid="selectOperLogVo"/>
where oper_id = #{operId}
</select>
<select id="selectOperLogListTitle" resultType="java.lang.String">
select distinct(title) from sys_oper_csp_log
</select>
<update id="cleanOperLog">
truncate table sys_oper_csp_log
</update>
</mapper>8.CspLog
定義一個日志管理的名稱:CspLog
package com.juepeiscm.csp.annotation;
import com.juepeiscm.common.enums.BusinessType;
import com.juepeiscm.common.enums.OperatorType;
import java.lang.annotation.*;
/**
* CSP系統(tǒng)的日志管理
* @Author: py.sun
* @Date: 2022/9/7 14:42
* @Target表示注解可以使用到哪些地方,可以是類,方法,或者是屬性上,定義在ElementType枚舉中:
* @Retention作用是定義被它所注解的注解保留多久,一共有三種策略,定義在RetentionPolicy枚舉中:
*
* 我們的@CspLog注解,可以作用在方法和參數(shù)上,將由編譯器記錄在類文件中,并在運行時由VM保留,因此可以反射性地讀取。該注解是通過AOP進(jìn)行解析的
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CspLog {
/**
* 模塊
* @return
*/
String title() default "";
/**
* 功能
* @return
*/
BusinessType businessType() default BusinessType.OTHER;
/**
* 操作人類別
* @return
*/
OperatorType operatorType() default OperatorType.MANAGE;
/**
* 是否保存請求的參數(shù)
* @return
*/
boolean isSaveRequestData() default true;
}9.實體類SysOperCspLog
package com.juepeiscm.csp.domain.csplog;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.juepeiscm.common.annotation.Excel;
import com.juepeiscm.common.core.domain.BaseEntity;
import java.util.Date;
/**
* @Author: py.sun
* @Date: 2022/9/7 15:04
*/
public class SysOperCspLog extends BaseEntity {
private static final long serialVersionUID = 1L;
@Excel(
name = "操作序號",
cellType = Excel.ColumnType.NUMERIC
)
private Long operId;
@Excel(
name = "操作模塊"
)
private String title;
@Excel(
name = "業(yè)務(wù)類型",
readConverterExp = "0=其它,1=新增,2=修改,3=刪除,4=授權(quán),5=導(dǎo)出,6=導(dǎo)入,7=強(qiáng)退,8=生成代碼,9=清空數(shù)據(jù)"
)
private Integer businessType;
private Integer[] businessTypes;
@Excel(
name = "請求方法"
)
private String method;
@Excel(
name = "請求方式"
)
private String requestMethod;
@Excel(
name = "操作類別",
readConverterExp = "0=其它,1=后臺用戶,2=手機(jī)端用戶"
)
private Integer operatorType;
@Excel(
name = "操作人員"
)
private String operName;
@Excel(
name = "部門名稱"
)
private String deptName;
@Excel(
name = "請求地址"
)
private String operUrl;
@Excel(
name = "操作地址"
)
private String operIp;
@Excel(
name = "操作地點"
)
private String operLocation;
@Excel(
name = "請求參數(shù)"
)
private String operParam;
@Excel(
name = "返回參數(shù)"
)
private String jsonResult;
@Excel(
name = "狀態(tài)",
readConverterExp = "0=正常,1=異常"
)
private Integer status;
@Excel(
name = "錯誤消息"
)
private String errorMsg;
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss"
)
@Excel(
name = "操作時間",
width = 30.0D,
dateFormat = "yyyy-MM-dd HH:mm:ss"
)
private Date operTime;
public SysOperCspLog() {
}
public Long getOperId() {
return this.operId;
}
public void setOperId(Long operId) {
this.operId = operId;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getBusinessType() {
return this.businessType;
}
public void setBusinessType(Integer businessType) {
this.businessType = businessType;
}
public Integer[] getBusinessTypes() {
return this.businessTypes;
}
public void setBusinessTypes(Integer[] businessTypes) {
this.businessTypes = businessTypes;
}
public String getMethod() {
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
public String getRequestMethod() {
return this.requestMethod;
}
public void setRequestMethod(String requestMethod) {
this.requestMethod = requestMethod;
}
public Integer getOperatorType() {
return this.operatorType;
}
public void setOperatorType(Integer operatorType) {
this.operatorType = operatorType;
}
public String getOperName() {
return this.operName;
}
public void setOperName(String operName) {
this.operName = operName;
}
public String getDeptName() {
return this.deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getOperUrl() {
return this.operUrl;
}
public void setOperUrl(String operUrl) {
this.operUrl = operUrl;
}
public String getOperIp() {
return this.operIp;
}
public void setOperIp(String operIp) {
this.operIp = operIp;
}
public String getOperLocation() {
return this.operLocation;
}
public void setOperLocation(String operLocation) {
this.operLocation = operLocation;
}
public String getOperParam() {
return this.operParam;
}
public void setOperParam(String operParam) {
this.operParam = operParam;
}
public String getJsonResult() {
return this.jsonResult;
}
public void setJsonResult(String jsonResult) {
this.jsonResult = jsonResult;
}
public Integer getStatus() {
return this.status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getErrorMsg() {
return this.errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public Date getOperTime() {
return this.operTime;
}
public void setOperTime(Date operTime) {
this.operTime = operTime;
}
}10. 定義日志管理的切面
大家一定要記住哈,所有針對實體的SysOperCspLog賦值操作必須在這里main執(zhí)行。
package com.juepeiscm.csp.controller.utils;
import com.alibaba.fastjson.JSON;
import com.juepeiscm.common.core.domain.entity.SysDept;
import com.juepeiscm.common.core.domain.model.LoginUser;
import com.juepeiscm.common.enums.BusinessStatus;
import com.juepeiscm.common.enums.HttpMethod;
import com.juepeiscm.common.utils.ServletUtils;
import com.juepeiscm.common.utils.StringUtils;
import com.juepeiscm.common.utils.ip.IpUtils;
import com.juepeiscm.common.utils.spring.SpringUtils;
import com.juepeiscm.csp.annotation.CspLog;
import com.juepeiscm.csp.domain.csplog.SysOperCspLog;
import com.juepeiscm.framework.aspectj.LogAspect;
import com.juepeiscm.framework.manager.AsyncManager;
import com.juepeiscm.framework.web.service.TokenService;
import com.juepeiscm.uam.service.ISysDeptService;
import com.juepeiscm.uam.version.UamVersion;
import org.apache.dubbo.config.annotation.Reference;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
/**
* @Author: py.sun
* @Date: 2022/9/7 16:31
* 操作日志記錄處理
*/
@Aspect
@Component
public class CspLogAspect {
private static final Logger log = LoggerFactory.getLogger(CspLog.class);
@Reference(version = UamVersion.idV)
public ISysDeptService deptService;
public CspLogAspect() {
}
//把@CspLog配置為切入點。 配置織入點
@Pointcut("@annotation(com.juepeiscm.csp.annotation.CspLog)")
public void logPointCut() {
}
//攔截異常操作
// 處理完請求后執(zhí)行該方法。也就是用@CspLog注解的方法,執(zhí)行完后,調(diào)用handleLog方法,處理返回結(jié)果。
@AfterReturning(
pointcut = "logPointCut()",
returning = "jsonResult"
)
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
this.handleLog(joinPoint, (Exception)null, jsonResult);
}
@AfterThrowing(
value = "logPointCut()",
throwing = "e"
)
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
this.handleLog(joinPoint, e, (Object)null);
}
// 如果函數(shù)拋出了異常,也是執(zhí)行handleLog方法,不過和正常返回的參數(shù)不一樣,此處是為了處理異常。
protected void handleLog(JoinPoint joinPoint, Exception e, Object jsonResult) {
try {
// 獲得注解
CspLog controllerLog = this.getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
// 獲取當(dāng)前的用戶
LoginUser loginUser = ((TokenService) SpringUtils.getBean(TokenService.class)).getLoginUser(ServletUtils.getRequest());
// *========數(shù)據(jù)庫日志=========*//
SysOperCspLog operLog = new SysOperCspLog();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 請求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
operLog.setOperIp(ip);
// 返回參數(shù)
operLog.setJsonResult(JSON.toJSONString(jsonResult));
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if (loginUser != null) {
operLog.setOperName(loginUser.getUsername());
}
// 獲取當(dāng)前登錄用戶的部門名稱
SysDept sysDept = deptService.selectDeptIdByUserIdAndAppId(loginUser.getUser().getUserId(), "oms");
if(sysDept != null && StringUtils.isNotEmpty(sysDept.getDeptName())){
operLog.setDeptName(sysDept.getDeptName());
}
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 設(shè)置方法名稱
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 設(shè)置請求方式
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 處理設(shè)置注解上的參數(shù)
this.getControllerMethodDescription(joinPoint, controllerLog, operLog);
// 保存數(shù)據(jù)庫
AsyncManager.me().execute(AsyncFactoryCsp.recordOper(operLog));
} catch (Exception var10) {
// 記錄本地異常日志
log.error("==前置通知異常==");
log.error("異常信息:{}", var10.getMessage());
var10.printStackTrace();
}
}
public void getControllerMethodDescription(JoinPoint joinPoint, CspLog log, SysOperCspLog operLog) throws Exception {
operLog.setBusinessType(log.businessType().ordinal());
operLog.setTitle(log.title());
operLog.setOperatorType(log.operatorType().ordinal());
if (log.isSaveRequestData()) {
this.setRequestValue(joinPoint, operLog);
}
}
private void setRequestValue(JoinPoint joinPoint, SysOperCspLog operLog) throws Exception {
String requestMethod = operLog.getRequestMethod();
if (!HttpMethod.PUT.name().equals(requestMethod) && !HttpMethod.POST.name().equals(requestMethod)) {
Map<?, ?> paramsMap = (Map)ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
} else {
String params = this.argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
}
}
private CspLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method method = methodSignature.getMethod();
return method != null ? (CspLog)method.getAnnotation(CspLog.class) : null;
}
private String argsArrayToString(Object[] paramsArray) {
String params = "";
if (paramsArray != null && paramsArray.length > 0) {
for(int i = 0; i < paramsArray.length; ++i) {
if (StringUtils.isNotNull(paramsArray[i]) && !this.isFilterObject(paramsArray[i])) {
Object jsonObj = JSON.toJSON(paramsArray[i]);
params = params + jsonObj.toString() + " ";
}
}
}
return params.trim();
}
public boolean isFilterObject(Object o) {
Class<?> clazz = o.getClass();
if (clazz.isArray()) {
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
} else {
Iterator iter;
if (Collection.class.isAssignableFrom(clazz)) {
Collection collection = (Collection)o;
iter = collection.iterator();
if (iter.hasNext()) {
return iter.next() instanceof MultipartFile;
}
} else if (Map.class.isAssignableFrom(clazz)) {
Map map = (Map)o;
iter = map.entrySet().iterator();
if (iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
return entry.getValue() instanceof MultipartFile;
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse || o instanceof BindingResult;
}
}
}11.AsyncFactoryCsp
package com.juepeiscm.csp.controller.utils;
import com.juepeiscm.common.utils.ip.AddressUtils;
import com.juepeiscm.common.utils.spring.SpringUtils;
import com.juepeiscm.csp.domain.csplog.SysOperCspLog;
import com.juepeiscm.csp.service.csplog.ISysOperCspLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.TimerTask;
/**
* @Author: py.sun
* @Date: 2022/9/7 16:47
*/
public class AsyncFactoryCsp {
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
public AsyncFactoryCsp() {
}
public static TimerTask recordOper(final SysOperCspLog operLog) {
return new TimerTask() {
public void run() {
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
((ISysOperCspLogService) SpringUtils.getBean(ISysOperCspLogService.class)).insertOperlog(operLog);
}
};
}
}12. 寫一個Controller的Demo來執(zhí)行一條日志試試
在這里插入代碼片package com.juepeiscm.csp.controller.order;
在這里插入代碼片package com.juepeiscm.csp.controller.order;
import com.alibaba.fastjson.JSON;
import com.juepeiscm.admin.api.service.ISysDictDataService;
import com.juepeiscm.common.annotation.RepeatSubmit;
import com.juepeiscm.common.core.controller.BaseController;
import com.juepeiscm.common.core.domain.AjaxResult;
import com.juepeiscm.common.core.domain.entity.SysDictData;
import com.juepeiscm.common.core.page.TableDataInfo;
import com.juepeiscm.common.enums.BusinessType;
import com.juepeiscm.common.exception.BaseException;
import com.juepeiscm.common.utils.StringUtils;
import com.juepeiscm.common.utils.poi.ExcelUtil;
import com.juepeiscm.csp.annotation.CspLog;
import com.juepeiscm.csp.domain.order.CspGodownEntry;
import com.juepeiscm.csp.domain.order.CspGodownEntryDetails;
import com.juepeiscm.csp.service.common.MenuLogService;
import com.juepeiscm.csp.service.data.ICspGoodsdataService;
import com.juepeiscm.csp.service.order.ICspGodownEntryService;
import com.juepeiscm.csp.vo.GodownEntryExcel;
import com.juepeiscm.csp.vo.GoodsDataForGodownEntryDetails;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
/**
* 入庫訂單Controller
*
* @author juepeiscm
* @date 2021-07-23
*/
@Api(tags = "入庫訂單接口")
@RestController
@RequestMapping("/order/godownEntry")
public class CspGodownEntryController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(CspGodownEntryController.class);
@Autowired
private ICspGodownEntryService cspGodownEntryService;
@Autowired
private ICspGoodsdataService goodsDataService;
@Autowired
private MenuLogService menuLogService;
@Autowired
private ISysDictDataService sysDictDataService;
/**
* 新增入庫訂單Demo
*/
@PreAuthorize("@ss.hasPermi('order:godownEntry:add')")
@ApiOperation(value = "新增入庫訂單")
@CspLog(title = "入庫訂單demo4", businessType = BusinessType.INSERT)
@PostMapping("/addOrder")
@RepeatSubmit
public AjaxResult addDemo(@RequestBody @Valid CspGodownEntry godownEntry) {
try {
return toAjax(cspGodownEntryService.insertOmsGodownEntry(godownEntry));
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error("新增失敗,請聯(lián)系管理員");
}
}
}測試下,看看數(shù)據(jù)庫內(nèi)容

到此這篇關(guān)于SpringBoot利用AOP實現(xiàn)一個日志管理詳解的文章就介紹到這了,更多相關(guān)SpringBoot AOP日志管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PowerJob的TransportServiceAware工作流程源碼解讀
這篇文章主要介紹了PowerJob的TransportServiceAware工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Java日常練習(xí)題,每天進(jìn)步一點點(63)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-08-08
SpringBoot整合DeepSeek實現(xiàn)AI對話功能
本文介紹了如何在SpringBoot項目中整合DeepSeek API和本地私有化部署DeepSeekR1模型,通過SpringAI框架簡化了人工智能模型的集成,感興趣的小伙伴跟著小編一起來看看吧2025-02-02
Java ConcurrentModificationException異常解決案例詳解
這篇文章主要介紹了Java ConcurrentModificationException異常解決案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09

