SimpleAuditService.java 12.8 KB
package cn.ibizlab.util.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import cn.ibizlab.util.annotation.Audit;
import cn.ibizlab.util.annotation.DEField;
import cn.ibizlab.util.domain.EntityBase;
import cn.ibizlab.util.domain.IBZDataAudit;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import cn.ibizlab.util.mapper.IBZDataAuditMapper;
import cn.ibizlab.util.security.AuthenticationUser;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 实体[DataAudit] 服务对象接口实现
 */
@Service
@Slf4j
public class SimpleAuditService extends ServiceImpl<IBZDataAuditMapper, IBZDataAudit> implements IBZDataAuditService {

    private final ExpressionParser parser = new SpelExpressionParser();

    private static List cacheMap = Collections.synchronizedList(new ArrayList());

    /**
     * 定时保存审计记录
     */
    @Scheduled(fixedRate = 10000)
    public void saveAudit() {
        if(cacheMap.size()>0) {
            log.info(String.format("正在保存审计数据,当前审计集合数量为[%s]",cacheMap.size()));
            List temp=new ArrayList();
            if(cacheMap.size()<500) {
              temp.addAll(cacheMap);
            }
            else {
              temp.addAll(cacheMap.subList(0,500));
            }
            this.saveBatch(temp);
            cacheMap.removeAll(temp);
            log.info(String.format("保存完成,当前审计集合数量为[%s]",cacheMap.size()));
        }
    }

    /**
     * 新建审计日志
     * @param request
     * @param entity
     * @param idValue
     * @param auditFields
     */
    @Override
    public void createAudit(HttpServletRequest request, EntityBase entity, Object idValue, Map<String, Audit> auditFields) {
        IBZDataAudit dataAudit = new IBZDataAudit();
        dataAudit.setOppersonid(AuthenticationUser.getAuthenticationUser().getUserid());
        dataAudit.setOppersonname(String.format("%s[%s]", AuthenticationUser.getAuthenticationUser().getPersonname(), AuthenticationUser.getAuthenticationUser().getOrgname()));
        dataAudit.setAudittype("CREATE");
        dataAudit.setAuditobject(entity.getClass().getSimpleName());
        dataAudit.setAuditobjectdata(idValue);
        dataAudit.setOptime(new Timestamp(new Date().getTime()));
        if(request != null) {
            dataAudit.setIpaddress(getIpAddress(request, AuthenticationUser.getAuthenticationUser()));
        }
        dataAudit.setAuditinfo(getAuditInfo(entity, auditFields));
        dataAudit.setIsdatachanged(1);
        cacheMap.add(dataAudit);
    }

    /**
     * 更新审计日志
     * @param request
     * @param beforeEntity
     * @param serviceObj
     * @param idValue
     * @param auditFields
     */
    @SneakyThrows
    public void updateAudit(HttpServletRequest request, EntityBase beforeEntity, Object serviceObj, Object idValue, Map<String, Audit> auditFields) {
        //获取更新后的实体
        EntityBase afterEntity = getEntity(serviceObj, idValue);
        //获取更新后的审计内容
        String auditInfo = getUpdateAuditInfo(beforeEntity, afterEntity, auditFields);//比较更新前后差异内容
        int isDataChanged = 1;
        //审计内容是否发生变化
        if(StringUtils.isEmpty(auditInfo)) {
            isDataChanged = 0;
        }
        IBZDataAudit dataAudit = new IBZDataAudit();
        dataAudit.setOppersonid(AuthenticationUser.getAuthenticationUser().getUserid());
        dataAudit.setOppersonname(String.format("%s[%s]", AuthenticationUser.getAuthenticationUser().getPersonname(), AuthenticationUser.getAuthenticationUser().getOrgname()));
        dataAudit.setAudittype("UPDATE");
        dataAudit.setAuditobject(afterEntity.getClass().getSimpleName());
        dataAudit.setAuditobjectdata(idValue);
        dataAudit.setOptime(new Timestamp(new Date().getTime()));
        if(request!=null) {
            dataAudit.setIpaddress(getIpAddress(request, AuthenticationUser.getAuthenticationUser()));
        }
        dataAudit.setAuditinfo(auditInfo);
        dataAudit.setIsdatachanged(isDataChanged);
        cacheMap.add(dataAudit);
    }

    /**
     * 删除审计日志
     * @param request
     * @param entity
     * @param idValue
     * @param auditFields
     */
    public void removeAudit(HttpServletRequest request, EntityBase entity, Object idValue, Map<String, Audit> auditFields) {
        IBZDataAudit dataAudit = new IBZDataAudit();
        dataAudit.setOppersonid(AuthenticationUser.getAuthenticationUser().getUserid());
        dataAudit.setOppersonname(String.format("%s[%s]", AuthenticationUser.getAuthenticationUser().getPersonname(), AuthenticationUser.getAuthenticationUser().getOrgname()));
        dataAudit.setAudittype("REMOVE");
        dataAudit.setAuditobject(entity.getClass().getSimpleName());
        dataAudit.setAuditobjectdata(idValue);
        dataAudit.setOptime(new Timestamp(new Date().getTime()));
        if(request!=null) {
            dataAudit.setIpaddress(getIpAddress(request, AuthenticationUser.getAuthenticationUser()));
        }
        dataAudit.setAuditinfo(getAuditInfo(entity, auditFields));
        dataAudit.setIsdatachanged(1);
        cacheMap.add(dataAudit);
    }

