zhou zhou
2 天以前 a8df4c4a80781c02815021a840971ce4b15419f5
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
package com.vincent.rsf.server.manager.utils;
 
 
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.framework.common.SpringUtils;
import com.vincent.rsf.server.common.service.RedisService;
import com.vincent.rsf.server.system.entity.User;
import com.vincent.rsf.server.system.service.UserService;
 
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class buildPageRowsUtils {
 
    private static final String USER_NAME_CACHE_FLAG = "PAGE_ROWS_USER_NAME";
    private static final int USER_NAME_CACHE_TTL_SECONDS = 300;
 
    public static <T> Map<Long, String> userNameMap(List<T> records){
        if (Cools.isEmpty(records)) {
            return Collections.emptyMap();
        }
        Set<Long> collect = records.stream()
                .filter(Objects::nonNull)
                .flatMap(item -> Stream.of(
                        readUserId(item, "createBy"),
                        readUserId(item, "updateBy")
                ))
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
 
        Map<Long, String> userNameMap = loadUserNameMap(collect);
        fillUserNameFields(records, userNameMap);
        return userNameMap;
    }
 
    private static Long readUserId(Object record, String fieldName) {
        if (record == null || Cools.isEmpty(fieldName)) {
            return null;
        }
        Field field = Cools.getField(record.getClass(), fieldName);
        if (field == null) {
            return null;
        }
        boolean accessible = field.isAccessible();
        try {
            field.setAccessible(true);
            Object value = field.get(record);
            if (value instanceof Long) {
                return (Long) value;
            }
            if (value instanceof Number) {
                return ((Number) value).longValue();
            }
            if (value instanceof String && !((String) value).trim().isEmpty()) {
                return Long.parseLong(((String) value).trim());
            }
        } catch (IllegalAccessException | NumberFormatException ignored) {
            return null;
        } finally {
            field.setAccessible(accessible);
        }
        return null;
    }
 
    private static Map<Long, String> loadUserNameMap(Set<Long> userIds) {
        if (Cools.isEmpty(userIds)) {
            return Collections.emptyMap();
        }
        List<Long> normalizedUserIds = userIds.stream()
                .filter(Objects::nonNull)
                .toList();
        if (normalizedUserIds.isEmpty()) {
            return Collections.emptyMap();
        }
        RedisService redisService = getRedisService();
        Map<Long, String> userNameMap = new HashMap<>();
        List<Long> missingUserIds = new ArrayList<>();
        for (Long userId : normalizedUserIds) {
            String cachedUserName = getCachedUserName(redisService, userId);
            if (cachedUserName == null) {
                missingUserIds.add(userId);
                continue;
            }
            userNameMap.put(userId, cachedUserName);
        }
        if (missingUserIds.isEmpty()) {
            return userNameMap;
        }
        UserService userService = SpringUtils.getBean(UserService.class);
        Map<Long, String> loadedUserNameMap = userService.listByIds(missingUserIds)
                .stream()
                .filter(Objects::nonNull)
                .filter(user -> user.getId() != null && user.getNickname() != null)
                .collect(Collectors.toMap(User::getId, User::getNickname, (left, right) -> left));
        userNameMap.putAll(loadedUserNameMap);
        cacheUserNames(redisService, loadedUserNameMap);
        return userNameMap;
    }
 
    private static RedisService getRedisService() {
        try {
            return SpringUtils.getBean(RedisService.class);
        } catch (Exception ignored) {
            return null;
        }
    }
 
    private static String getCachedUserName(RedisService redisService, Long userId) {
        if (redisService == null || userId == null) {
            return null;
        }
        try {
            String value = redisService.getValue(USER_NAME_CACHE_FLAG, String.valueOf(userId));
            return Cools.isEmpty(value) ? null : value;
        } catch (Exception ignored) {
            return null;
        }
    }
 
    private static void cacheUserNames(RedisService redisService, Map<Long, String> userNameMap) {
        if (redisService == null || Cools.isEmpty(userNameMap)) {
            return;
        }
        userNameMap.forEach((userId, userName) -> {
            if (userId == null || Cools.isEmpty(userName)) {
                return;
            }
            try {
                redisService.setValue(USER_NAME_CACHE_FLAG, String.valueOf(userId), userName, USER_NAME_CACHE_TTL_SECONDS);
            } catch (Exception ignored) {
            }
        });
    }
 
    private static <T> void fillUserNameFields(List<T> records, Map<Long, String> userNameMap) {
        if (Cools.isEmpty(records) || Cools.isEmpty(userNameMap)) {
            return;
        }
        records.stream()
                .filter(Objects::nonNull)
                .forEach(record -> {
                    writeUserName(record, "createBy$", userNameMap.get(readUserId(record, "createBy")));
                    writeUserName(record, "updateBy$", userNameMap.get(readUserId(record, "updateBy")));
                });
    }
 
    private static void writeUserName(Object record, String fieldName, String userName) {
        if (record == null || Cools.isEmpty(fieldName) || userName == null) {
            return;
        }
        Field field = Cools.getField(record.getClass(), fieldName);
        if (field == null || !String.class.equals(field.getType())) {
            return;
        }
        boolean accessible = field.isAccessible();
        try {
            field.setAccessible(true);
            field.set(record, userName);
        } catch (IllegalAccessException ignored) {
        } finally {
            field.setAccessible(accessible);
        }
    }
}