当前位置: 首页 > news >正文

java实现日志记录-注解方式

系统日志

在实际开发中,对于某些关键业务,我们通常需要记录该操作的内容,一个操作调一次记录方法,每次还得去收集参数等等,会造成大量代码重复。 我们希望代码中只有业务相关的操作,在项目中使用注解来完成此项功能。

在需要被记录日志的controller方法上添加@Log注解,使用方法如下:

@PostMapping("/test")
@Log(title = "测试", businessType = BusinessType.OTHER)
public AjaxResult test() {

}

注解参数说明

参数类型默认值描述
titleString操作模块
businessTypeBusinessTypeOTHER操作功能(OTHER其他、INSERT新增、UPDATE修改、DELETE删除、GRANT授权、EXPORT导出、IMPORT导入、FORCE强退、GENCODE生成代码、CLEAN清空数据)
operatorTypeOperatorTypeMANAGE操作人类别(OTHER其他、MANAGE后台用户、MOBILE手机端用户)
isSaveRequestDatabooleantrue是否保存请求的参数
isSaveResponseDatabooleantrue是否保存响应的参数
excludeParamNamesString[]{}排除指定的请求参数
package com.yxsd.common.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.yxsd.common.enums.BusinessType;
import com.yxsd.common.enums.OperatorType;/*** 自定义操作日志记录注解* * @author **/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{/*** 模块*/public String title() default "";/*** 功能*/public BusinessType businessType() default BusinessType.OTHER;/*** 操作人类别*/public OperatorType operatorType() default OperatorType.MANAGE;/*** 是否保存请求的参数*/public boolean isSaveRequestData() default true;/*** 是否保存响应的参数*/public boolean isSaveResponseData() default true;/*** 排除指定的请求参数*/public String[] excludeParamNames() default {};
}

 

package com.yxsd.common.enums;/*** 业务操作类型* * @author liu*/
public enum BusinessType
{/*** 其它*/OTHER,/*** 新增*/INSERT,/*** 修改*/UPDATE,/*** 删除*/DELETE,/*** 授权*/GRANT,/*** 导出*/EXPORT,/*** 导入*/IMPORT,/*** 强退*/FORCE,/*** 生成代码*/GENCODE,/*** 清空数据*/CLEAN,
}

 切面

