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);
    }
  • 相关阅读:
    2015.2.27 UltraEdit中显示XML结构
    2015.1.31 DataGridView自动滚动到某行
    2015.1.15 利用函数实现将一行记录拆分成多行记录 (多年想要的效果)
    2015.1.15 利用Oracle函数返回表结果 重大技术进步!
    2015.1.15 利用Oracle函数插入表结构 Bulk collect into 不用循环,简洁高效
    2015.1.8 Left join 左连接
    2015.1.10 解决DataGridView SelectionChanged事件自动触发问题
    delphi 遍历窗口
    delphi 访问 protected 属性 哈哈
    clientdataset 读取excel 如果excel 文件不存在的时候 相应的gird 会不显示数据, 鼠标掠过 gird 格子 才会显示数据。 这是一个bug 哈哈
  • 原文地址:https://www.cnblogs.com/jockming/p/12240805.html
Copyright © 2011-2022 走看看