项目场景:
采用AOP的方式,拦截请求,写入日志
切面代码:
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
@Slf4j
public class RSAAspect {
@Autowired
private LogService logService;
@Pointcut("execution(* com..*.controller..*.*(..))")
public void webRequest() {
}
@Around("webRequest()")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = joinPoint.proceed();
Map<String, Object> joinPointMap= new HashMap<>();
String apiName = joinPoint.getSignature().getName();
joinPointMap.put("apiName",apiName);
joinPointMap.put("className",joinPoint.getTarget().getClass().getName());
joinPointMap.put("signature",joinPoint.getSignature());
joinPointMap.put("proceed",proceed);
// 获取请求信息
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//保存操作日志
logService.saveLogAction(joinPointMap,request);
return proceed;
}
}
业务代码:
public void saveLogAction( Map<String, Object> joinPointMap, HttpServletRequest request) {
try {
//接口名
String apiName = joinPointMap.get("apiName").toString();
//类名
String className = joinPointMap.get("className").toString();
String lastClassName = className.substring(className.lastIndexOf(".") + 1);
//get/post...
String requestMethod = request.getMethod();
// 获取客户端IP地址
String clientIpAddress = request.getRemoteAddr();
// 获取服务端IP地址(注意:这通常是负载均衡器或前端服务器的IP)
String serverIpAddress = request.getLocalAddr();
// 获取服务器端口
String serverPort = String.valueOf(request.getLocalPort());
LogAction logAction = new LogAction();
logAction.setClientIp(clientIpAddress);
logAction.setServerIp(serverIpAddress);
logAction.setServerPort(serverPort);
logAction.setActionTime(LocalDateTime.now());
logAction.setLogId(getUUID());
logAction.setSessionId("");
logAction.setSystemName(ConMap.SYSTEM_NAME);
logAction.setModuleName("");
logAction.setActionName(getActionNameByMethod(requestMethod,apiName));
if(ConMap.containsKey(lastClassName)) {
//Controller对应的模块名称
String lastName = ConMap.getValue(lastClassName);
logAction.setModuleName(lastName);
//操作描述 xx对xxx进行xxx操作
StringBuilder sb = new StringBuilder();
sb.append("对");
sb.append(lastName);
sb.append("进行");
sb.append(logAction.getActionName());
sb.append("操作");
logAction.setActionDesc(sb.toString());
}else {
logAction.setActionDesc(logAction.getActionName());
}
logAction.setActionCmd(className+"."+apiName);
logAction.setActionNum(0);
logAction.setActionResult(1);
String sessionId = StpUtil.getTokenValue();
logAction.setSessionId(sessionId);
// 返回结果
Object proceed = joinPointMap.get("proceed");
if (proceed instanceof R) {
R r = (R) proceed;
if(r.getCode().equals("200")){
logAction.setActionResult(0);
Object obj = r.getData();
logAction.setActionNum(getDataTotal(obj));
}
}
if(StpUtil.isLogin()){
//当前人信息
AppUser userInfo = UserInfoUtil.getUserInfo();
if(userInfo!=null){
logAction.setUserId(userInfo.getId());
logAction.setUserCode(userInfo.getUserCode());
logAction.setUserName(userInfo.getUserName());
logAction.setTenantId(userInfo.getTenantId());
logAction.setActionDesc(userInfo.getUserCode()+logAction.getActionDesc());
}
}
this.baseMapper.insert(logAction);
}catch (Throwable e) {
log.error("记录操作日志异常", e);
}
}
private String getActionNameByMethod(String requestMethod, String apiName) {
String actionName = getActionNameByApi(apiName);
if(StringUtils.isEmpty(actionName)) {
switch (requestMethod) {
case "GET":
case "get":
actionName = "查询";
break;
case "DELETE":
case "delete":
actionName = "删除";
break;
default:
actionName = "新增或修改";
}
}
return actionName;
}
/*获取数据量*/
private Integer getDataTotal(Object obj) {
if (obj != null) {
if (obj instanceof List) {
log.debug("Object is a List.");
return ((List<Object>) obj).size();
} else if (obj instanceof Map ) {
log.debug("Object is a Map.");
Map<String, Object> map = (Map<String, Object>) obj;
return map.get("total") ==null ? 0 : Integer.valueOf(map.get("total").toString()) ;
} else if (obj instanceof Page) {
log.debug("Object is a Page.");
Page<?> page = (Page<?>) obj;
return (int) page.getTotal();
}
}
return 0;
}
private String getActionNameByApi(String apiName) {
String name = "";
if(apiName.contains("login") || apiName.contains("doLogin")){
name = "登录";
}else if(apiName.contains("logout")){
name = "登出";
}else if(apiName.contains("page") || apiName.contains("get") || apiName.contains("select")
|| apiName.contains("list") || apiName.contains("search")){
name = "查询";
}else if(apiName.contains("create") || apiName.contains("add") || apiName.contains("save")){
name = "新增";
}else if(apiName.contains("update")){
name = "修改";
}else if(apiName.contains("delete")){
name = "删除";
}else if(apiName.contains("export")){
name = "导出";
}else if(apiName.contains("import") ){
name = "导入";
}else if(apiName.contains("upload") ){
name = "上传";
}
return name;
}
private String getUUID() {
String uuid = UUID.randomUUID().toString();
return uuid.replaceAll("-", "");
}
业务代码:
import java.util.HashMap;
import java.util.Map;
public class ConMap {
//根据业务系统自己命名
public static String SYSTEM_NAME ="运营系统";
// 创建一个静态的HashMap来存储固定的键值对
private static final Map<String, String> FIXED_MAP = new HashMap<>();
// 静态初始化块,用于初始化FIXED_MAP
static {
/*auth*/
FIXED_MAP.put("AppDeptController", "部门");
FIXED_MAP.put("AppRoleController", "角色");
FIXED_MAP.put("AppTenantController", "租户");
FIXED_MAP.put("AppUserController", "用户");
// 添加更多固定的键值对...
}
// 私有构造器,防止外部实例化
private ConMap() {
}
/**
* 获取指定的key对应的value
*
* @param key 要查找的key
* @return 如果key存在,则返回对应的value;否则返回null
*/
public static String getValue(String key) {
return FIXED_MAP.get(key);
}
/**
* 检查Map中是否包含指定的key
*
* @param key 要检查的key
* @return 如果Map包含指定的key,则返回true;否则返回false
*/
public static boolean containsKey(String key) {
return FIXED_MAP.containsKey(key);
}
}
操作类:
/**
* <p>
* 操作日志
* </p>
*/
@Getter
@Setter
@TableName("tbl_log")
public class LogAction extends CrudEntity {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long id;
/**
* 租户id
*/
private Long tenantId;
/**
* 用户id
*/
private Long userId;
/**
* 用户帐号
*/
private String userCode;
/**
* 用户姓名
*/
private String userName;
/**
* 客户端IP地址:用户登录所使用的客户端IP
*
*/
private String clientIp;
/**
* 服务端IP地址:应用服务器ip地址
*/
private String serverIp;
/**
* 服务器端端口
*/
private String serverPort;
/**
* 操作时间
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime actionTime;
/**
*日志ID
*/
private String logId;
/**
*会话ID:关联应用系统接口调用日志的标识
*/
private String sessionId;
/**
* 系统名称,三级系统名称“辽宁联通服务营销运营系统”
*/
private String systemName;
/**
* 模块名称 如:开户、积分调整、开通xx套餐等。如果此业务涉敏,需与“涉敏数据资产”
*/
private String moduleName;
/**
*操作动作名称,如:新增、查询、修改、删除、导出、登录、登出
*/
private String actionName;
/**
*操作描述:如:Xxx(操作帐号)对(操作对象xxx(可为手机号))进行xxx操作
*/
private String actionDesc;
/**
* 操作命令,记录接口请求的方法com.holycrm.hollycas.record.controller.queryRecord
*/
private String actionCmd;
/**
* 操作数量
*/
private Integer actionNum;
/**
* 操作结果,0:成功,1:失败
*/
private Integer actionResult;
}
sql脚本:
CREATE TABLE `tbl_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`tenant_id` bigint(20) DEFAULT NULL COMMENT '租户id',
`user_id` varchar(50) DEFAULT NULL COMMENT '用户id',
`user_code` varchar(50) DEFAULT NULL COMMENT '用户帐号',
`user_name` varchar(50) DEFAULT NULL COMMENT '用户姓名',
`client_ip` varchar(50) DEFAULT NULL COMMENT '客户端IP地址:用户登录所使用的客户端IP',
`server_ip` varchar(50) DEFAULT NULL COMMENT '服务端IP地址:应用服务器ip地址',
`server_port` varchar(20) DEFAULT NULL COMMENT '服务器端端口',
`action_time` datetime DEFAULT NULL COMMENT '操作时间',
`log_id` varchar(50) DEFAULT NULL COMMENT '日志ID',
`session_id` varchar(50) DEFAULT NULL COMMENT '会话ID:关联应用系统接口调用日志的标识',
`system_name` varchar(50) DEFAULT NULL COMMENT '系统名称,三级系统名称“辽宁联通服务营销运营系统”',
`module_name` varchar(50) DEFAULT NULL COMMENT '模块名称,如crm系统:开户、积分调整、开通xx套餐等。如果此业务涉敏,需与“涉敏数据资产”',
`action_name` varchar(50) DEFAULT NULL COMMENT '操作动作名称,如:新增、查询、修改、删除、导出、登录、登出',
`action_desc` varchar(500) DEFAULT NULL COMMENT '操作描述:如:Xxx(操作帐号)对(操作对象xxx(可为手机号))进行xxx操作',
`action_cmd` varchar(500) DEFAULT NULL COMMENT '操作命令,记录接口请求的方法com.holycrm.hollycas.record.controller.queryRecord',
`action_num` int(10) DEFAULT NULL COMMENT '操作数量',
`action_result` int(10) DEFAULT NULL COMMENT '操作结果:0-成功1-失败',
`update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '最后更新人',
`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
`create_by` varchar(50) DEFAULT NULL COMMENT '最后更新人',
`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建人部门id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志';