精华内容
下载资源
问答
  • 用户操作日志.zip

    2019-09-11 11:25:02
    java aop 用户操作日志 在每个action\controller 上加上注解 就可以了 例如 @Log(“添加用户”) 日志包含(请求时间,请求ip,请求类名 ,请求方法,请求参数,请求异常)
  • java记录日志

    2014-01-22 10:26:43
    java多线程异步的记录日志(可以精确到具体哪个字段发生了改变,可以记录到提交的所有参数,也可以将抛出的异常和提交参数记录到文件)
  • JAVA记录操作日志步骤

    万次阅读 多人点赞 2019-08-06 14:01:55
    说明 系统日志不论是在日常的管理还是维护中都会起到很大的作用,但是在日志的记录中通常会存在很多的...记录出参入参这是日志记录最好操作的一部分,而这里会存在一定的重复性,因为每个请求都需要记录,这是重复操作,...

    项目地址:https://gitee.com/Selegant/logs-demo.git

    说明

    系统日志不论是在日常的管理还是维护中都会起到很大的作用,但是在日志的记录中通常会存在很多的问题

    1. 日志记录的不规范性
    2. 日志记录的重复性
    3. 日志记录的难分类

    目前日志主要记录的有三方面

    1. 请求的入参,出参
    2. 关于业务上的操作
    3. 异常日常日志的打印

    解决方案

    1.记录请求的出参入参

    记录出参入参这是日志记录最好操作的一部分,而这里会存在一定的重复性,因为每个请求都需要记录,这是重复操作,完全可以使用Spring AOP进行入参和出参的记录

    import org.apache.log4j.Logger;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.core.annotation.Order;
    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.Arrays;
    
    /**
     * Web层日志切面
     */
    @Aspect    //这里使用@Aspect注解方式设置AOP
    @Order(5)  //值越小,越先加载
    @Component
    public class WebLogAspect {
    
        private Logger logger = Logger.getLogger(getClass());
    
        ThreadLocal<Long> startTime = new ThreadLocal<>();
    	
    	//这里@Pointcut设置切点可以设置为Controller层的地址
        @Pointcut("execution(public * com.training..*.*Controller(..))")
        public void webLog(){}
    
    	//@Before指在切点方法之前执行,也就是在Controller层方法执行之前执行,这里可以通过JoinPoint获取一些有关方法的信息,在这里也可以修改参数的值
        
    	//@Before()括号里设置的是切点方法的名称
    	@Before("webLog()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            startTime.set(System.currentTimeMillis());
    
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            // 记录下请求内容
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    
        }
    
        @AfterReturning(returning = "ret", pointcut = "webLog()")
        public void doAfterReturning(Object ret) throws Throwable {
            // 处理完请求,返回内容
            logger.info("RESPONSE : " + ret);
            logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
        }
    
    }
    

    2.记录操作日志

    在系统中可能会有很多的增删改查或是会涉及到一些业务操作,这时候我们需要记录一下操作的入口,在此还可以记录下操作的类型,或是业务的名称.不过在就操作日志前需要构建日志的基础部件

    日志对象

    import java.util.Date;
    
    /**
     * 操作日志
     */
    public class OperationLog extends Base {
    
        private static final long serialVersionUID = 1L;
    
        /**
         * 日志类型
         */
        private String  logtype;
        /**
         * 日志名称
         */
        private String  logname;
        /**
         * 用户id
         */
        private Integer userid;
        /**
         * 类名称
         */
        private String  classname;
        /**
         * 方法名称
         */
        private String  method;
        /**
         * 创建时间
         */
        private Date    createtime;
        /**
         * 是否成功
         */
        private String  succeed;
        /**
         * 备注
         */
        private String  message;
    
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getLogtype() {
            return logtype;
        }
    
        public void setLogtype(String logtype) {
            this.logtype = logtype;
        }
    
        public String getLogname() {
            return logname;
        }
    
        public void setLogname(String logname) {
            this.logname = logname;
        }
    
        public Integer getUserid() {
            return userid;
        }
    
        public void setUserid(Integer userid) {
            this.userid = userid;
        }
    
        public String getClassname() {
            return classname;
        }
    
        public void setClassname(String classname) {
            this.classname = classname;
        }
    
        public String getMethod() {
            return method;
        }
    
        public void setMethod(String method) {
            this.method = method;
        }
    
        public Date getCreatetime() {
            return createtime;
        }
    
        public void setCreatetime(Date createtime) {
            this.createtime = createtime;
        }
    
        public String getSucceed() {
            return succeed;
        }
    
        public void setSucceed(String succeed) {
            this.succeed = succeed;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

    日志对象创建工厂

    import com.stylefeng.guns.common.constant.state.LogSucceed;
    import com.stylefeng.guns.common.constant.state.LogType;
    import com.stylefeng.guns.common.persistence.model.LoginLog;
    import com.stylefeng.guns.common.persistence.model.OperationLog;
    
    import java.util.Date;
    
    /**
     * 日志对象创建工厂
     */
    public class LogFactory {
    
        /**
         * 创建操作日志
         */
        public static OperationLog createOperationLog(LogType logType, Integer userId, String bussinessName, String clazzName, String methodName, String msg, LogSucceed succeed) {
            OperationLog operationLog = new OperationLog();
            operationLog.setLogtype(logType.getMessage());
            operationLog.setLogname(bussinessName);
            operationLog.setUserid(userId);
            operationLog.setClassname(clazzName);
            operationLog.setMethod(methodName);
            operationLog.setCreatetime(new Date());
            operationLog.setSucceed(succeed.getMessage());
            operationLog.setMessage(msg);
            return operationLog;
        }
    
        /**
         * 创建登录日志
         */
        public static LoginLog createLoginLog(LogType logType, Integer userId, String msg,String ip) {
            LoginLog loginLog = new LoginLog();
            loginLog.setLogname(logType.getMessage());
            loginLog.setUserid(userId);
            loginLog.setCreatetime(new Date());
            loginLog.setSucceed(LogSucceed.SUCCESS.getMessage());
            loginLog.setIp(ip);
            loginLog.setMessage(msg);
            return loginLog;
        }
    }
    

    日志任务创建工厂

    日志任务创建工厂的作用是将日志记录存储到数据库中

    import com.stylefeng.guns.common.constant.state.LogSucceed;
    import com.stylefeng.guns.common.constant.state.LogType;
    import com.stylefeng.guns.common.persistence.dao.LoginLogMapper;
    import com.stylefeng.guns.common.persistence.dao.OperationLogMapper;
    import com.stylefeng.guns.common.persistence.model.LoginLog;
    import com.stylefeng.guns.common.persistence.model.OperationLog;
    import com.stylefeng.guns.core.log.LogManager;
    import com.stylefeng.guns.core.util.SpringContextHolder;
    import com.stylefeng.guns.core.util.ToolUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.TimerTask;
    
    /**
     * 日志操作任务创建工厂
     */
    public class LogTaskFactory {
    
        private static Logger logger  = LoggerFactory.getLogger(LogManager.class);
    	//LoginLogMapper记录登录登出日志
        private static LoginLogMapper loginLogMapper = SpringContextHolder.getBean(LoginLogMapper.class);
    	//OperationLogMapper记录操作日志	    
    	private static OperationLogMapper operationLogMapper = SpringContextHolder.getBean(OperationLogMapper.class);
    
        public static TimerTask loginLog(final Integer userId, final String ip) {
            return new TimerTask() {
                @Override
                public void run() {
                    try {
                        LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null, ip);
                        loginLogMapper.insert(loginLog);
                    } catch (Exception e) {
                        logger.error("创建登录日志异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask loginLog(final String username, final String msg, final String ip) {
            return new TimerTask() {
                @Override
                public void run() {
                    LoginLog loginLog = LogFactory.createLoginLog(
                            LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg, ip);
                    try {
                        loginLogMapper.insert(loginLog);
                    } catch (Exception e) {
                        logger.error("创建登录失败异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask exitLog(final Integer userId, final String ip) {
            return new TimerTask() {
                @Override
                public void run() {
                    LoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null,ip);
                    try {
                        loginLogMapper.insert(loginLog);
                    } catch (Exception e) {
                        logger.error("创建退出日志异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask bussinessLog(final Integer userId, final String bussinessName, final String clazzName, final String methodName, final String msg) {
            return new TimerTask() {
                @Override
                public void run() {
                    OperationLog operationLog = LogFactory.createOperationLog(
                            LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS);
                    try {
                        operationLogMapper.insert(operationLog);
                    } catch (Exception e) {
                        logger.error("创建业务日志异常!", e);
                    }
                }
            };
        }
    
        public static TimerTask exceptionLog(final Integer userId, final Exception exception) {
            return new TimerTask() {
                @Override
                public void run() {
                    String msg = ToolUtil.getExceptionMsg(exception);
                    OperationLog operationLog = LogFactory.createOperationLog(
                            LogType.EXCEPTION, userId, "", null, null, msg, LogSucceed.FAIL);
                    try {
                        operationLogMapper.insert(operationLog);
                    } catch (Exception e) {
                        logger.error("创建异常日志异常!", e);
                    }
                }
            };
        }
    }
    

    记录操作日志

    这一步是最关键的一环

    原理:通过自定义的注解@BussinessLog(可以任意命名),里面定义了业务的名称,被修改的实体的唯一标识,字典(用于查找key的中文名称和字段的中文名称),然后通过AOP,拦截所有添加了@BussinessLog注解的方法,解析其注解里面的属性,然后记录到对应的操作日志表中,完成操作日志的记录

    @BussinessLog

    import java.lang.annotation.*;
    
    /**
     * 标记需要做业务日志的方法
     */
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface BussinessLog {
    
        /**
         * 业务的名称,例如:"修改菜单"
         */
        String value() default "";
    
        /**
         * 被修改的实体的唯一标识,例如:菜单实体的唯一标识为"id"
         */
        String key() default "id";
    
        /**
         * 字典(用于查找key的中文名称和字段的中文名称)
         */
        String dict() default "SystemDict";
    }
    

    @BussinessLog注解拦截AOP

    import com.stylefeng.guns.common.annotion.log.BussinessLog;
    import com.stylefeng.guns.common.constant.dictmap.base.AbstractDictMap;
    import com.stylefeng.guns.common.constant.dictmap.factory.DictMapFactory;
    import com.stylefeng.guns.core.log.LogManager;
    import com.stylefeng.guns.core.log.LogObjectHolder;
    import com.stylefeng.guns.core.log.factory.LogTaskFactory;
    import com.stylefeng.guns.core.shiro.ShiroKit;
    import com.stylefeng.guns.core.shiro.ShiroUser;
    import com.stylefeng.guns.core.support.HttpKit;
    import com.stylefeng.guns.core.util.Contrast;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Map;
    
    /**
     * 日志记录
     */
    @Aspect
    @Component
    public class LogAop {
    
        private Logger log = LoggerFactory.getLogger(this.getClass());
    
        @Pointcut(value = "@annotation(com.stylefeng.guns.common.annotion.log.BussinessLog)")
        public void cutService() {
        }
    
        @Around("cutService()")
        public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {
    
            //先执行业务
            Object result = point.proceed();
    
            try {
                handle(point);
            } catch (Exception e) {
                log.error("日志记录出错!", e);
            }
    
            return result;
        }
    
        private void handle(ProceedingJoinPoint point) throws Exception {
    
            //获取拦截的方法名
            Signature sig = point.getSignature();
            MethodSignature msig = null;
            if (!(sig instanceof MethodSignature)) {
                throw new IllegalArgumentException("该注解只能用于方法");
            }
            msig = (MethodSignature) sig;
            Object target = point.getTarget();
            Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
            String methodName = currentMethod.getName();
    
            //如果当前用户未登录,不做日志
            ShiroUser user = ShiroKit.getUser();
            if (null == user) {
                return;
            }
    
            //获取拦截方法的参数
            String className = point.getTarget().getClass().getName();
            Object[] params = point.getArgs();
    
            //获取操作名称
            BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class);
            String bussinessName = annotation.value();
            String key = annotation.key();
            String dictClass = annotation.dict();
    
            StringBuilder sb = new StringBuilder();
            for (Object param : params) {
                sb.append(param);
                sb.append(" & ");
            }
    
            //如果涉及到修改,比对变化
            String msg;
            if (bussinessName.indexOf("修改") != -1 || bussinessName.indexOf("编辑") != -1) {
                Object obj1 = LogObjectHolder.me().get();
                Map<String, String> obj2 = HttpKit.getRequestParameters();
                msg = Contrast.contrastObj(dictClass, key, obj1, obj2);
            } else {
                Map<String, String> parameters = HttpKit.getRequestParameters();
                AbstractDictMap dictMap = DictMapFactory.createDictMap(dictClass);
                msg = Contrast.parseMutiKey(dictMap,key,parameters);
            }
    
            LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), bussinessName, className, methodName, msg));
        }
    }
    

    @BussinessLog使用实例

    /**
     * 新增字典
     @param dictValues 格式例如   "1:启用;2:禁用;3:冻结"
     */
    @BussinessLog(value = "添加字典记录", key = "dictName,dictValues", dict = com.stylefeng.guns.common.constant.Dict.DictMap)
    @RequestMapping(value = "/add")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object add(String dictName, String dictValues) {
        if (ToolUtil.isOneEmpty(dictName, dictValues)) {
            throw new BussinessException(BizExceptionEnum.REQUEST_NULL);
        }
        dictService.addDict(dictName, dictValues);
        return SUCCESS_TIP;
    }
    

    3.记录异常日志

    记录异常日志其实也是一个重复式的过程,这也可以通过统一的处理来记录异常抛出的日志

    import com.stylefeng.guns.common.constant.tips.ErrorTip;
    import com.stylefeng.guns.common.exception.BizExceptionEnum;
    import com.stylefeng.guns.common.exception.BussinessException;
    import com.stylefeng.guns.common.exception.InvalidKaptchaException;
    import com.stylefeng.guns.core.log.LogManager;
    import com.stylefeng.guns.core.log.factory.LogTaskFactory;
    import com.stylefeng.guns.core.shiro.ShiroKit;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.CredentialsException;
    import org.apache.shiro.authc.DisabledAccountException;
    import org.apache.shiro.session.InvalidSessionException;
    import org.apache.shiro.session.UnknownSessionException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.ResponseStatus;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.UndeclaredThrowableException;
    
    import static com.stylefeng.guns.core.support.HttpKit.getIp;
    import static com.stylefeng.guns.core.support.HttpKit.getRequest;
    
    /**
     * 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
     */
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        private Logger log = LoggerFactory.getLogger(this.getClass());
    
        /**
         * 拦截业务异常
         */
        @ExceptionHandler(BussinessException.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ResponseBody
        public ErrorTip notFount(BussinessException e) {
            LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
            getRequest().setAttribute("tip", e.getMessage());
            log.error("业务异常:", e);
            return new ErrorTip(e.getCode(), e.getMessage());
        }
    
        /**
         * 用户未登录
         */
        @ExceptionHandler(AuthenticationException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        public String unAuth(AuthenticationException e) {
            log.error("用户未登陆:", e);
            return "/login.html";
        }
    
        /**
         * 账号被冻结
         */
        @ExceptionHandler(DisabledAccountException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        public String accountLocked(DisabledAccountException e, Model model) {
            String username = getRequest().getParameter("username");
            LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号被冻结", getIp()));
            model.addAttribute("tips", "账号被冻结");
            return "/login.html";
        }
    
        /**
         * 账号密码错误
         */
        @ExceptionHandler(CredentialsException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        public String credentials(CredentialsException e, Model model) {
            String username = getRequest().getParameter("username");
            LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号密码错误", getIp()));
            model.addAttribute("tips", "账号密码错误");
            return "/login.html";
        }
    
        /**
         * 验证码错误
         */
        @ExceptionHandler(InvalidKaptchaException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String credentials(InvalidKaptchaException e, Model model) {
            String username = getRequest().getParameter("username");
            LogManager.me().executeLog(LogTaskFactory.loginLog(username, "验证码错误", getIp()));
            model.addAttribute("tips", "验证码错误");
            return "/login.html";
        }
    
        /**
         * 无权访问该资源
         */
        @ExceptionHandler(UndeclaredThrowableException.class)
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        @ResponseBody
        public ErrorTip credentials(UndeclaredThrowableException e) {
            getRequest().setAttribute("tip", "权限异常");
            log.error("权限异常!", e);
            return new ErrorTip(BizExceptionEnum.NO_PERMITION);
        }
    
        /**
         * 拦截未知的运行时异常
         */
        @ExceptionHandler(RuntimeException.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ResponseBody
        public ErrorTip notFount(RuntimeException e) {
            LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
            getRequest().setAttribute("tip", "服务器未知运行时异常");
            log.error("运行时异常:", e);
            return new ErrorTip(BizExceptionEnum.SERVER_ERROR);
        }
    
        /**
         * session失效的异常拦截
         */
        @ExceptionHandler(InvalidSessionException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String sessionTimeout(InvalidSessionException e, Model model, HttpServletRequest request, HttpServletResponse response) {
            model.addAttribute("tips", "session超时");
            assertAjax(request, response);
            return "/login.html";
        }
    
        /**
         * session异常
         */
        @ExceptionHandler(UnknownSessionException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String sessionTimeout(UnknownSessionException e, Model model, HttpServletRequest request, HttpServletResponse response) {
            model.addAttribute("tips", "session超时");
            assertAjax(request, response);
            return "/login.html";
        }
    
        private void assertAjax(HttpServletRequest request, HttpServletResponse response) {
            if (request.getHeader("x-requested-with") != null
                    && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                //如果是ajax请求响应头会有,x-requested-with
                response.setHeader("sessionstatus", "timeout");//在响应头设置session状态
            }
        }
    
    }
    

    项目地址:https://gitee.com/Selegant/logs-demo.git

    展开全文
  • java操作日志实现

    千次阅读 2019-07-25 11:04:46
    以下是基于springboot+springcloud实现的操作日志功能 第一步:定义日志注解SysLog /** * 操作日志注解 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ...

    以下是基于springboot+springcloud实现的操作日志功能

    第一步:定义日志注解SysLog

    /**
     * 操作日志注解
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface SysLog {
    
        /**
         * 日志描述
         */
        String desc() default "";
        
        /**
         * 日志操作类型
         */
        BusinessType businessType() default BusinessType.OTHER;
    
    }
    

    第二步:配置日志切面记录日志信息

    /**
     * 操作日志切面
     */
    @Slf4j
    @Aspect
    @Component
    public class WebLogAspect {
    
        @Autowired
        private LogFeignClient logFeignClient;
    
        /**
         * 日志 切面 自定义注解  切到任意方法
         */
        @Pointcut("@annotation(com.yuguo.aspect.SysLog)")
        public void webLog() {
    
        }
    
        @Before("webLog()")
        public void doBefore(JoinPoint joinPoint) {
            log.info("dobefore...");
        }
    
    
        @AfterReturning(returning = "ret", pointcut = "webLog()")
        public void doAfterReturning(JoinPoint joinPoint, Object ret) throws Throwable {
            // 处理完请求,返回内容
            log.info("doAfter save log ...");
            try {
                //获取请求数据
                Map<String, Object> logMap = getLogData(joinPoint);
                logFeignClient.saveLog(logMap);
            } catch (Exception e) {
                log.error("##########[WebLogAspect]catch exception, save log error!###########" + e.getMessage());
            }
        }
    
    
        //获取请求数据
        private Map<String, Object> getLogData(JoinPoint joinPoint) {
            Map<String, Object> logMap = new HashMap<String, Object>();
            try {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                        .getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                //日志描述  日志类型
                String methodName = joinPoint.getSignature().getName();
                Method method = currentMethod(joinPoint, methodName);
                SysLog sysLog = method.getAnnotation(SysLog.class);
                String eventDesc = sysLog.desc();
                BusinessType bType = sysLog.businessType();
                String eventType = BusinessType.getMsg(bType);
                logMap.put("eventDesc", eventDesc);
                logMap.put("eventType", eventType);
                // 请求地址
                String requestUrl = request.getRequestURL().toString();
                logMap.put("requestUrl", requestUrl);
                //客户端地址
                //String requestIp = request.getRemoteAddr();
                String clientIp = getClientIp (request);
                logMap.put("requestIp", clientIp);
                //操作者
                String operator = request.getRemoteUser();
                logMap.put("operator", operator);
                //请求参数
                String requestParam = null;
                Enumeration<String> enu = request.getParameterNames();
                while (enu.hasMoreElements()) {
                    String name = (String) enu.nextElement();
                    requestParam = requestParam + name + ":" + request.getParameter(name) + ",";
                    log.info("name【请求参数名】:{},value【请求参数值】:{}", name, request.getParameter(name));
                }
                //如果为空,就从请求体里面去获取
                if (StringUtils.isBlank(requestParam)) {
                    log.info("requestParam:" + requestParam + ",再从请求体中获取");
                    Object[] objects = joinPoint.getArgs();
                    requestParam = JSONObject.toJSONString(objects);
                }
                log.info("REQUEST_PARAM【请求参数】 : " + requestParam);
                logMap.put("requestParam", requestParam);
                // 测试另一种获取请求参数的方式:
        		String paramData = JSON.toJSONString(request.getParameterMap(),
        				SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
        		log.info("######测试得到的requestParam:"+paramData+"######");
            } catch (Exception e) {
                log.error("####[WebLogAspect]catch exception, getLogData log error! 组装数据错误 #####" + e.getMessage());
            }
            return logMap;
        }
    
        private Method currentMethod(JoinPoint joinPoint, String methodName) {
            Method[] methods = joinPoint.getTarget().getClass().getMethods();
            Method resultMethod = null;
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    resultMethod = method;
                    break;
                }
            }
            return resultMethod;
        }
        
        /**
         * 获取客户端ip地址
         * @param request
         * @return
         */
        public static String getClientIp(HttpServletRequest request)
        {
            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            // 多个路由时,取第一个非unknown的ip
            final String[] arr = ip.split(",");
            for (final String str : arr) {
                if (!"unknown".equalsIgnoreCase(str)) {
                    ip = str;
                    break;
                }
            }
            return ip;
        }
    
    }
    

    第三步:定义功能类型BusinessType

    /**
     * 日志操作类型
     */
    public enum BusinessType
    {
        /**
         * 其它
         */
        OTHER,
        /**
         * 新增
         */
        INSERT,
        /**
         * 修改
         */
        UPDATE,
        /**
         * 删除
         */
        DELETE,
        /**
         * 查询
         */
        SELECT,
        /**
         * 导出
         */
        EXPORT,
        /**
         * 导入
         */
        IMPORT;
    
        public static String getMsg(BusinessType type){
        	String result = null;
            switch (type) {
    		case INSERT:
    			result = "新增";
    			break;
    		case UPDATE:
    			result = "修改";
    			break;
    		case DELETE:
    			result = "删除";
    			break;
    		case SELECT:
    			result = "查询";
    			break;
    		case EXPORT:
    			result = "导出";
    			break;
    		case IMPORT:
    			result = "导入";
    			break;
    		case OTHER:
    			result = "其它";
    			break;
    		default:
    			break;
    		}
            return result;
        }
    }
    

    第四步:方法上添加日志注解@SysLog()

    	@PostMapping
    	@SysLog(desc = "新增用户", businessType = BusinessType.INSERT)
    	public Result add(User user){
    		...
        }
    
    展开全文
  • JAVA记录用户操作日志

    千次阅读 2021-02-27 16:19:03
    import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.te...

    import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Calendar; public class LogInfo {  private static String filepath = "C:\\log\\";  private static Calendar c = Calendar.getInstance();  private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  /**   * 记录日志文件   * @param file   * @param username   * @param ip   * @param dowhat   */  public static void saveLog(File file, String username,String ip,String dowhat){   BufferedWriter bw = null;   try {    bw = new BufferedWriter(new OutputStreamWriter(      new FileOutputStream(file, true)));    bw.write("用户 "+username+",ip为  "+ip+",进行了 "+dowhat+" 操作\n");    bw.flush();   } catch (FileNotFoundException e) {    System.out.println("文件未找到");   } catch (IOException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }   finally{    if(null!=bw){     try {      bw.close();     } catch (IOException e) {      System.out.println("流操作异常");     }    }   }  }    /**   * 根据时间创建日志文件   * @return   */  public static File createFile(){   //每天创建一个日志文件,名称为"2010-11-30.txt"   File file = null;   try {    file = new File(filepath+sdf.format(c.getTime())+".txt");    if(!file.exists()){     file.createNewFile();    }   } catch (Exception e) {    System.out.println("路径不存在");   }   return file;  }    public static void main(String[] args) {   File file = createFile();   saveLog(file, "windforce", "192.168.0.1", "更改密码");  } }

    展开全文
  • java实现日志操作记录

    千次阅读 2019-07-09 09:19:16
    import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URLDecoder; import java.sql.Timestamp; import java.text.SimpleDateFormat; ...
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.StringUtils;
    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.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import java.io.UnsupportedEncodingException;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.net.URLDecoder;
    import java.sql.Timestamp;
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.Objects;
    
    @Aspect
    @Component
    @Slf4j
    @Order(1)
    public class ThirdApiRequestLogAspect {
        ObjectMapper objectMapper = new ObjectMapper();
    
        @Resource
        private CrmOperationLogMapper operationLogMapper;
    
        public ThirdApiRequestLogAspect() {
            log.info("初始化接口日志切面类...");
        }
    
        @Pointcut("execution(public * com.arvato.service.goods.api.controller.*.*(..))")
        public void controllerInteceptor() {
        }
    
        @Around("controllerInteceptor()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Date start = new Date();
            try {
                //数据库对应的实体
                CrmOperationLog sysLog = new CrmOperationLog();
                SysLog syslog1 = method.getAnnotation(SysLog.class);
                if (syslog1 != null) {
                    //注解上的描述
                    sysLog.setModule(syslog1.MODULE());
                    sysLog.setMethod(syslog1.REMARK());
                }
                //请求的方法名
                String clazzName = joinPoint.getTarget().getClass().getName();
                Class<?> clazz = Class.forName(clazzName);
                String clazzSimpleName = clazz.getSimpleName();
                String methodName = signature.getName();
                sysLog.setOperationDesc(clazzSimpleName + "." + methodName);
    
                //请求的参数
                String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
                StringBuilder sb = null;
                if (Objects.nonNull(parameterNames)) {
                    sb = new StringBuilder();
                    for (int i = 0; i < parameterNames.length; i++) {
                        Object param = joinPoint.getArgs()[i] != null ? joinPoint.getArgs()[i] : "";
                        if (StringUtils.isNotEmpty(param.toString()) && !"request".equals(parameterNames[i]) && !"response".equals(parameterNames[i])
                                && !"modelMap".equals(parameterNames[i])) {
                            if (param instanceof Integer) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof String) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof Double) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof Float) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof Long) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof Boolean) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof Date) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else if (param instanceof Timestamp) {
                                sb.append(parameterNames[i] + ":" + param + "; ");
                            } else {
                                sb.append(parameterNames[i] + ":" + getString(param) + "; ");
                            }
                        }
                    }
                }
                sb = sb == null ? new StringBuilder() : sb;
                sysLog.setParams(sb.toString());
                //设置IP地址
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                sysLog.setIp(IpAddressUtil.getIpAddr(request));
    
               sysLog.setUserName(this.getDecodeUserName(request));
                sysLog.setCreateTime(new Date());
                log.debug("interface request startTime " + start.getTime());
                Object o = joinPoint.proceed();
                String response = objectMapper.writeValueAsString(o);
    
                sysLog.setTimeMin(System.currentTimeMillis() - start.getTime());
                log.debug(getString(sysLog));
                //保存系统日志
                 operationLogMapper.insert(sysLog);
                return o;
            } catch (Exception ex) {
                log.error("保存系统日志失败"+ex.getMessage());
            }
           return null;
        }
        public static String getDecodeUserName(HttpServletRequest request) {
            String userName = request.getHeader("currentUserName");
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(userName)) {
                try {
                    userName = URLDecoder.decode(userName, "utf-8");
                } catch (UnsupportedEncodingException var3) {
                    log.error(var3.getMessage(), var3);
                }
            }
    
            return userName;
        }
        public static String getString(Object o) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            StringBuffer sb = new StringBuffer();
            sb.append("entity[");
            Field[] farr = o.getClass().getDeclaredFields();
            for (Field field : farr) {
                try {
                    field.setAccessible(true);
                    if (!ValidatorUtils.empty(field.get(o))) {
                        sb.append(field.getName());
                        sb.append("=");
                        if (field.get(o) instanceof Date) {
                            // 日期的处理
                            sb.append(sdf.format(field.get(o)));
                        } else {
                            sb.append(field.get(o));
                        }
                        sb.append("|");
                    }
    
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            sb.append("]");
            return sb.toString();
        }
    }
    

    获取用户IP

    import javax.servlet.http.HttpServletRequest;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /**
     * IP地址工具类定义
     * @author yang.liu
     */
    public class IpAddressUtil {
    	public static String getIpAddr(HttpServletRequest request){
            String ipAddress = request.getHeader("x-forwarded-for");  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getHeader("Proxy-Client-IP");  
            }  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getHeader("WL-Proxy-Client-IP");  
            }  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getRemoteAddr();  
                if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){  
                    //根据网卡取本机配置的IP  
                    InetAddress inet=null;  
                    try {  
                        inet = InetAddress.getLocalHost();  
                    } catch (UnknownHostException e) {  
                        e.printStackTrace();  
                    }  
                    ipAddress= inet.getHostAddress();  
                }  
            }  
            //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割  
            if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15  
                if(ipAddress.indexOf(",")>0){  
                    ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));  
                }  
            }  
            return ipAddress;   
        }
    }
    

    系统日志注解

    import java.lang.annotation.*;
    
    /**
     * 系统日志注解
     *
     * @author lipengjun
     * @email 939961241@qq.com
     * @date 2017年3月8日 上午10:19:56
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface SysLog {
    
        String MODULE() default "操作模块";
        String REMARK() default "操作日志";
    }
    

    方法上使用自定义一注解去标识

    @SysLog(MODULE = "自定义页面配置", REMARK = "删除自定义页面配置")
    
    展开全文
  • java 设置操作日志切入点

    千次阅读 2021-08-16 10:46:46
    /** * 设置操作日志切入点 在注解的位置切入代码 */ @Pointcut("@annotation(com.jrtc.base.annotations.OperationLogAnnotation)") public void operLogPoinCut() { } @AfterReturning(returning = "result", ...
  • 系统操作日志实现_JAVA

    千次阅读 2019-04-29 13:18:22
    最近需求需要记录系统日志,在网上查询...我这个需求需要记录的是系统操作日志,范围更广,使用拦截器排除特定的Url会更适合(类似于黑名单)。 AOP实现系统操作日志及参考文章https://blog.csdn.net/u01152189...
  • 该jar中内放了实现功能的class,代码比较易于理解,可以直观的看出效果
  • 哪个人哪个时间操作了哪个模块,做的是什么操作,和原来比有什么不一样的,嗯。。。,再加上用的是什么方法操作的,方便后台直接定位问题。 二、数据库表设计 1.主键-----pkGuid 2.模块-----module 3.调用的方法路径...
  • java自定义注解,保存用户操作日志

    千次阅读 2019-05-09 15:22:05
    关于注解,很多人都清楚它们的用途,像@Autowired,@Controller,@Service等等 ...本文使用自定义注解结合springAop,记录用户的操作日志。 说到Aop切面编程,这种官方词语,看着就慌。 举个例子,现在你要吃
  • 现在做一个日志记录,需要记录下用户每一步操作的详细信息,包括成功或者失败。 之前使用的aop针对每一个control进行记录,现在control数量太多,希望找到一种简便的方法来实现记录详细操作
  • java记录用户操作日志

    千次阅读 2020-04-27 10:10:23
    https://blog.csdn.net/jceator123/article/details/84543398
  • 时间过的真快,转眼就一年了,没想到随手写的笔记会被这么多人浏览,不想误人子弟,于是整理了一个优化版。感谢各位同道的支持!
  • Java自定义日志模块实现

    热门讨论 2013-06-18 22:59:39
    自定义日志模块(接口及代理实现),而不直接使用第三方日志框架接口,避免在日志框架升级或者切换时,代码过多耦合。 这个举例说明一下: 比如,在某一项目开始时使用的是“log4j”框架,后面经过研究发现“sf4j...
  • Java程序日志打印规范

    千次阅读 2020-05-02 11:17:04
    日志技术框架一览 JUL:JDK中的日志记录工具,也常称为JDKLog、jdk-logging。 LOG4J1:一个具体的日志实现框架。 LOG4J2:一个具体的日志实现框架,是LOG4J1的下一个版本。 LOGBACK:一个具体的日志实现框架...
  • java自定义注解annotation记录操作日志

    千次阅读 2018-12-06 10:24:24
    1.首先java jdk 给我们提供了meta-annotation用于自定义注解的时候使用,这四个注解为:@Target,@Retention,@Documented 和@Inherited。 第一个注解 @Target @Target :用于描述注解的使用范围(即:被描述...
  • Java的8个Java日志工具

    千次阅读 2018-06-28 23:49:47
    Log4j是一款基于Java的开源日志组件,Log4j功能非常强大,我们可以将日志信息输出到控制台、文件、用户界面,也可以输出到操作系统的事件记录器和一些系统常驻进程。更值得一提的是,Log4j可以允许你非常便捷地...
  • java日志操作之Log4j.doc

    2011-10-09 16:17:21
    java日志操作之Log4j.doc java日志操作之Log4j.doc java日志操作之Log4j.doc java日志操作之Log4j.doc
  • Java获取项目日志/读取日志

    千次阅读 2019-06-14 16:24:09
    @RestController @RequestMapping(value = "api/common") public class CommonContoller { ... * 日志管理 */ private Logger LOGGER = LoggerFactory.getLogger(CommonContoller.class); // 字...
  • java Web工程实现操作日志记录的方式有很多,比如通过spring aop方式实现,也可以通过Filter方式实现。 public class StoreLogFilter implements Filter { private static final Logger logger = LoggerFactory....
  • spring aop 操作日志

    2014-06-04 00:14:07
    本资源用来展示如何使用 spring aop 进行日志记录,例子里面通过aop的配置,把产生的日志存放到当前项目的根目录下,而且对方法执行过程中的参数进行了记录,对于aop如何记录日志不清楚的同学可以看看。
  • Java实现日志脱敏处理

    万次阅读 热门讨论 2019-01-24 19:30:36
    Java 实现日志脱敏处理 题记 在日常工作中,日志处理是我们每一个程序员必备的素质,但是在有些场景下客户信息敏感,需要进行某些字段,或者某部分字段的脱敏处理。接到需求我们开始操刀! 需求分析 处理字段的...
  • java利用AOP 实现操作日志记录(一)

    千次阅读 2018-05-08 09:21:00
    * @param 操作类型 */ String option(); }   定义切面类: @Aspect // 该注解标示该类为切面类 @Component // 注入依赖 public class OperationLogAspect { // 标注该方法体为后置通知,当目标方法...
  • 实现管理员操作数据的记录。效果如下 二,代码实现 基于注解的Aop日志记录 1.Log实体类 package com.vulcan.facade.operationlog.entity; import lombok.Data; import org.springframework.data.annotation.Id...
  • java程序日志规范

    千次阅读 2019-04-08 10:48:05
    1. 【强制】应用中不可直接使用日志系统( Log4j、 Logback)中的 API,而应依赖使用日志框架 SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。 1 2 3 4 5 ...
  • 比如删除一条数据 点击恢复就会恢复这条数据。 修改了一条数据 点击恢复就是恢复到修改之前的数据 求教各位大佬 有什么好的思路 或者 成型的框架
  • 怎样分析java线程堆栈日志

    千次阅读 2019-02-21 10:23:36
    注: 该文章的原文是由 Tae Jin Gu 编写,原文地址为 How to Analyze Java Thread Dumps 当有障碍,或者是一个基于 JAVA 的 WEB 应用运行的比预期慢...在这里我将解释在 JAVA什么是 threads,他们的类型,怎么...
  • Java 代码里的日志输出优化

    千次阅读 2019-07-01 10:59:45
    什么时候应该打日志 当你遇到问题的时候,只能通过debug功能来确定问题,你应该考虑打日志,良好的系统,是可以通过日志进行问题定为的。 当你碰到if…else 或者 switch这样的分支时,要在分支的首行打印日志,用来...
  • 我们开发的业务系统通常会提供给很多人使用,那在使用的过程中,日志系统变得非常重要。...我们就可以看到这样的操作日志展示: 对于这样的日志记录,我们可以在相关记录点添加对应的日志写入代...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 483,326
精华内容 193,330
关键字:

java操作日志是什么

java 订阅