package com.iplatform.base.support;
|
|
import com.iplatform.base.AsyncManager;
|
import com.iplatform.base.SecuritySpi;
|
import com.iplatform.base.service.LogServiceImpl;
|
import com.iplatform.model.po.S_oper_log;
|
import com.iplatform.model.po.S_user_core;
|
import com.walker.infrastructure.utils.JsonUtils;
|
import com.walker.infrastructure.utils.StringUtils;
|
import com.walker.web.Constants;
|
import com.walker.web.ResponseCode;
|
import com.walker.web.log.BusinessType;
|
import com.walker.web.log.Log;
|
import com.walker.web.util.IpUtils;
|
import com.walker.web.util.ServletUtils;
|
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.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
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.util.Collection;
|
import java.util.Map;
|
import java.util.TimerTask;
|
|
/**
|
* 操作日志切面对象定义。<p></p>
|
* <pre>
|
* 1)业务在自己的调用方法上添加注解即可自动完成操作日志记录
|
* 2)注解示例:
|
* @Log(title = "用户管理", businessType = BusinessType.Insert, isSaveRequestData = true, isSaveResponseData = false)
|
* </pre>
|
* @date 2023-01-06
|
*/
|
@Aspect
|
public class LogAspect {
|
|
protected final transient Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
private static final int MAX_DATA_SIZE = 2000;
|
private static final int MAX_ERROR_SIZE = com.iplatform.base.Constants.LOG_ERROR_MAX_SIZE;
|
|
private SecuritySpi securitySpi;
|
private LogServiceImpl logService;
|
private boolean enableLog = true;
|
|
/**
|
* 配置是否打开或关闭日志写入。
|
* @param enableLog
|
*/
|
public void setEnableLog(boolean enableLog) {
|
this.enableLog = enableLog;
|
}
|
|
public void setLogService(LogServiceImpl logService) {
|
this.logService = logService;
|
}
|
|
public void setSecuritySpi(SecuritySpi securitySpi) {
|
this.securitySpi = securitySpi;
|
}
|
|
/**
|
* 处理完请求后执行
|
* @param joinPoint 切点
|
*/
|
@AfterReturning(pointcut = "@annotation(logAnnotation)", returning = "jsonResult")
|
public void doAfterReturning(JoinPoint joinPoint, Log logAnnotation, Object jsonResult) {
|
if(this.enableLog){
|
handleLog(joinPoint, logAnnotation, null, jsonResult);
|
}
|
}
|
|
/**
|
* 拦截异常操作
|
* @param joinPoint 切点
|
* @param e 异常
|
*/
|
@AfterThrowing(value = "@annotation(logAnnotation)", throwing = "e")
|
public void doAfterThrowing(JoinPoint joinPoint, Log logAnnotation, Exception e) {
|
if(this.enableLog){
|
handleLog(joinPoint, logAnnotation, e, null);
|
}
|
}
|
|
private void handleLog(final JoinPoint joinPoint, Log logAnnotation, final Exception e, Object jsonResult){
|
try{
|
S_oper_log s_oper_log = new S_oper_log();
|
S_user_core user_core = this.securitySpi.getCurrentUser();
|
if(user_core != null){
|
s_oper_log.setOper_name(user_core.getUser_name());
|
}
|
if(e == null){
|
s_oper_log.setStatus(ResponseCode.SUCCESS.getCode());
|
} else {
|
s_oper_log.setStatus(ResponseCode.ERROR.getCode());
|
s_oper_log.setError_msg(StringUtils.substring(e.getMessage(), 0, MAX_ERROR_SIZE));
|
}
|
|
String requestMethod = ServletUtils.getRequest().getMethod();
|
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
s_oper_log.setOper_ip(ip);
|
s_oper_log.setOper_url(ServletUtils.getRequest().getRequestURI());
|
// 设置方法名称
|
String className = joinPoint.getTarget().getClass().getName();
|
String methodName = joinPoint.getSignature().getName();
|
s_oper_log.setMethod(className + "." + methodName);
|
s_oper_log.setRequest_method(requestMethod);
|
s_oper_log.setOper_location(StringUtils.EMPTY_STRING);
|
s_oper_log.setTitle(logAnnotation.title());
|
s_oper_log.setOperate_user(logAnnotation.operatorType().getIndex());
|
|
//
|
BusinessType businessType = logAnnotation.businessType();
|
s_oper_log.setBusiness_type(businessType.getIndex());
|
|
if(logAnnotation.isSaveRequestData() && businessType.isSaveRequest()){
|
// 只有开发设置注解以及业务类型都允许保存时才真正保存数据
|
if(requestMethod.equals(Constants.HTTP_METHOD_POST) || requestMethod.equals(Constants.HTTP_METHOD_PUT)){
|
String params = argsArrayToString(joinPoint.getArgs());
|
if(StringUtils.isNotEmpty(params)){
|
s_oper_log.setOper_param(params);
|
}
|
} else {
|
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
if(paramsMap != null){
|
s_oper_log.setOper_param(StringUtils.substring(paramsMap.toString(), 0, MAX_DATA_SIZE));
|
}
|
}
|
}
|
if(logAnnotation.isSaveResponseData() && businessType.isSaveResponse()){
|
// 只有开发设置注解以及业务类型都允许保存时才真正保存数据
|
if(jsonResult != null){
|
String res = JsonUtils.objectToJsonString(jsonResult);
|
if(StringUtils.isNotEmpty(res)){
|
s_oper_log.setJson_result(StringUtils.substring(res, 0, MAX_DATA_SIZE));
|
}
|
}
|
}
|
|
AsyncManager.me().execute(this.acquireOperateLogTask(s_oper_log));
|
|
}catch (Exception ex){
|
if(logger.isDebugEnabled()){
|
logger.error(ERROR_LOG, ex);
|
} else {
|
logger.error(ERROR_LOG + ex.getMessage());
|
}
|
}
|
}
|
|
private String argsArrayToString(Object[] paramsArray){
|
try {
|
StringBuilder sb = new StringBuilder();
|
if (paramsArray != null && paramsArray.length > 0){
|
for (Object o : paramsArray){
|
if(o == null){
|
continue;
|
}
|
if(!this.isFilterObject(o)){
|
sb.append(JsonUtils.objectToJsonString(o)).append(StringUtils.SEPARATOR_SEMI_COLON);
|
}
|
}
|
}
|
return sb.toString();
|
} catch (Exception e){
|
return StringUtils.EMPTY_STRING;
|
}
|
}
|
|
/**
|
* 判断是否需要过滤的对象。
|
*
|
* @param o 对象信息。
|
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
*/
|
private boolean isFilterObject(final Object o)
|
{
|
Class<?> clazz = o.getClass();
|
if (clazz.isArray()) {
|
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
}
|
else if (Collection.class.isAssignableFrom(clazz)) {
|
Collection collection = (Collection) o;
|
for (Object value : collection) {
|
return value instanceof MultipartFile;
|
}
|
}
|
else if (Map.class.isAssignableFrom(clazz)) {
|
Map map = (Map) o;
|
for (Object value : map.entrySet()) {
|
Map.Entry entry = (Map.Entry) value;
|
return entry.getValue() instanceof MultipartFile;
|
}
|
}
|
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
|| o instanceof BindingResult;
|
}
|
|
private TimerTask acquireOperateLogTask(S_oper_log s_oper_log){
|
return new TimerTask() {
|
@Override
|
public void run() {
|
// s_oper_log.setOper_time(DateUtils.getDateTimeNumber(System.currentTimeMillis()));
|
// s_oper_log.setOper_id(NumberGenerator.getLongSequenceNumber());
|
logService.execInsertOperateLog(s_oper_log);
|
}
|
};
|
}
|
|
private static final String ERROR_LOG = "日志切面记录异常:";
|
}
|