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 '操作地點(diǎn)', `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ù)上,將由編譯器記錄在類文件中,并在運(yùn)行時由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 = "操作地點(diǎn)" ) 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配置為切入點(diǎn)。 配置織入點(diǎn) @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)文章
WebSocket實現(xiàn)系統(tǒng)后臺消息實時通知功能
在現(xiàn)代Web應(yīng)用中,提供實時通知對于改善用戶體驗至關(guān)重要,WebSocket技術(shù)允許建立雙向通信通道,從系統(tǒng)后臺將消息實時傳送給系統(tǒng)用戶,下面我們就來深入探討一下如何使用WebSocket來實現(xiàn)這一功能吧2023-10-10Java數(shù)據(jù)結(jié)構(gòu)之鏈表的增刪查改詳解
在這篇文章中,小編將帶大家了解一下Java數(shù)據(jù)結(jié)構(gòu)中鏈表的增刪查改(以下結(jié)果均在IDEA中編譯)希望在方便自己復(fù)習(xí)的同時也能幫助到大家2022-09-09java 中的instanceof用法詳解及instanceof是什么意思(推薦)
instanceof 是 Java 的保留關(guān)鍵字。它的作用是測試它左邊的對象是否是它右邊的類的實例,返回 boolean 的數(shù)據(jù)類型。接下來通過本文給大家介紹java 中的instanceof用法詳解及instanceof是什么意思,需要的朋友參考下吧2017-11-11Java 類型相互轉(zhuǎn)換byte[]類型,Blob類型詳細(xì)介紹
這篇文章主要介紹了Java 類型相互轉(zhuǎn)換byte[]類型,Blob類型的相關(guān)資料,需要的朋友可以參考下2016-10-10