package com.yxsd.framework.aspectj;import java.util.Collection;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
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.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson2.JSON;
import com.yxsd.common.annotation.Log;
import com.yxsd.common.core.domain.entity.SysUser;
import com.yxsd.common.core.domain.model.LoginUser;
import com.yxsd.common.enums.BusinessStatus;
import com.yxsd.common.enums.HttpMethod;
import com.yxsd.common.filter.PropertyPreExcludeFilter;
import com.yxsd.common.utils.SecurityUtils;
import com.yxsd.common.utils.ServletUtils;
import com.yxsd.common.utils.StringUtils;
import com.yxsd.common.utils.ip.IpUtils;
import com.yxsd.framework.manager.AsyncManager;
import com.yxsd.framework.manager.factory.AsyncFactory;
import com.yxsd.system.domain.SysOperLog;/*** 操作日志记录处理* * @author liu*/
@Aspect
@Component
public class LogAspect
{private static final Logger log = LoggerFactory.getLogger(LogAspect.class);/** 排除敏感属性字段 */public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };/** 计算操作消耗时间 */private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");/*** 处理请求前执行*/@Before(value = "@annotation(controllerLog)")public void boBefore(JoinPoint joinPoint, Log controllerLog){TIME_THREADLOCAL.set(System.currentTimeMillis());}/*** 处理完请求后执行** @param joinPoint 切点*/@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult){handleLog(joinPoint, controllerLog, null, jsonResult);}/*** 拦截异常操作* * @param joinPoint 切点* @param e 异常*/@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e){handleLog(joinPoint, controllerLog, e, null);}protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult){try{// 获取当前的用户LoginUser loginUser = SecurityUtils.getLoginUser();// *========数据库日志=========*//SysOperLog operLog = new SysOperLog();operLog.setStatus(BusinessStatus.SUCCESS.ordinal());// 请求的地址String ip = IpUtils.getIpAddr();operLog.setOperIp(ip);operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));if (loginUser != null){operLog.setOperName(loginUser.getUsername());SysUser currentUser = loginUser.getUser();if (StringUtils.isNotNull(currentUser) && StringUtils.isNotNull(currentUser.getDept())){operLog.setDeptName(currentUser.getDept().getDeptName());}}if (e != null){operLog.setStatus(BusinessStatus.FAIL.ordinal());operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));}// 设置方法名称String className = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();operLog.setMethod(className + "." + methodName + "()");// 设置请求方式operLog.setRequestMethod(ServletUtils.getRequest().getMethod());// 处理设置注解上的参数getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);// 设置消耗时间operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());// 保存数据库AsyncManager.me().execute(AsyncFactory.recordOper(operLog));}catch (Exception exp){// 记录本地异常日志log.error("异常信息:{}", exp.getMessage());exp.printStackTrace();}finally{TIME_THREADLOCAL.remove();}}/*** 获取注解中对方法的描述信息 用于Controller层注解* * @param log 日志* @param operLog 操作日志* @throws Exception*/public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception{// 设置action动作operLog.setBusinessType(log.businessType().ordinal());// 设置标题operLog.setTitle(log.title());// 设置操作人类别operLog.setOperatorType(log.operatorType().ordinal());// 是否需要保存request,参数和值if (log.isSaveRequestData()){// 获取参数的信息,传入到数据库中。setRequestValue(joinPoint, operLog, log.excludeParamNames());}// 是否需要保存response,参数和值if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)){operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));}}/*** 获取请求的参数,放到log中* * @param operLog 操作日志* @throws Exception 异常*/private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception{Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());String requestMethod = operLog.getRequestMethod();if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())){String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);operLog.setOperParam(StringUtils.substring(params, 0, 2000));}else{operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));}}/*** 参数拼装*/private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames){String params = "";if (paramsArray != null && paramsArray.length > 0){for (Object o : paramsArray){if (StringUtils.isNotNull(o) && !isFilterObject(o)){try{String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));params += jsonObj.toString() + " ";}catch (Exception e){}}}}return params.trim();}/*** 忽略敏感属性*/public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames){return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));}/*** 判断是否需要过滤的对象。* * @param o 对象信息。* @return 如果是需要过滤的对象,则返回true;否则返回false。*/@SuppressWarnings("rawtypes")public 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;}
}
package com.yxsd.system.domain;import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yxsd.common.annotation.Excel;
import com.yxsd.common.annotation.Excel.ColumnType;
import com.yxsd.common.core.domain.BaseEntity;/*** 操作日志记录表 oper_log* * @author liu*/
public class SysOperLog extends BaseEntity
{private static final long serialVersionUID = 1L;/** 日志主键 */@Excel(name = "操作序号", cellType = ColumnType.NUMERIC)private Long operId;/** 操作模块 */@Excel(name = "操作模块")private String title;/** 业务类型(0其它 1新增 2修改 3删除) */@Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据")private Integer businessType;/** 业务类型数组 */private Integer[] businessTypes;/** 请求方法 */@Excel(name = "请求方法")private String method;/** 请求方式 */@Excel(name = "请求方式")private String requestMethod;/** 操作类别(0其它 1后台用户 2手机端用户) */@Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户")private Integer operatorType;/** 操作人员 */@Excel(name = "操作人员")private String operName;/** 部门名称 */@Excel(name = "部门名称")private String deptName;/** 请求url */@Excel(name = "请求地址")private String operUrl;/** 操作地址 */@Excel(name = "操作地址")private String operIp;/** 操作地点 */@Excel(name = "操作地点")private String operLocation;/** 请求参数 */@Excel(name = "请求参数")private String operParam;/** 返回参数 */@Excel(name = "返回参数")private String jsonResult;/** 操作状态(0正常 1异常) */@Excel(name = "状态", readConverterExp = "0=正常,1=异常")private Integer status;/** 错误消息 */@Excel(name = "错误消息")private String errorMsg;/** 操作时间 */@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")private Date operTime;/** 消耗时间 */@Excel(name = "消耗时间", suffix = "毫秒")private Long costTime;public Long getOperId(){return operId;}public void setOperId(Long operId){this.operId = operId;}public String getTitle(){return title;}public void setTitle(String title){this.title = title;}public Integer getBusinessType(){return businessType;}public void setBusinessType(Integer businessType){this.businessType = businessType;}public Integer[] getBusinessTypes(){return businessTypes;}public void setBusinessTypes(Integer[] businessTypes){this.businessTypes = businessTypes;}public String getMethod(){return method;}public void setMethod(String method){this.method = method;}public String getRequestMethod(){return requestMethod;}public void setRequestMethod(String requestMethod){this.requestMethod = requestMethod;}public Integer getOperatorType(){return operatorType;}public void setOperatorType(Integer operatorType){this.operatorType = operatorType;}public String getOperName(){return operName;}public void setOperName(String operName){this.operName = operName;}public String getDeptName(){return deptName;}public void setDeptName(String deptName){this.deptName = deptName;}public String getOperUrl(){return operUrl;}public void setOperUrl(String operUrl){this.operUrl = operUrl;}public String getOperIp(){return operIp;}public void setOperIp(String operIp){this.operIp = operIp;}public String getOperLocation(){return operLocation;}public void setOperLocation(String operLocation){this.operLocation = operLocation;}public String getOperParam(){return operParam;}public void setOperParam(String operParam){this.operParam = operParam;}public String getJsonResult(){return jsonResult;}public void setJsonResult(String jsonResult){this.jsonResult = jsonResult;}public Integer getStatus(){return status;}public void setStatus(Integer status){this.status = status;}public String getErrorMsg(){return errorMsg;}public void setErrorMsg(String errorMsg){this.errorMsg = errorMsg;}public Date getOperTime(){return operTime;}public void setOperTime(Date operTime){this.operTime = operTime;}public Long getCostTime(){return costTime;}public void setCostTime(Long costTime){this.costTime = costTime;}
}

 