    private String getAuditInfo(EntityBase entity, Map<String, Audit> auditFields) {
        String auditResult = "";
        if(auditFields.size() == 0) {
            return auditResult;
        }
        Map<String, DEField> deFields = DEFieldCacheMap.getDEFields(entity.getClass());
        if(deFields.size() == 0) {
            return auditResult;
        }
        JSONArray auditFieldArray = new JSONArray();
        for (Map.Entry<String, Audit> auditField : auditFields.entrySet()) {
            Object objFieldName = auditField.getKey();
            String fieldName = String.valueOf(objFieldName);
            DEField deField = null;
            if(deFields.containsKey(fieldName)) {
                deField = deFields.get(fieldName);
            }
            if(ObjectUtils.isEmpty(deField)) {
                continue;
            }
            Object value = dataTransfer(entity.get(fieldName), deField.fieldType(), deField.format());
            if(!StringUtils.isEmpty(value)) {
                JSONObject auditFieldObj = new JSONObject();
                auditFieldObj.put("field", deField.value());
                auditFieldObj.put("value", value);
                if(!StringUtils.isEmpty(deField.dict())) {
                    auditFieldObj.put("dict", deField.dict());
                }
                auditFieldArray.add(auditFieldObj);
            }
        }
        if(auditFieldArray.size()>0) {
            auditResult = auditFieldArray.toString();
        }
        return auditResult;
    }

    /**
     * 获取更新审计内容
     * @param oldData
     * @param newData
     * @param auditFields
     * @return
     */
    private String getUpdateAuditInfo(EntityBase oldData, EntityBase newData, Map<String, Audit> auditFields){
        String auditResult = "";
        JSONArray auditFieldArray = new JSONArray();
        if(auditFields.size() == 0) {
            return auditResult;
        }

        Map<String, DEField> deFields = DEFieldCacheMap.getDEFields(oldData.getClass());
        if(deFields.size() == 0){
            return auditResult;
        }

        for (Map.Entry<String, Audit> auditField : auditFields.entrySet()) {
            Object objFieldName = auditField.getKey();//获取注解字段
            String fieldName = String.valueOf(objFieldName); //属性名称
            DEField deField = null;
            if(deFields.containsKey(fieldName)) {
                deField = deFields.get(fieldName);
            }
            if(ObjectUtils.isEmpty(deField)) {
                continue;
            }
            Object oldValue = oldData.get(fieldName);//老属性值
            Object newValue = newData.get(fieldName);//新属性值
            if(!compare(oldValue, newValue)) {
                oldValue = dataTransfer(oldValue, deField.fieldType(), deField.format());//属性值转换
                newValue = dataTransfer(newValue, deField.fieldType(), deField.format());//属性值转换
                JSONObject auditFieldObj = new JSONObject();
                auditFieldObj.put("field", deField.value());
                auditFieldObj.put("beforevalue", oldValue);
                auditFieldObj.put("value", newValue);
                if(!StringUtils.isEmpty(deField.dict())) {
                    auditFieldObj.put("dict", deField.dict());
                }
                auditFieldArray.add(auditFieldObj);
            }
        }
        if(auditFieldArray.size()>0) {
            auditResult = auditFieldArray.toString();
        }
        return auditResult;
    }

    /**
     * 数据转换
     * @param value 转换值
     * @param dataType 转换字段类型
     * @param strFormat   转换字段格式化文本
     * @return
     */
    private String dataTransfer(Object value, String dataType, String strFormat) {
        if(value==null) {
            return "";
        }
        String transResult=value.toString();
        if((dataType.equals("DATE") || dataType.equals("DATETIME") || dataType.equals("TIME")) && (!StringUtils.isEmpty(strFormat))) {  //时间类型转换
            Timestamp timestamp = (Timestamp)value;
            Date date = timestamp;
            SimpleDateFormat format = new SimpleDateFormat(strFormat);
            transResult = format.format(date);
        }
        return transResult;
    }

    /**
     * 对象比较
     * @param sourceObj 比较源对象
     * @param targetObj 比较目标对象
     * @return
     */
    private boolean compare(Object sourceObj, Object targetObj) {
        if(sourceObj == null && targetObj == null) {
            return true;
        }
        if(sourceObj == null && targetObj != null) {
            return false;
        }
        return sourceObj.equals(targetObj);
    }

    /**
     * 获取实体
     * @param service
     * @param id
     * @return
     */
    @SneakyThrows
    private EntityBase getEntity(Object service, Object id) {
        EntityBase entity = null;
        if(!ObjectUtils.isEmpty(service)) {
            EvaluationContext oldContext = new StandardEvaluationContext();
            oldContext.setVariable("service",service);
            oldContext.setVariable("id",id);
            Expression oldExp = parser.parseExpression("#service.get(#id)");
            return oldExp.getValue(oldContext, EntityBase.class);
        }
        return entity;
    }

    /**
     * 获取Ip地址
     * @param request
     * @return
     */
    public String getIpAddress(HttpServletRequest request, AuthenticationUser authenticationUser) {
        //客户端有提交ip,以提交的ip为准
        if(authenticationUser != null && !StringUtils.isEmpty(authenticationUser.getAddr())) {
            return authenticationUser.getAddr();
        }
        if(request == null) {
            return "";
        }
        String Xip = request.getHeader("X-Real-IP");
        String XFor = request.getHeader("X-Forwarded-For");
        if(!StringUtils.isEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
            //多次反向代理后会有多个ip值,第一个ip才是真实ip
            int index = XFor.indexOf(",");
            if(index != -1){
                return XFor.substring(0,index);
            }else{
                return XFor;
            }
        }
        XFor = Xip;
        if(!StringUtils.isEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
            return XFor;
        }
        if (StringUtils.isEmpty(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isEmpty(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isEmpty(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getRemoteAddr();
        }
        return XFor;
    }
}