• 系统审计日志开发


    基于注解的Aop日志记录

    项目安全送检前需要做个审计日志,做完后在这记录下实现过程

    1.Log实体类

    package com.ideal.manage.guest.bean.log;
    
    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * @apiNote 日志
     * @author lcoil
     * @since 2020-05-24
     */
    @Data
    public class Log {
    
        private Long id;
    
        private String content;
    
        private String description;
    
        private String ip;
    
        private String module;
    
        private String username;
    
        private Date createAt;
    
        private Date updateAt;
    
        private Integer able;
        
    }
    View Code

    2.定义注解

    package com.ideal.manage.guest.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * @author lcoil
     * @create 2020-05-24
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Log {
        /**模块*/
        String module() default "";
    
        /**描述*/
        String description() default "";
    }

    3.定义切面

    package com.ideal.manage.guest.aop;
    
    
    import com.ideal.manage.guest.annotation.Log;
    import com.ideal.manage.guest.service.log.LogService;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    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 java.lang.reflect.Method;
    
    /**
     * 日志切面处理类
     *
     * @author lcoil
     * @create 2020-05-24
     */
    @Aspect
    @Component
    public class LogAspect {
    
        @Autowired
        private LogService logService;
    
        /**
         * 日志切入点
         */
        @Pointcut("@annotation(com.ideal.manage.guest.annotation.Log)")
        public void logPointCut(){}
    
        /**
         * 前置通知
         * @param joinPoint
         */
        @Before(value ="execute()")
        public void Before(JoinPoint joinPoint) {
             /**
             * 解析Log注解
             */
            String methodName = joinPoint.getSignature().getName();
            Method method = currentMethod(joinPoint,methodName);
            Log log = method.getAnnotation(Log.class);
            logService.put(joinPoint,methodName,log.module(),log.description());
        }
        
         /**
         * 环绕通知
         * @param proceedingJoinPoint
         * @return
         */
        @Around(value ="execute()")
        public Object around(ProceedingJoinPoint proceedingJoinPoint) {
            System.out.println("环绕通知开始");
            try {
                System.out.println("执行方法:" + proceedingJoinPoint.getSignature().getName());
                
                MethodSignature signature =(MethodSignature) proceedingJoinPoint.getSignature();
                Action action = signature.getMethod().getAnnotation(Action.class);
                
                System.out.println("菜单="+action.description());
                
                Object object =  proceedingJoinPoint.proceed();
                System.out.println("环绕通知结束,方法返回:" + object);
                return object;
            } catch (Throwable e) {
                System.out.println("执行方法异常:" + e.getClass().getName());
                return null;
            }
        }
    
        /**
         * 后置通知
         * @param joinPoint
         */
        @After(value ="execute()")
        public void After(JoinPoint joinPoint) {
            System.out.println("执行方法之后");
        }
        
        /**
         * 后置通知,带返回值
         * @param obj
         */
        @AfterReturning(pointcut = "execute()",returning = "obj")
        public void doAfter(Object obj){
           System.out.println("执行方法之后获取返回值:"+obj);
        }
        
        /**
         * 后置通知,异常时执行
         * @param e
         */
        @AfterThrowing(throwing = "e",pointcut = "execute()")
        public void doAfterThrowing(Exception e) {
            System.out.println("执行方法异常:"+e.getClass().getName());
        }
        
        /**
         * 获取当前执行的方法
         *
         * @param joinPoint  连接点
         * @param methodName 方法名称
         * @return 方法
         */
        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;
        }
    
    }
    LogAspect

    4.业务处理:LogService

    package com.ideal.manage.guest.service.log;
    
    import com.alibaba.fastjson.JSONObject;
    
    
    import com.ideal.manage.guest.bean.DTO.PageDto;
    import com.ideal.manage.guest.bean.log.Log;
    
    import com.ideal.manage.guest.config.shiro.MyShiroRealm;
    import com.ideal.manage.guest.repository.framework.MySpecification;
    import com.ideal.manage.guest.repository.framework.SpecificationOperator;
    import com.ideal.manage.guest.repository.log.LogRepository;
    import com.ideal.manage.guest.util.Const;
    import com.ideal.manage.guest.util.HttpRequests;
    import com.ideal.manage.guest.util.IPUtils;
    
    /*import org.apache.ibatis.javassist.*;
    import org.apache.ibatis.javassist.bytecode.CodeAttribute;
    import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
    import org.apache.ibatis.javassist.bytecode.MethodInfo;*/
    import javassist.*;
    import javassist.bytecode.CodeAttribute;
    import javassist.bytecode.LocalVariableAttribute;
    import javassist.bytecode.MethodInfo;
    import org.apache.shiro.SecurityUtils;
    import org.aspectj.lang.JoinPoint;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    import org.springframework.stereotype.Service;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.StringUtils;
    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.Iterator;
    import java.util.List;
    import java.util.Map;
    
    /**
     *  服务实现类
     *
     * @author lcoil
     * @since 2020-05-24
     */
    @Service
    public class LogService{
    
        private static final String LOG_CONTENT = "[类名]:%s,[方法]:%s,[参数]:%s,[IP]:%s";
    
        private String username;
    
        @Autowired
        private LogRepository logRepository;
    
        public String initUsername(String username) {
            if(!StringUtils.isEmpty(username)){
                this.username = username;
            }
            return this.username;
        }
    
    
        public void put(JoinPoint joinPoint, String methodName, String module, String description) {
            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                Log log = new Log();
                //username = ((JwtClient) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
                // 获取当前登录用户
                MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
                username = shiroUser.getUsername();
                if (StringUtils.isEmpty(username)) {
                    username = Const.USERNAME_IN_CONTEXT != null ? Const.USERNAME_IN_CONTEXT : "未知用户";
                }
    
                String ip = IPUtils.getIpAddr(request);
                log.setUsername(username);
                log.setModule(module);
                log.setDescription(description);
                log.setIp(ip);
                log.setContent(operateContent(joinPoint, methodName, ip, request));
                log.setAble(1);
                logRepository.save(log);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /*public Page<Log> page(LogRequest request, Page<Log> page) {
            if(request == null){
                request = new LogRequest();
            }
            request.setIsDeleted(Config.ABLE_CONFIG.ABLE);
            List<Log> logs = baseMapper.page(request,page);
            page.setRecords(logs);
            return page;
        }*/
    
        /**
         * 查询所有日志
         * @param pageNum
         * @param request
         * @return
         */
        public PageDto findAll(int pageNum, HttpServletRequest request) {
            Sort sort = new Sort(Sort.Direction.DESC, "updateAt");
            List<SpecificationOperator> operators = HttpRequests.getParametersStartingWith(request, "Q_");
            //增加删除标识的过滤
            SpecificationOperator isValid = new SpecificationOperator("able", "1", "EQ");
            operators.add(isValid);
            MySpecification<Log> mySpecifications = new MySpecification<>(operators);
            Pageable pageable = new PageRequest(pageNum, 10, sort);
            Page<Log> page = logRepository.findAll(mySpecifications, pageable);
            //设置PageDto
            List<Log> parameters = page.getContent();
            long total = page.getTotalElements();
            PageDto pageDto = new PageDto();
            pageDto.setRows(parameters);
            pageDto.setTotal(total);
            return pageDto;
        }
    
    
        public String operateContent(JoinPoint joinPoint, String methodName, String ip, HttpServletRequest request) throws ClassNotFoundException, NotFoundException {
            String className = joinPoint.getTarget().getClass().getName();
            Object[] params = joinPoint.getArgs();
            String classType = joinPoint.getTarget().getClass().getName();
            Class<?> clazz = Class.forName(classType);
            String clazzName = clazz.getName();
            Map<String,Object > nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,params);
            StringBuffer bf = new StringBuffer();
            if (!CollectionUtils.isEmpty(nameAndArgs)){
                Iterator it = nameAndArgs.entrySet().iterator();
                while (it.hasNext()){
                    Map.Entry entry = (Map.Entry) it.next();
                    String key = (String) entry.getKey();
                    String value = JSONObject.toJSONString(entry.getValue());
                    bf.append(key).append("=");
                    bf.append(value).append("&");
                }
            }
            if (StringUtils.isEmpty(bf.toString())){
                bf.append(request.getQueryString());
            }
            return String.format(LOG_CONTENT, className, methodName, bf.toString(), ip);
        }
    
        private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException {
            Map<String,Object > map=new HashMap<String,Object>();
    
            ClassPool pool = ClassPool.getDefault();
            ClassClassPath classPath = new ClassClassPath(cls);
            pool.insertClassPath(classPath);
    
            CtClass cc = pool.get(clazzName);
            CtMethod cm = cc.getDeclaredMethod(methodName);
            MethodInfo methodInfo = cm.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                return map;
            }
            int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
            for (int i = 0; i < cm.getParameterTypes().length; i++){
                map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名
            }
            return map;
        }
    }
    LogService

    5.使用注解在需要的地方记录日志

    @Log(module = "设备管理",description = "添加设备")
        public Integer saveEquipment(Equipment equipment) {
            equipment.setAble(1);
            Equipment resultEquipment = equipmentRepository.save(equipment);
            if(resultEquipment == null){
                return StateUtil.RESULT_FAILED;
            }
            return StateUtil.RESULT_SUCCESS;
        }
    博客园:https://www.cnblogs.com/xianquan
    Copyright ©2020 l-coil
    【转载文章务必保留出处和署名,谢谢!】
  • 相关阅读:
    使用Connector/C++(VS2015)连接MySQL的完整例子
    一个表里有多个字段需要同时使用字典表进行关联显示,如何写sql查询语句
    Delphi连接MySql(待测试验证,使用mysql.pas未通过)
    MySQL5.5.51启用网络远程连接
    delphi做的程序如何连接SQL数据库
    定时删除所有文件夹下的_desktop.ini文件
    Delphi中打开网页连接的几种方法
    SQL增删改查
    ADOConnection断线重连
    TDBGridEh 标头排序
  • 原文地址:https://www.cnblogs.com/xianquan/p/13018974.html
  • Copyright © 2020-2023  润新知