package com.yxsd.common.enums;/*** 操作状态* * @author liu**/
public enum BusinessStatus
{/*** 成功*/SUCCESS,/*** 失败*/FAIL,
}

 

package com.yxsd.common.utils.ip;import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import com.yxsd.common.utils.ServletUtils;
import com.yxsd.common.utils.StringUtils;/*** 获取IP方法* * @author liu*/
public class IpUtils
{public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";// 匹配 ippublic final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";// 匹配网段public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";/*** 获取客户端IP* * @return IP地址*/public static String getIpAddr(){return getIpAddr(ServletUtils.getRequest());}/*** 获取客户端IP* * @param request 请求对象* @return IP地址*/public static String getIpAddr(HttpServletRequest request){if (request == null){return "unknown";}String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getHeader("X-Forwarded-For");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getHeader("X-Real-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getRemoteAddr();}return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);}/*** 检查是否为内部IP地址* * @param ip IP地址* @return 结果*/public static boolean internalIp(String ip){byte[] addr = textToNumericFormatV4(ip);return internalIp(addr) || "127.0.0.1".equals(ip);}/*** 检查是否为内部IP地址* * @param addr byte地址* @return 结果*/private static boolean internalIp(byte[] addr){if (StringUtils.isNull(addr) || addr.length < 2){return true;}final byte b0 = addr[0];final byte b1 = addr[1];// 10.x.x.x/8final byte SECTION_1 = 0x0A;// 172.16.x.x/12final byte SECTION_2 = (byte) 0xAC;final byte SECTION_3 = (byte) 0x10;final byte SECTION_4 = (byte) 0x1F;// 192.168.x.x/16final byte SECTION_5 = (byte) 0xC0;final byte SECTION_6 = (byte) 0xA8;switch (b0){case SECTION_1:return true;case SECTION_2:if (b1 >= SECTION_3 && b1 <= SECTION_4){return true;}case SECTION_5:switch (b1){case SECTION_6:return true;}default:return false;}}/*** 将IPv4地址转换成字节* * @param text IPv4地址* @return byte 字节*/public static byte[] textToNumericFormatV4(String text){if (text.length() == 0){return null;}byte[] bytes = new byte[4];String[] elements = text.split("\\.", -1);try{long l;int i;switch (elements.length){case 1:l = Long.parseLong(elements[0]);if ((l < 0L) || (l > 4294967295L)){return null;}bytes[0] = (byte) (int) (l >> 24 & 0xFF);bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);bytes[3] = (byte) (int) (l & 0xFF);break;case 2:l = Integer.parseInt(elements[0]);if ((l < 0L) || (l > 255L)){return null;}bytes[0] = (byte) (int) (l & 0xFF);l = Integer.parseInt(elements[1]);if ((l < 0L) || (l > 16777215L)){return null;}bytes[1] = (byte) (int) (l >> 16 & 0xFF);bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);bytes[3] = (byte) (int) (l & 0xFF);break;case 3:for (i = 0; i < 2; ++i){l = Integer.parseInt(elements[i]);if ((l < 0L) || (l > 255L)){return null;}bytes[i] = (byte) (int) (l & 0xFF);}l = Integer.parseInt(elements[2]);if ((l < 0L) || (l > 65535L)){return null;}bytes[2] = (byte) (int) (l >> 8 & 0xFF);bytes[3] = (byte) (int) (l & 0xFF);break;case 4:for (i = 0; i < 4; ++i){l = Integer.parseInt(elements[i]);if ((l < 0L) || (l > 255L)){return null;}bytes[i] = (byte) (int) (l & 0xFF);}break;default:return null;}}catch (NumberFormatException e){return null;}return bytes;}/*** 获取IP地址* * @return 本地IP地址*/public static String getHostIp(){try{return InetAddress.getLocalHost().getHostAddress();}catch (UnknownHostException e){}return "127.0.0.1";}/*** 获取主机名* * @return 本地主机名*/public static String getHostName(){try{return InetAddress.getLocalHost().getHostName();}catch (UnknownHostException e){}return "未知";}/*** 从多级反向代理中获得第一个非unknown IP地址** @param ip 获得的IP地址* @return 第一个非unknown IP地址*/public static String getMultistageReverseProxyIp(String ip){// 多级反向代理检测if (ip != null && ip.indexOf(",") > 0){final String[] ips = ip.trim().split(",");for (String subIp : ips){if (false == isUnknown(subIp)){ip = subIp;break;}}}return StringUtils.substring(ip, 0, 255);}/*** 检测给定字符串是否为未知,多用于检测HTTP请求相关** @param checkString 被检测的字符串* @return 是否未知*/public static boolean isUnknown(String checkString){return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);}/*** 是否为IP*/public static boolean isIP(String ip){return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);}/*** 是否为IP,或 *为间隔的通配符地址*/public static boolean isIpWildCard(String ip){return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);}/*** 检测参数是否在ip通配符里*/public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip){String[] s1 = ipWildCard.split("\\.");String[] s2 = ip.split("\\.");boolean isMatchedSeg = true;for (int i = 0; i < s1.length && !s1[i].equals("*"); i++){if (!s1[i].equals(s2[i])){isMatchedSeg = false;break;}}return isMatchedSeg;}/*** 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串*/public static boolean isIPSegment(String ipSeg){return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);}/*** 判断ip是否在指定网段中*/public static boolean ipIsInNetNoCheck(String iparea, String ip){int idx = iparea.indexOf('-');String[] sips = iparea.substring(0, idx).split("\\.");String[] sipe = iparea.substring(idx + 1).split("\\.");String[] sipt = ip.split("\\.");long ips = 0L, ipe = 0L, ipt = 0L;for (int i = 0; i < 4; ++i){ips = ips << 8 | Integer.parseInt(sips[i]);ipe = ipe << 8 | Integer.parseInt(sipe[i]);ipt = ipt << 8 | Integer.parseInt(sipt[i]);}if (ips > ipe){long t = ips;ips = ipe;ipe = t;}return ips <= ipt && ipt <= ipe;}/*** 校验ip是否符合过滤串规则* * @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99`* @param ip 校验IP地址* @return boolean 结果*/public static boolean isMatchedIp(String filter, String ip){if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip)){return false;}String[] ips = filter.split(";");for (String iStr : ips){if (isIP(iStr) && iStr.equals(ip)){return true;}else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip)){return true;}else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip)){return true;}}return false;}
}

 

 

