zoukankan      html  css  js  c++  java
  • 切面编程(操作日志)

    自定义注解

    import java.lang.annotation.*;
     
    /**
     * @author wzm
     */
    //注解会在class中存在,运行时可通过反射获取
    @Retention(RetentionPolicy.RUNTIME)
    //目标是方法
    @Target({ElementType.METHOD, ElementType.PARAMETER})
    //表示是否将注解信息添加在java文档中
    @Documented
    public @interface Log {
     
        //这个用户所做的是什么操作
        String value() default "未标注操作";
     
        /**
         * 1 2 3 4 / 增 删 改 查
         * 0 未设置
         * @return int
         */
        int type() default 0;
     
    }
     

    切面类

    SysLogAspect.java

    import com.thyc.fabric.annotation.Log;
    import com.thyc.fabric.common.utils.IpUtil;
    import com.thyc.fabric.entity.business.OperationLogger;
    import com.thyc.fabric.service.business.OperationLoggerService;
    import com.thyc.fabric.shiro.JWTUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.StringUtils;
    import org.apache.shiro.SecurityUtils;
    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.springframework.beans.factory.annotation.Autowired;
    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.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
     
    /**
     * @author wzm
     */
    @Aspect
    @Component
    @Slf4j
    public class SysLogAspect {
     
        @Autowired
        private OperationLoggerService operationLoggerService;
     
        public SysLogAspect() {
        }
     
        private static OperationLogger operationLogger = new OperationLogger();
     
        /**
         * 注解切点
         */
        @Pointcut("@annotation(com.thyc.fabric.annotation.Log)")
        public void pointCut() {
        }
     
        @Around("pointCut()")
        public Object around(ProceedingJoinPoint pjd) throws Throwable {
            Object object = null;
            try {
                // 开始执行时间
                long starTime = System.currentTimeMillis();
                object = pjd.proceed();
     
                // 获取request
                ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = null;
                if (servletRequestAttributes != null) {
                    request = servletRequestAttributes.getRequest();
                }
                if (request != null) {
                    // 通过token解析操作用户
                    String token = (String) SecurityUtils.getSubject().getPrincipal();
                    if (token != null) {
                        String username = JWTUtil.getUsername(token);
                        operationLogger.setCreator(username);
                    }
                    // 获取访问端(web android ios)
                    operationLogger.setAccessType(request.getHeader("accessType"));
     
                }
                MethodSignature methodName1 = (MethodSignature) pjd.getSignature();
                Method method = methodName1.getMethod();
     
                //method方法上面的注解
                Annotation[] annotations = method.getAnnotations();
                boolean flag = false;
                for (Annotation annotation : annotations) {
                    if (Log.class.equals(annotation.annotationType())) {
                        flag = true;
                    }
                }
                if (flag) {
                    // 类名
                    String className = pjd.getTarget().getClass().getName();
                    operationLogger.setLogClassName(className);
     
                    // 操作描述
                    String operation = method.getAnnotation(Log.class).value();
                    operationLogger.setOperationContent(operation);
     
                    // 操作类型
                    Integer operationType = method.getAnnotation(Log.class).type();
                    operationLogger.setOperationType(operationType);
     
                    // ip地址
                    String ip = IpUtil.getIp(request);
                    operationLogger.setRemoteIpAddress(ip);
     
                    // 城市信息
                    String cityInfo = IpUtil.getCityInfo(ip);
                    operationLogger.setCityInfo(cityInfo);
     
                    // 设置方法名
                    operationLogger.setLogMethodName(method.getName());
     
                    Signature signature = pjd.getSignature();
                    MethodSignature methodSignature = (MethodSignature) signature;
                    String[] argNames = methodSignature.getParameterNames();
     
                    // 如果有参数
                    if (argNames.length > 0) {
                        // 参数名列表
                        List<String> paramNameList =
                                new ArrayList<>(Arrays.asList(methodSignature.getParameterNames()).subList(0, argNames.length));
     
                        // 参数类型
                        List<String> paramTypeList = new ArrayList<>();
                        Parameter[] parameters = method.getParameters();
                        for (Parameter parameter : parameters) {
                            String paramType = parameter.getType().getName();
                            paramTypeList.add(paramType);
                        }
     
                        // 参数的值
                        List<Object> paramValueList = new ArrayList<>();
                        Object[] params = pjd.getArgs();
                        Collections.addAll(paramValueList, params);
     
                        operationLogger.setParamsTypeList(paramTypeList.toString());
                        operationLogger.setParamsNameList(paramNameList.toString());
                        operationLogger.setParamsValueList(paramValueList.toString());
                    } else {
                        // 没有参数的话就都设置为none
                        operationLogger.setParamsTypeList("none");
                        operationLogger.setParamsNameList("none");
                        operationLogger.setParamsValueList("none");
                    }
                }
                // 设置异常信息
                operationLogger.setExceptionInfo(null);
     
                // 执行时间 = 执行结束时间 - 开始时间 (单位:毫秒)
                long execTime = System.currentTimeMillis() - starTime;
                operationLogger.setExecTime(String.valueOf(execTime));
            } catch (Exception e) {
                operationLogger.setExceptionInfo(e.getMessage());
                operationLoggerService.addLogger(operationLogger);
                throw e;
            }
            log.info("[" + operationLogger.getRemoteIpAddress() + "][" + operationLogger.getOperationContent() + "]["
                    + operationLogger.getLogClassName() + " - " + operationLogger.getLogMethodName() + "]" + " - "
                    + (StringUtils.isNotBlank(operationLogger.getExecTime()) ? operationLogger.getExecTime() : "0") + "ms");
     
            // 录入数据库
            operationLoggerService.addLogger(operationLogger);
            // 执行方法,获取返回参数
            return object;
        }
    }

    service层

    OperationLoggerService.java
    import com.baomidou.mybatisplus.service.IService;
    import com.thyc.fabric.common.exception.BaseException;
    import com.thyc.fabric.entity.business.OperationLogger;
     
    /**
    * 操作日志记录 Service层
    *
    * @author wzm
    * @version 1.0
    */
    public interface OperationLoggerService extends IService<OperationLogger> {
     
        /**
         * 添加日志(配置了aop切面)
         *
         * @param operationLogger log
         * @throws BaseException e
         */
        void addLogger(OperationLogger operationLogger) throws BaseException;
    }
     
    OperationLoggerServiceImpl.java
    import com.baomidou.mybatisplus.service.impl.ServiceImpl;
    import com.thyc.fabric.common.exception.BaseException;
    import com.thyc.fabric.dao.business.OperationLoggerMapper;
    import com.thyc.fabric.entity.business.OperationLogger;
    import com.thyc.fabric.service.business.OperationLoggerService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.transaction.interceptor.TransactionAspectSupport;
     
    import javax.annotation.Resource;
    import java.util.Date;
     
    /**
     * 操作日志记录 ServiceImpl层
     *
     * @author wzm
     * @version 1.0
     */
    @Service
    @Slf4j
    public class OperationLoggerServiceImpl extends ServiceImpl<OperationLoggerMapper, OperationLogger> implements OperationLoggerService {
     
        @Resource
        private OperationLoggerMapper operationLoggerMapper;
     
        /**
         * 添加日志(配置了aop切面)
         *
         * @param operationLogger 日志对象
         */
        @Transactional(rollbackFor = {Exception.class})
        @Override
        public void addLogger(OperationLogger operationLogger) throws BaseException {
            //尚未添加logger实体和dao
            try {
                operationLogger.setCreateTime(new Date());
                int result = operationLoggerMapper.insert(operationLogger);
                //操作成功
                if (result < 1) {
                    log.warn("新增日志失败");
                }
            } catch (Exception e) {
                //手动回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                throw new BaseException(e.getMessage());
            }
        }
     
    }
     

    Dao层

    OperationLoggerMapper.java
    import com.baomidou.mybatisplus.mapper.BaseMapper;
    import com.thyc.fabric.entity.business.OperationLogger;
    import com.thyc.fabric.vo.business.LogVO;
     
    import java.util.List;
     
    /**
    * @author wzm
    */
    public interface OperationLoggerMapper extends BaseMapper<OperationLogger> {
     
        /**
         * 查询操作日志
         *
         * @param type 日志类型
         * @param star 开始时间
         * @param end  截止时间
         * @return list vo
         * @author wzh
         * @date 2019/9/29 0029 17:53
         */
        List<LogVO> queryLogList(Integer type, String star, String end);
    }
     
    OperationLoggerMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.thyc.fabric.dao.business.OperationLoggerMapper">
     
        <resultMap id="OperationLoggerMap" type="com.thyc.fabric.entity.business.OperationLogger">
            <result column="id" property="id" />
            <result column="operation_content" property="operationContent" />
            <result column="operation_type" property="operationType" />
            <result column="log_class_name" property="logClassName" />
            <result column="log_method_name" property="logMethodName" />
            <result column="params_type_list" property="paramsTypeList" />
            <result column="params_name_list" property="paramsNameList" />
            <result column="params_value_list" property="paramsValueList" />
            <result column="exception_info" property="exceptionInfo" />
            <result column="remote_ip_address" property="remoteIpAddress" />
            <result column="access_type" property="accessType" />
            <result column="exec_time" property="execTime" />
            <result column="city_info" property="cityInfo" />
            <result column="creator" property="creator" />
            <result column="modifier" property="modifier" />
            <result column="create_time" property="createTime" />
            <result column="modify_time" property="modifyTime" />
            <result column="valid" property="valid" />
        </resultMap>
     
        <select id="queryLogList" resultType="com.thyc.fabric.vo.business.LogVO">
            select
            log.id as logId,
            u.nick_name as nickName,
            log.operation_type as typeId,
            log.operation_content as `desc`,
            log.remote_ip_address as ip,
            log.log_class_name as className,
            log.log_method_name as methodName,
            log.exception_info as exceptionInfo,
            log.create_time as createTime
            from
            t_operation_logger as log
            inner join t_sys_user as u
            on u.id = log.user_id
            where  log.valid = 1 AND u.valid = 1
            <if test="type != null">
                AND log.operation_type = #{type}
            </if>
            <if test="type == null">
                AND log.operation_type <![CDATA[!=]]> 4
            </if>
            <if test="star != null and end != null">
                AND DATE_FORMAT(log.create_time,'%Y-%m-%d') BETWEEN STR_TO_DATE(#{star},'%Y-%m-%d') AND STR_TO_DATE(#{end},'%Y-%m-%d')
            </if>
            order by log.create_time desc
        </select>
    </mapper>
     

    日志实体类

    实体类:
    import com.baomidou.mybatisplus.annotations.TableField;
    import com.thyc.fabric.entity.BaseEntity;
    import com.baomidou.mybatisplus.annotations.TableName;
    import lombok.Data;
    import java.io.Serializable;
     
    /**
     *
     * @author wzm
     */
    @TableName("t_operation_logger")
    @Data
    public class OperationLogger extends BaseEntity<OperationLogger>{
     
        private static final long serialVersionUID = 1L;
     
        /**
         * 操作内容
         */
        @TableField("operation_content")
        private String operationContent;
        /**
         * 操作类型( 0-未设置, 1-新增, 2-删除, 3-修改, 4-查询, 5-登录, 6-登出, 7-转账)
         */
        @TableField("operation_type")
        private Integer operationType;
        /**
         * 类名
         */
        @TableField("log_class_name")
        private String logClassName;
        /**
         * 方法名
         */
        @TableField("log_method_name")
        private String logMethodName;
        /**
         * 参数类型列表
         */
        @TableField("params_type_list")
        private String paramsTypeList;
        /**
         * 参数名称列表
         */
        @TableField("params_name_list")
        private String paramsNameList;
        /**
         * 参数值列表
         */
        @TableField("params_value_list")
        private String paramsValueList;
        /**
         * 异常信息
         */
        @TableField("exception_info")
        private String exceptionInfo;
        /**
         * 远程IP地址
         */
        @TableField("remote_ip_address")
        private String remoteIpAddress;
        /**
         * 访问类型(0-web, 1-android, 2-ios)
         */
        @TableField("access_type")
        private String accessType;
        /**
         * 执行时间
         */
        @TableField("exec_time")
        private String execTime;
        /**
         * 城市信息
         */
        @TableField("city_info")
        private String cityInfo;
     
        @Override
        protected Serializable pkVal() {
            return this.id;
        }
     
    }

    控制层

    注解加到方法是以记录该接口的行为。
    @PostMapping("oss_file_uploader")
    @Log(value = "oss文件上传", type = 1)
    @ApiOperation(value = "oss文件上传", notes = "文件上传接口", produces = "application/json")
    public ApiResult ossUploadFile(@RequestParam(value = "file") MultipartFile file) throws BusinessException {
        return commonService.ossUploadFile(file);
    }
  • 相关阅读:
    JAVA-jar包下载地址
    JAVA-Eclipse中web-inf和meta-inf文件夹
    【转载】JAVA-dynamic web module与tomcat
    判断二叉树是不是平衡
    二叉树的深度
    二叉搜索树的后序遍历序列
    数对之差的最大值
    字符串的组合
    求二元查找树的镜像
    字符串的排列
  • 原文地址:https://www.cnblogs.com/jockming/p/12240805.html
Copyright © 2011-2022 走看看