Spring Boot 使用切面记录日志

方案选择
针对记录用户操作日志,面向切面编程无疑是最好的解决方法:

创建日志注解类;
创建方法所属模块枚举、接口操作类型枚举、相关常量枚举;
创建日志切面 ;
创建日志写入文件工具类 ;

创建日志注解类



@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogTail {

    /**
     * 方法名称
     */
    String name();
    
    /**
     * 所属模块
     */
    FunctionModuleEnum module();
    
    /**
     * 方法的操作类型
     */
    OperateTypeEnum operateType();
}


创建方法所属模块枚举
根据项目中的模块创建所属模块

/**
 * 方法所属模块
 */
public enum FunctionModuleEnum {

    STATISTICS("统计分析"),

    DATA_MANAGEMENT("数据管理"),

    SYSTEM("系统配置")
    ;

    private String name;

    FunctionModuleEnum(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

创建接口操作类型枚举
根据甲方文档要求创建接口操作类型枚举


/**
 * 接口操作类型
 */
public enum OperateTypeEnum {

    LOG_IN(0, "登录"),

    QUERY(1, "查询"),

    ADD(2, "新增"),

    UPDATE(3, "更新"),

    DELETE(4, "删除"),

    LOG_OUT(5, "退出"),
    ;

    private Integer code;

    private String title;

    OperateTypeEnum(Integer code, String title) {
        this.code = code;
        this.title = title;
    }

    public Integer getCode() {
        return code;
    }

    public String getTitle() {
        return title;
    }

    public static OperateTypeEnum getByCode(Integer code) {
        for (OperateTypeEnum value : values()) {
            if (value.code.equals(code)) {
                return value;
            }
        }
        return null;
    }
}

创建相关常量枚举

/**
 * 相关常量
 */
public class Constants {

    /**
     * 分隔符
     */
    public static final String SEPARATOR = "|";

    /**
     * 换行符
     */
    public static final String LINE = "\n";
}

创建日志切面

/**
 * 日志切面
 */
@Aspect
@Component
public class LogTailAspect {

    private static final Logger LOG = LoggerFactory.getLogger("operate");

    private static Field[] fields;

    @Resource
    private LogRecordService logRecordService;

    @Value("${product.id:310000000000}")
    private String productId;

    @Value("${product.name:机场打击整治非法客运管理}")
    private String productName;

    @Pointcut("execution(* com.shxp.project.*.controller..*.*(..))")
    public void excudeService() {

    }

    static {
        Class<LogBean> clazz = LogBean.class;
        fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
        }
    }

    @Around("@annotation(com.shxp.project.sys.annotation.LogTail)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Date start = new Date();
        Object object = joinPoint.proceed();
        Date end = new Date();
        execute(joinPoint, object, start, end);
        return object;
    }

    private void execute(ProceedingJoinPoint joinPoint, Object result, Date start, Date end) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();

        MethodSignature methodSignature = Optional.of(joinPoint)
                .map(ProceedingJoinPoint::getSignature)
                .map(e -> (MethodSignature) e)
                .orElse(null);

        LogTail logTail = Optional.of(methodSignature)
                .map(MethodSignature::getMethod)
                .map(e -> e.getAnnotation(LogTail.class))
                .orElse(null);

        Method method = methodSignature.getMethod();
        Annotation[][] annotations = method.getParameterAnnotations();
        Class[] classes = methodSignature.getParameterTypes();
        String[] names = methodSignature.getParameterNames();
        Object[] args = joinPoint.getArgs();

        LogBean logBean = new LogBean();

        /**
         * 获取用户信息
         */
        UserMessage user = getUser(names, args);
        if (Objects.nonNull(user)) {
            logBean.setOperatorID(user.getUser_id()+"");
            logBean.setOperatorAccount(user.getUser_id()+"");
            logBean.setOperatorName(user.getUser_name());
            logBean.setOrganizationID(user.getOrg_code());
            logBean.setOrganizationName(user.getFull_name());
        }else{
            ShiroUserEntity currentUser = UserUtil.getCurrentUser();
            assert currentUser != null;
            logBean.setOperatorID(currentUser.getId()+"");
            logBean.setOperatorAccount(currentUser.getUserAccount()+"");
            logBean.setOperatorName(currentUser.getName());
            DeptEnum deptEnum = DeptEnum.getByCode(currentUser.getDept());
            if (deptEnum!=null){
                logBean.setOrganizationID(deptEnum.getOrg());
                logBean.setOrganizationName(deptEnum.getTitle());
            }
        }

        logBean.setProductID(productId);
        logBean.setProductName(productName);
        logBean.setLogID(UUID.randomUUID().toString());
        logBean.setOperatorIdentity(1);
        logBean.setOpTime(DateUtils.format(start, DateUtils.DEFAULT_DATE_PATTERN14));
        logBean.setResTime(DateUtils.format(end, DateUtils.DEFAULT_DATE_PATTERN14));
        logBean.setTerminalType(0);
        logBean.setOpType(logTail.operateType().getCode());
        logBean.setClientIp(request.getRequestURL().toString());
        logBean.setClientPort(Objects.isNull(request.getRemotePort())?null:String.valueOf(request.getRemotePort()));
        logBean.setURL(request.getRequestURI());
//        logBean.setObjectParams();
        logBean.setSessionID(request.getRequestedSessionId());
        logBean.setFuncModuleName(logTail.module().getName()+"-"+logTail.name());
        logBean.setObjectIP(request.getRequestURL().toString());
        logBean.setObjectPort(Objects.isNull(request.getRemotePort())?null:String.valueOf(request.getRemotePort()));
//        logBean.setOperateCondition();
        logBean.setOperateCondition(getRequestParam(joinPoint));
//        logBean.setTerminalID();
//        logBean.setTerminalMac();
//        logBean.setQuerySql();
        String log = Stream.of(fields).map(e -> {
            try {
                return e.get(logBean);
            } catch (IllegalAccessException ex) {
                return "";
            }
        }).map(Util::getString).collect(Collectors.joining(Constants.SEPARATOR));
        LogUtils.insertLog(log);
        logRecordService.insertLog(logBean);
    }