package com.yxsd.common.utils.ip;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.yxsd.common.config.AppConfig;
import com.yxsd.common.constant.Constants;
import com.yxsd.common.utils.StringUtils;
import com.yxsd.common.utils.http.HttpUtils;/*** 获取地址类* * @author liu*/
public class AddressUtils
{private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);// IP地址查询public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";// 未知地址public static final String UNKNOWN = "XX XX";public static String getRealAddressByIP(String ip){// 内网不查询if (IpUtils.internalIp(ip)){return "内网IP";}if (AppConfig.isAddressEnabled()){try{String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);if (StringUtils.isEmpty(rspStr)){log.error("获取地理位置异常 {}", ip);return UNKNOWN;}JSONObject obj = JSON.parseObject(rspStr);String region = obj.getString("pro");String city = obj.getString("city");return String.format("%s %s", region, city);}catch (Exception e){log.error("获取地理位置异常 {}", ip);}}return UNKNOWN;}
}

 

 

package com.yxsd.framework.manager;import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.yxsd.common.utils.Threads;
import com.yxsd.common.utils.spring.SpringUtils;/*** 异步任务管理器* * @author liu*/
public class AsyncManager
{/*** 操作延迟10毫秒*/private final int OPERATE_DELAY_TIME = 10;/*** 异步操作任务调度线程池*/private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");/*** 单例模式*/private AsyncManager(){}private static AsyncManager me = new AsyncManager();public static AsyncManager me(){return me;}/*** 执行任务* * @param task 任务*/public void execute(TimerTask task){executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);}/*** 停止任务线程池*/public void shutdown(){Threads.shutdownAndAwaitTermination(executor);}
}
package com.yxsd.framework.manager.factory;import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yxsd.common.constant.Constants;
import com.yxsd.common.utils.LogUtils;
import com.yxsd.common.utils.ServletUtils;
import com.yxsd.common.utils.StringUtils;
import com.yxsd.common.utils.ip.AddressUtils;
import com.yxsd.common.utils.ip.IpUtils;
import com.yxsd.common.utils.spring.SpringUtils;
import com.yxsd.system.domain.SysLogininfor;
import com.yxsd.system.domain.SysOperLog;
import com.yxsd.system.service.ISysLogininforService;
import com.yxsd.system.service.ISysOperLogService;
import eu.bitwalker.useragentutils.UserAgent;/*** 异步工厂(产生任务用)* * @author liu*/
public class AsyncFactory
{private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");/*** 操作日志记录* * @param operLog 操作日志信息* @return 任务task*/public static TimerTask recordOper(final SysOperLog operLog){return new TimerTask(){@Overridepublic void run(){
//业务保存 自己写ISysOperLogService  logService=SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
logService.save(operLog)}};}
}

 

