import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import cn.id5.commons.util.DateUtils;
import cn.id5.entity.sys.SysAccessErrorLog;
import cn.id5.entity.sys.SysAccessLog;
import cn.id5.mapper.sys.SysAccessErrorLogMapper;
@Aspect
@Component
public class ErrorLogAspect extends BaseAopAspect {
private static final Logger logger = LoggerFactory.getLogger("err_log_data");
@Autowired
private SysAccessErrorLogMapper sysAccessErrorLogMapper;
@AfterThrowing(value = "@annotation(cn.id5.annotation.OperationLog)", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Throwable e) {
if (e instanceof Throwable) {
SysAccessLog sal = super.joinPointArgs(joinPoint);
SysAccessErrorLog sael = SysAccessErrorLog.builder()
.userId(sal.getUserId())
.dwcode(sal.getDwcode())
.clientIp(sal.getClientIp())
.uri(sal.getUri())
.func(sal.getFunc())
.funcDesc(sal.getFuncDesc())
.classSlg(sal.getClassSlg())
.logTime(DateUtils.getDateFormatMillisWithSplit())
.requestTime(sal.getRequestTime())
.responseTime(sal.getResponseTime())
.estTime(sal.getEstTime())
.requestParams(sal.getRequestParams())
.errStackTrace(ExceptionUtils.getStackTrace(e))
.build();
sysAccessErrorLogMapper.insert(sael);
logger.error(e.getMessage(), e);
}
}
}
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DateUtils {
// 毫秒时间字符串
public static final String TIME_MILLIS = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* yyyy-MM-dd HH:mm:ss.SSS
*
* @return
*/
public static String getDateFormatMillisWithSplit() {
return getDateStr(TIME_MILLIS);
}
/**
* yyyyMMddHHmmssSSS
*
* @return
*/
public static String getDateFormatMillis() {
return getDateStr("yyyyMMddHHmmssSSS");
}
/**
* yyyy-MM-dd HH:mm:ss
*
* @return
*/
public static String getDateFormatMillisWithSecond() {
return getDateStr("yyyy-MM-dd HH:mm:ss");
}
/**
* yyyyMMdd
*
* @return
*/
public static String getDateFormatDay() {
return getDateStr("yyyyMMdd");
}
public static String getDateStr(String format) {
return DateTime.now().toString(format);
}
public static long getMillis() {
return DateTime.now().getMillis();
}
public static long betweenMillis(DateTime startTime, DateTime endTime) {
if (startTime == null || endTime == null) {
return 0;
}
return endTime.getMillis() - startTime.getMillis();
}
public static long betweenSecond(String startTime, String endTime) {
if (startTime == null || endTime == null) {
return 0;
}
DateTime s1 = DateTime.parse(startTime, DateTimeFormat.forPattern(TIME_FORMAT));
DateTime s0 = DateTime.parse(endTime, DateTimeFormat.forPattern(TIME_FORMAT));
return Math.abs(s1.getMillis() - s0.getMillis())/1000;
}
public static String formatMillis(String date, String pattern) {
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
return DateTime.parse(date, fmt).toString(TIME_MILLIS);
}
public static String formatMillis(long instant, String pattern) {
return new DateTime(instant).toString(TIME_MILLIS);
}
/**
* 把时间格式从yyyy-MM-dd'T'HH:mm:ss.SSS Z转成yyyy-MM-dd HH:mm:ss.SSS
* @param oldDate
* @return
* @throws ParseException
*/
public static String dealDateFormat(String oldDate) throws ParseException {
Date date1 = null;
DateFormat df2 = null;
try {
oldDate= oldDate.replace("Z", " UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
Date date = df.parse(oldDate);
SimpleDateFormat df1 = new SimpleDateFormat ("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
date1 = df1.parse(date.toString());
df2 = new SimpleDateFormat(TIME_MILLIS);
} catch (ParseException e) {
log.info("Approval Report process, message = {}, date = {}", "日期时间转换出错", oldDate);
e.printStackTrace();
throw e;
}
return df2.format(date1);
}
public static void main(String[] args) {
//System.out.println(betweenSecond("2019-09-17 00:00:00.111","2019-09-19 00:00:00"));
System.out.println("yyyy-MM-dd HH:mm:ss".length());
}
}
import java.io.Serializable;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
@Data
@Builder
@ToString
public class SysAccessErrorLog implements Serializable {
/**
*
*/
private Integer id;
/**
* 用户id:已登录用户包含
*/
private String userId;
/**
* 用户单位code:登录用户会包含
*/
private String dwcode;
/**
* 客户ip
*/
private String clientIp;
/**
* http路径
*/
private String uri;
/**
* 功能
*/
private String func;
/**
* 功能说明
*/
private String funcDesc;
/**
* 类、方法名称
*/
private String classSlg;
/**
* 日志记录时间
*/
private String logTime;
/**
* 请求开始时间(毫秒数)
*/
private String requestTime;
/**
* 请求结束时间(毫秒数)
*/
private String responseTime;
/**
* 消耗时间(毫秒数)
*/
private String estTime;
/**
* 请求参数信息 json
*/
private String requestParams;
/**
* 异常堆栈信息
*/
private String errStackTrace;
/**
* s_t_log_access_error
*/
private static final long serialVersionUID = 1L;
}
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
@Data
@Builder
@ToString
public class SysAccessLog {
/**
*
*/
private Integer id;
/**
* 用户id:已登录用户包含
*/
private String userId;
/**
* 用户单位code:登录用户会包含
*/
private String dwcode;
/**
* 客户ip
*/
private String clientIp;
/**
* http路径
*/
private String uri;
/**
* 功能
*/
private String func;
/**
* 功能说明
*/
private String funcDesc;
/**
* 类、方法名称
*/
private String classSlg;
/**
* 请求开始时间、结束时间、耗时
*/
private String requestTime;
private String responseTime;
private String estTime;
/**
* 日志记录时间
*/
private String logTime;
/**
* 请求参数信息 json
*/
private String requestParams;
/**
* 响应信息
*/
private String responseBody;
}
import cn.id5.entity.sys.SysAccessErrorLog;
public interface SysAccessErrorLogMapper {
int insert(SysAccessErrorLog record);
}
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import cn.id5.annotation.OperationLog;
import cn.id5.commons.codec.text.JsonCodec;
import cn.id5.commons.util.DateUtils;
import cn.id5.entity.sys.SysAccessLog;
import cn.id5.service.bean.LoginUserInfo;
import cn.id5.service.constants.BizConstants;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BaseAopAspect {
protected static final String LOG_START_TIME = "X-LOG-StartTime";
public SysAccessLog joinPointArgs(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
LoginUserInfo currUser = (LoginUserInfo) request.getAttribute(BizConstants.CURR_USER);
String userId = currUser == null ? null : currUser.getUserId();
String dwcode = currUser == null ? null : currUser.getDwcode();
log.debug("<curr login user> currUser = {} ", currUser);
// 设置ip
String ipAddress = request.getRemoteAddr();
// 设置当前登录用户的用户名和id
// 设置方法
String simpleName = joinPoint.getSignature().getDeclaringType().getSimpleName();
String methodName = joinPoint.getSignature().getName();
String function = simpleName + "." + methodName;
String uri = request.getRequestURI();
// 设置参数
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Class<?>[] paramters = methodSignature.getParameterTypes();
String[] parameterNames = methodSignature.getParameterNames();
OperationLog opl = methodSignature.getMethod().getAnnotation(OperationLog.class);
if (opl != null) {
log.debug("opl = {} ", opl);
}
log.debug("func = {} ", opl.func().func());
log.debug("func.msg = {} ", opl.func().desc());
log.debug("uri = {} ", uri);
log.debug("ip = {} ", ipAddress);
log.debug("simpleName = {} ", simpleName);
log.debug("methodName = {} ", methodName);
log.debug("function = {} ", function);
Map<String, Object> requestParams = new HashMap<>();
if (null != args) {
for (int i = 0; i < args.length; i++) {
if (paramters[i] == HttpServletRequest.class) {
continue;
}
if (paramters[i] == HttpServletResponse.class) {
continue;
}
log.debug("args[{}] {} = {} ", i, parameterNames[i], args[i]);
requestParams.put(parameterNames[i], args[i]);
}
}
log.debug("params = {} ", requestParams);
long startTime = (long) request.getAttribute(LOG_START_TIME);
long endTime = System.currentTimeMillis();
return SysAccessLog.builder()
.userId(userId)
.dwcode(dwcode)
.clientIp(ipAddress)
.uri(uri)
.func(opl.func().func())
.funcDesc(opl.func().desc())
.classSlg(function)
.logTime(DateUtils.getDateFormatMillisWithSplit())
.requestTime(String.valueOf(startTime))
.responseTime(String.valueOf(endTime))
.estTime(String.valueOf(endTime - startTime))
.requestParams(JsonCodec.toJson(requestParams))
.build();
}
}
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JsonCodec {
private static final Gson gsonPretty = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
private static final Gson gson = new GsonBuilder().serializeNulls().create();
private static final Gson gsonExpose = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().serializeNulls().create();
public static String toJson(Object obj) {
return gson.toJson(obj);
}
public static String toJsonExpose(Object obj) {
return gsonExpose.toJson(obj);
}
public static String toJsonPretty(Object obj) {
return gsonPretty.toJson(obj);
}
public static <T> T fromJson(String json, Class<T> classOfT) {
return gson.fromJson(json, classOfT);
}
public static <T> T fromJson(String json, Type type) {
return gson.fromJson(json, type);
}
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
OperationLogFunc func();
}