    /**
     * 从参数列表中获取userId参数,返回用户信息
     *
     * @param names
     * @param args
     * @return
     */
    private UserMessage getUser(String[] names, Object[] args) {
        UserMessage user = null;
        for (int i = 0; i < names.length; i++) {
            if ("userId".equals(names[i]) && args.length >= i+1) {
                String userId = StringTools.getStringValue(args[i]);
                List<UserMessage> userMessages = KoalClient.queryUserByIdcard(userId);
                if (!CollectionUtils.isEmpty(userMessages)){
                    user = userMessages.get(0);
                }
            }
        }
        return user;
    }
    private String getRequestParam(JoinPoint pjp){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        if (HttpMethod.PUT.name().equals(request.getMethod()) || HttpMethod.POST.name().equals(request.getMethod())){
            return getBodyContent(pjp);
        } else {
            Map<String,Object> map = getParamContent(request.getParameterMap());
            return JSON.toJSONString(map);
        }
    }
    private Map<String,Object> getParamContent(Map<String, String[]> params) {
        Map<String,Object> resultMap = new HashMap<>();
        try {
            for (Map.Entry<String, String[]> entry : params.entrySet()) {
                Object value = new Object();
                if (entry.getValue() != null && entry.getValue().length == 1) {
                    value = entry.getValue()[0];
                } else {
                    value = entry.getValue();
                }
                resultMap.put(entry.getKey(),value);
            }
        } catch (Exception e) {
            LOG.error("日志记录解析param参数失败",e.getMessage());
            resultMap.put("paramParse","参数解析失败");
        }
        return resultMap;
    }

    private String getBodyContent(JoinPoint pjp) {
        String bodyContent = "";
        try {
            Object[] args = pjp.getArgs();
            List arguments = new ArrayList();
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
                    //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
                    //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
                    continue;
                }
                arguments.add(args[i]);
            }
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(arguments) && arguments.size() == 1) {
                bodyContent = JSON.toJSONString(arguments.get(0));
            } else {
                bodyContent = JSON.toJSONString(arguments);
            }
        }catch (Exception e) {
            LOG.error("日志记录解析body参数失败",e);
            Map<String,Object> resultMap = new HashMap<>();
            resultMap.put("paramParse","参数解析失败");
        }
        return bodyContent;
    }
   

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

princeAladdin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值