VersionCheckAspect.java 5.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
package cn.ibizlab.util.aspect;

import lombok.SneakyThrows;
import cn.ibizlab.util.annotation.VersionCheck;
import cn.ibizlab.util.domain.EntityBase;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.RuleUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
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.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * 数据库版本检查
 */
@Aspect
@Order(50)
@Component
public class VersionCheckAspect
{
    private final ExpressionParser parser = new SpelExpressionParser();
    private final String IgnoreField = "ignoreversioncheck";

    @SneakyThrows
    @Before("execution(* cn.ibizlab.*.rest.*.update(..)) &&  @annotation(versionCheck)")
    public void BeforeUpdate(JoinPoint point, VersionCheck versionCheck) {
        Object[] args = point.getArgs();
        Object id = args[0];
        Object dto = args[1];
        if(ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(dto)) {
            return;
        }
        String versionField = versionCheck.versionfield();
        if(StringUtils.isEmpty(versionField)) {
            return;
        }
        versionCheck(versionCheck,point.getTarget(), dto, id);
    }

    @SneakyThrows
    @Before("execution(* cn.ibizlab.*.rest.*.updateBy*(..)) &&  @annotation(versionCheck)")
    public void BeforeUpdateBy(JoinPoint point, VersionCheck versionCheck) {
        Object[] args = point.getArgs();
        if(args.length>=2) {
            Object id = args[args.length-2];
            Object dto = args[args.length-1];
            if(ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(dto)) {
                return;
            }
            String versionField = versionCheck.versionfield();
            if(StringUtils.isEmpty(versionField)) {
                return;
            }
            versionCheck(versionCheck, point.getTarget(), dto, id);
        }
    }

    private void versionCheck(VersionCheck versionCheck, Object resource, Object dto, Object id) {
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("dto", dto);
        //忽略版本检查
        Expression dtoParamsExp = parser.parseExpression("#dto.extensionparams");
        Map dtoParam = dtoParamsExp.getValue(context, Map.class);
        if(!ObjectUtils.isEmpty(dtoParam) && !ObjectUtils.isEmpty(dtoParam.get(IgnoreField)) && dtoParam.get(IgnoreField).equals(1)) {
            return;
        }
        Expression newExp = parser.parseExpression(String.format("#dto.%s", versionCheck.versionfield()));
        Object newVersion = newExp.getValue(context);
        if(ObjectUtils.isEmpty(newVersion)) {
            return;
        }
        //进行版本检查
        Object oldVersion = getDBVersion(versionCheck,getService(resource, versionCheck.entity()), id);
        if(!ObjectUtils.isEmpty(oldVersion)) {
            if(RuleUtils.gt(newVersion, oldVersion)) {
                throw new BadRequestAlertException("数据已变更,可能后台数据已被修改,请重新加载数据", "VersionCheckAspect", "versionCheck");
            }
        }
    }

    /**
     * 获取实体服务对象
     * @param resource
     * @param entity
     * @return
     */
    @SneakyThrows
    private Object getService(Object resource, String entity) {
        Object service = null;
        Field[] fields = resource.getClass().getDeclaredFields();
        for(Field field : fields) {
            if(field.getModifiers()==1 && field.getName().equalsIgnoreCase(String.format("%sService",entity))) {
                service = field.get(resource);
                break;
            }
        }
        return service;
    }

    /**
     * 获取数据库版本
     * @param versionCheck
     * @param service
     * @param id
     * @return
     */
    @SneakyThrows
    private Object getDBVersion(VersionCheck versionCheck, Object service, Object id) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Timestamp dbVersion = null;
        String versionField = versionCheck.versionfield();
        if(!ObjectUtils.isEmpty(service)) {
            EvaluationContext oldContext = new StandardEvaluationContext();
            oldContext.setVariable("service", service);
            oldContext.setVariable("id", id);
            Expression oldExp = parser.parseExpression("#service.get(#id)");
            EntityBase oldEntity = oldExp.getValue(oldContext, EntityBase.class);
            Object oldDate = oldEntity.get(versionField);
            if(oldDate!=null && oldDate instanceof Timestamp) {
                Timestamp db_time = (Timestamp) oldDate;
                Date db_date = sdf.parse(sdf.format(db_time));
                dbVersion = new Timestamp(db_date.getTime());
            }
        }
        return dbVersion;
    }
}