后台管理系统之系统操作日志开发(Java实现)

一,功能点

实现管理员操作数据的记录。效果如下

二,代码实现

基于注解的Aop日志记录

1.Log实体类

package com.ideal.manage.guest.bean.log;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

/**
 * @apiNote 日志
 * @author Yaming
 * @since 2019-01-24
 */
@Entity
@Table(name = "visitor_sys_log")
public class Log implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    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;



    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getModule() {
        return module;
    }

    public void setModule(String module) {
        this.module = module;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getCreateAt() {
        return createAt;
    }

    public void setCreateAt(Date createAt) {
        this.createAt = createAt;
    }

    public Date getUpdateAt() {
        return updateAt;
    }

    public void setUpdateAt(Date updateAt) {
        this.updateAt = updateAt;
    }

    public Integer getAble() {
        return able;
    }

    public void setAble(Integer able) {
        this.able = able;
    }
}

2.定义注解

package com.ideal.manage.guest.annotation;

import java.lang.annotation.*;

/**
 * @author Hao
 * @create 2017-03-29
 */
@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 Yaming
 * @create 2019-01-24
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogService logService;

    /**
     * 日志切入点
     */
    @Pointcut("@annotation(com.ideal.manage.guest.annotation.Log)")
    public void logPointCut(){}

    @AfterReturning(pointcut = "logPointCut()")
    public void doAfter(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 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;
    }

}

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;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author
 * @since 2017-09-05
 */
@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();
//          User user = userRepository.findOne(shiroUser.getId());
            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);
            //insert(log);
            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) {
            // exception
            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;
    }
}

5.dao

package com.ideal.manage.guest.repository.log;
import com.ideal.manage.guest.bean.log.Log;
import com.ideal.manage.guest.repository.framework.BaseRepository;

/**
 * <p>
  *  Mapper 接口
 * </p>
 *
 * @author Yankee
 * @since 2017-09-05
 */

public interface LogRepository extends BaseRepository<Log,String> {

    /**
     * 查询分页
     * @param request
     * @param page
     * @return
     */
    //List<Log> page(@Param("re") LogRequest request, Pagination page);
}

三,使用注解在需要的地方记录日志

@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/inspred/p/10385005.html