liusheng
7 天以前 896d14b328059863b5cc668dfc6c1d375f59de59
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package com.ruoyi.framework.aspectj;
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.annotation.UniqueCheck;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
 
/**
 * 唯一性校验切面
 * 用于在新增操作前进行字段唯一性检查
 * 
 * @author ruoyi
 */
@Aspect
@Order(2)
@Component
public class UniqueCheckAspect
{
    protected Logger logger = LoggerFactory.getLogger(getClass());
 
    @Pointcut("@annotation(com.ruoyi.common.annotation.UniqueCheck)")
    public void uniqueCheckPointCut()
    {
    }
 
    @Before("uniqueCheckPointCut()")
    public void doBefore(JoinPoint point) throws Throwable
    {
        handleUniqueCheck(point);
    }
 
    protected void handleUniqueCheck(JoinPoint joinPoint) throws Exception
    {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        UniqueCheck uniqueCheck = method.getAnnotation(UniqueCheck.class);
 
        if (uniqueCheck == null)
        {
            return;
        }
 
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0)
        {
            return;
        }
 
        // 获取第一个参数(通常是实体对象)
        Object entity = args[0];
        if (entity == null)
        {
            return;
        }
 
        // 校验实体类型
        Class<?> entityClass = uniqueCheck.entityClass();
        if (!entityClass.isInstance(entity))
        {
            logger.warn("实体类型不匹配, 期望: {}, 实际: {}", entityClass.getName(), entity.getClass().getName());
            return;
        }
 
        // 获取Service实例
        Class<?> serviceClass = uniqueCheck.serviceClass();
        IService service = (IService) SpringUtils.getBean(serviceClass);
 
        // 获取需要检查的字段
        String[] fields = uniqueCheck.fields();
        if (fields == null || fields.length == 0)
        {
            throw new ServiceException("UniqueCheck注解的fields属性不能为空");
        }
 
        // 构建查询条件
        QueryWrapper queryWrapper = Wrappers.query();
        StringBuilder messageBuilder = new StringBuilder();
        boolean hasCondition = false;
 
        for (int i = 0; i < fields.length; i++)
        {
            String fieldName = fields[i];
            Object fieldValue = getFieldValue(entity, fieldName);
 
            // 只有字段值不为空时才添加查询条件
            if (fieldValue != null && !"".equals(fieldValue))
            {
                // 使用字符串字段名,MyBatis-Plus会自动转换为数据库列名
                queryWrapper.eq(StringUtils.toUnderScoreCase(fieldName), fieldValue);
                hasCondition = true;
 
                if (messageBuilder.length() > 0)
                {
                    messageBuilder.append(",");
                }
                messageBuilder.append(fieldValue);
            }
        }
 
        // 如果没有有效的查询条件,直接返回
        if (!hasCondition)
        {
            return;
        }
 
        // 执行查询
        List list = service.list(queryWrapper);
        if (list != null && !list.isEmpty())
        {
            String message = uniqueCheck.message();
            // 简单的消息格式化
            if (message.contains("{value0}"))
            {
                message = message.replace("{value0}", messageBuilder.toString());
            }
            
            logger.warn("唯一性校验失败: {}", message);
            throw new ServiceException(message);
        }
    }
 
    /**
     * 通过反射获取实体字段值
     */
    private Object getFieldValue(Object entity, String fieldName) throws Exception
    {
        Class<?> clazz = entity.getClass();
        
        // 尝试获取字段
        Field field = null;
        while (clazz != null && field == null)
        {
            try
            {
                field = clazz.getDeclaredField(fieldName);
            }
            catch (NoSuchFieldException e)
            {
                clazz = clazz.getSuperclass();
            }
        }
 
        if (field == null)
        {
            throw new ServiceException("实体类中不存在字段: " + fieldName);
        }
 
        field.setAccessible(true);
        return field.get(entity);
    }
}