作為一個小外包...,記錄一下工作中常用的一些方法(tools),以便后續(xù)使用。
如果有小伙伴看,歡迎指點。切記:不要指指點點。
操作日志表結構
-- mysql 8.0 操作日志表結構
CREATE TABLE `sys_op_log`
(
`id` varchar(40) NOT NULL COMMENT '主鍵',
`op_user_id` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '操作人id\n',
`op_user_name` varchar(65) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '操作人賬號',
`url` varchar(255) DEFAULT NULL COMMENT '訪問路徑',
`ip` varchar(255) DEFAULT NULL COMMENT '客戶端ip',
`module` varchar(255) DEFAULT NULL COMMENT '所屬模塊',
`type` varchar(255) DEFAULT NULL COMMENT '請求類型',
`status` tinyint DEFAULT NULL COMMENT '1成功,0失敗',
`title` varchar(255) DEFAULT NULL COMMENT '日志標題',
`message` text COMMENT '成功或失敗的信息',
`op_time` datetime DEFAULT NULL COMMENT '操作時間',
`request_param` varchar(2000) DEFAULT NULL COMMENT '請求參數(shù)\n',
`request_body` varchar(2000) DEFAULT NULL COMMENT '請求body',
`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
`create_by` varchar(40) DEFAULT NULL COMMENT '創(chuàng)建人',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`update_by` varchar(40) DEFAULT NULL COMMENT '更新人',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='系統(tǒng)操作日志表';
注解:
package log;
import java.lang.annotation.*;
/**
* @author OutResource Boy
* @date 2023/8/17 22:43
*/
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OpLog {
/**
* 操作模塊
*/
String module() default "";
/**
* 操作標題
*/
String title() default "";
/**
* 是否使用了body參數(shù)
*/
boolean useBody() default false;
/**
* 注解:body參數(shù)位于方法的第幾位
*/
int bodyIndex() default 0;
}
opLog status 相關常量
package log;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* opLog status 相關常量
* @author OutResource Boy
* @date 2023/8/18 10:58
*/
@AllArgsConstructor
public enum OpLogEnum {
/**
* 成功
*/
SUCCESS(1, "成功"),
/**
* 失敗
*/
FAIL(0, "失敗");
@Getter
private final Integer FLAG;
@Getter
private final String DESC;
}
Aspect
package log;
import java.util.Date;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import utils.GlobalWebVarUtil;
import utils.SnowFlakeIdGenerateUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @author OutResource Boy
* 來自:ruoyi
* 重要依賴:hu-tool
* @date 2023/8/17 22:43
*/
@Aspect
@Component
public class OpLogAspect {
/**
* 處理完請求后執(zhí)行
*
* @param opLog 操作日志
* @param jsonResult json結果
*/
@AfterReturning(pointcut = "@annotation(opLog)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, OpLog opLog, Object jsonResult) {
handleLog(joinPoint, opLog, null, jsonResult);
}
/**
* 攔截異常操作
*
* @param e 異常
* @param opLog 操作日志
*/
@AfterThrowing(pointcut = "@annotation(opLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, OpLog opLog, Exception e) {
handleLog(joinPoint, opLog, e, null);
}
/**
* 處理日志
*
* @param joinPoint 連接點
* @param opLog 操作日志注解
* @param e 異常
* @param jsonResult json結果
*/
private void handleLog(JoinPoint joinPoint, OpLog opLog, Exception e, Object jsonResult) {
try {
// 記錄到數(shù)據(jù)庫時,return的數(shù)據(jù) 或者 異常的 限制長度
int msgMaxSize = 500;
// 1、生成日志Id
String id = SnowFlakeIdGenerateUtils.getSnowFlakeId();
// 2、操作人Id:這個需要獲取當前登錄的用戶,這里不設置
String opId = StrUtil.EMPTY;
// 3、和操作人Id一樣
String opName = StrUtil.EMPTY;
// 4、獲取請求Uri
HttpServletRequest request = GlobalWebVarUtil.getRequest();
String requestUri = request.getRequestURI();
// 5、獲取請求者IP地址
String ip = ServletUtil.getClientIP(request);
// 6、獲取請求模塊
String module = opLog.module();
// +1、請求方式
String requestMethod = request.getMethod();
// 7、獲取請求主題
String title = opLog.title();
// 8、獲取請求Param參數(shù)
Map<String, String[]> parameterMap = request.getParameterMap();
// 處理成json串
String requestParam = JSONUtil.toJsonPrettyStr(parameterMap);
// 9、獲取Body參數(shù)--> 這個不能從request中獲取,因為request的body只能被讀取一次,所有采用從方法的形參中讀取
String bodyParam = StrUtil.EMPTY;
if (opLog.useBody()) {
Object[] args = joinPoint.getArgs();
bodyParam = JSONUtil.toJsonPrettyStr(args[opLog.bodyIndex()]);
}
// 10、處理記錄的message、狀態(tài)
String message;
int status;
if (ObjectUtil.isNull(e)) {
status = OpLogEnum.SUCCESS.getFLAG();
String resString = JSONUtil.toJsonPrettyStr(jsonResult);
message = StrUtil.length(resString) > msgMaxSize ? StrUtil.sub(resString, 0, msgMaxSize) : resString;
} else {
status = OpLogEnum.FAIL.getFLAG();
String resString = JSONUtil.toJsonPrettyStr(e);
message = StrUtil.length(resString) > msgMaxSize ? StrUtil.sub(resString, 0, msgMaxSize) : resString;
}
// 記錄日志
SysOpLog sysOpLog = new SysOpLog();
sysOpLog.setId(id);
sysOpLog.setOpId(opId);
sysOpLog.setOpName(opName);
sysOpLog.setUrl(requestUri);
sysOpLog.setIp(ip);
sysOpLog.setModule(module);
sysOpLog.setType(requestMethod);
sysOpLog.setStatus(status);
sysOpLog.setTitle(title);
sysOpLog.setMessage(message);
sysOpLog.setOpTime(new Date());
sysOpLog.setRequestParam(requestParam);
sysOpLog.setRequestBody(bodyParam);
// --- 下面這幾個我覺得放在mybatis攔截器里面比較好,這里就不設置了 --- //
sysOpLog.setCreateTime(new Date());
sysOpLog.setCreateBy("");
sysOpLog.setUpdateTime(new Date());
sysOpLog.setUpdateBy("");
}catch (Exception exp){
// 打一下異常..
}
}
}
其他小工具
package utils;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
/**
* 雪花id生成工具
*
* @author OutResource Boy
* @date 2023/6/28 17:06
*/
public class SnowFlakeIdGenerateUtils {
public static String getSnowFlakeId(){
//參數(shù)1為終端ID, 參數(shù)2為數(shù)據(jù)中心ID
Snowflake snowflake = IdUtil.getSnowflake(1, 1);
return snowflake.nextIdStr();
}
}
package utils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 獲取Request
* @author OutResource Boy
* @date 2023/07/07
*/
public class GlobalWebVarUtil {
/**
* 得到HttpServletRequest對象
*/
public static HttpServletRequest getRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return requestAttributes != null ? ((ServletRequestAttributes) requestAttributes).getRequest() : null;
}
/**
* 設置父線程requestAttributes共享 當異步執(zhí)行的DAO方法需要記錄日志時,需要先調用此方法設置
*/
public static void setParentRequestShare() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(requestAttributes, true);
}
}
}
完整代碼在這:GIT