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
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;
21 22 23
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
24 25 26 27 28 29 30 31 32 33 34
import java.util.Map;

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

    @SneakyThrows
    @Before("execution(* cn.ibizlab.*.rest.*.update(..)) &&  @annotation(versionCheck)")
39
    public void BeforeUpdate(JoinPoint point, VersionCheck versionCheck) {
40
        Object[] args = point.getArgs();
41 42 43
        Object id = args[0];
        Object dto = args[1];
        if(ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(dto)) {
44
            return;
45 46 47
        }
        String versionField = versionCheck.versionfield();
        if(StringUtils.isEmpty(versionField)) {
48
            return;
49 50
        }
        versionCheck(versionCheck,point.getTarget(), dto, id);
51 52 53 54
    }

    @SneakyThrows
    @Before("execution(* cn.ibizlab.*.rest.*.updateBy*(..)) &&  @annotation(versionCheck)")
55
    public void BeforeUpdateBy(JoinPoint point, VersionCheck versionCheck) {
56
        Object[] args = point.getArgs();
57 58 59 60
        if(args.length>=2) {
            Object id = args[args.length-2];
            Object dto = args[args.length-1];
            if(ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(dto)) {
61
                return;
62 63 64
            }
            String versionField = versionCheck.versionfield();
            if(StringUtils.isEmpty(versionField)) {
65
                return;
66 67
            }
            versionCheck(versionCheck, point.getTarget(), dto, id);
68 69 70
        }
    }

71
    private void versionCheck(VersionCheck versionCheck, Object resource, Object dto, Object id) {
72
        EvaluationContext context = new StandardEvaluationContext();
73
        context.setVariable("dto", dto);
74 75
        //忽略版本检查
        Expression dtoParamsExp = parser.parseExpression("#dto.extensionparams");
76 77
        Map dtoParam = dtoParamsExp.getValue(context, Map.class);
        if(!ObjectUtils.isEmpty(dtoParam) && !ObjectUtils.isEmpty(dtoParam.get(IgnoreField)) && dtoParam.get(IgnoreField).equals(1)) {
78
            return;
79 80 81 82
        }
        Expression newExp = parser.parseExpression(String.format("#dto.%s", versionCheck.versionfield()));
        Object newVersion = newExp.getValue(context);
        if(ObjectUtils.isEmpty(newVersion)) {
83
            return;
84
        }
85
        //进行版本检查
86 87 88 89 90
        Object oldVersion = getDBVersion(versionCheck,getService(resource, versionCheck.entity()), id);
        if(!ObjectUtils.isEmpty(oldVersion)) {
            if(RuleUtils.gt(newVersion, oldVersion)) {
                throw new BadRequestAlertException("数据已变更,可能后台数据已被修改,请重新加载数据", "VersionCheckAspect", "versionCheck");
            }
91 92 93 94 95 96 97 98 99 100
        }
    }

    /**
     * 获取实体服务对象
     * @param resource
     * @param entity
     * @return
     */
    @SneakyThrows
101
    private Object getService(Object resource, String entity) {
102
        Object service = null;
103 104 105 106
        Field[] fields = resource.getClass().getDeclaredFields();
        for(Field field : fields) {
            if(field.getModifiers()==1 && field.getName().equalsIgnoreCase(String.format("%sService",entity))) {
                service = field.get(resource);
107 108 109 110 111 112 113 114 115 116 117 118 119 120
                break;
            }
        }
        return service;
    }

    /**
     * 获取数据库版本
     * @param versionCheck
     * @param service
     * @param id
     * @return
     */
    @SneakyThrows
121
    private Object getDBVersion(VersionCheck versionCheck, Object service, Object id) {
122
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
123 124 125
        Timestamp dbVersion = null;
        String versionField = versionCheck.versionfield();
        if(!ObjectUtils.isEmpty(service)) {
126
            EvaluationContext oldContext = new StandardEvaluationContext();
127 128
            oldContext.setVariable("service", service);
            oldContext.setVariable("id", id);
129
            Expression oldExp = parser.parseExpression("#service.get(#id)");
130 131 132 133
            EntityBase oldEntity = oldExp.getValue(oldContext, EntityBase.class);
            Object oldDate = oldEntity.get(versionField);
            if(oldDate!=null && oldDate instanceof Timestamp) {
                Timestamp db_time = (Timestamp) oldDate;
134
                Date db_date = sdf.parse(sdf.format(db_time));
135
                dbVersion = new Timestamp(db_date.getTime());
136
            }
137 138 139 140
        }
        return dbVersion;
    }
}