http://www.lryc.cn/news/578882.html

相关文章:

  • 使用哪种语言的人更容易通过面试?
  • 【Web前端】优化轮播图展示(源代码)
  • (一)大语言模型的关键技术<-AI大模型构建
  • 360安全卫士占用5037端口(ADB端口)解决方案
  • Wps开放平台v5升级v7上传实体文件踩坑(Java使用restTemplate)
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的场景零售创新研究
  • Mac电脑 卸载工具 App Cleaner
  • Java 大视界 -- Java 大数据在智能医疗健康管理中的慢性病风险预测与个性化干预(330)
  • 带GPU启动 Docker 容器
  • FAISS 简介及其与 GPT 的对接(RAG)
  • [CS创世SD NAND征文] 精准控制的坚固基石:CS创世SD NAND在华大HC32F4A0运动控制卡中的高可靠应用
  • 7月2日星期三今日早报简报微语报早读
  • Java AQS(AbstractQueuedSynchronizer)详解
  • 【前端】基础 - HTML基础标签和样式设置
  • Baumer工业相机堡盟工业相机如何实现高精度的硬件同步触发
  • 公用LCU屏的功能、应用场景
  • 微信小程序使用wx.chooseImage上传图片时进行压缩,并添加时间水印
  • 微信小程序入门实例_____打造你的专属单词速记小程序
  • PH热榜 | 2025-07-02
  • zabbix批量生成监控项教程!
  • Benchmarking in Go
  • 利器:NPM和YARN及其他
  • SQL Server 再进阶:类型多样性分析与时间维度扩展(第三课)
  • 解锁医疗AI密码:医疗人工智能专业大学四年学习路径
  • android核心技术摘要
  • 数论基础知识和模板
  • 香港券商交易系统开发与解决方案全景报告:云原生、跨境协同与高性能架构的创新实践
  • 【unitrix】 4.13 类型级加一计算(add1.rs)
  • 【GHS】Green Hills软件MULTI-IDE的安装教程
  • 【AI落地应用实战】AIGC赋能职场PPT汇报:从效率工具到辅助优化