package com.vincent.rsf.server.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.server.common.domain.BaseParam; import com.vincent.rsf.server.common.domain.PageParam; import com.vincent.rsf.server.common.domain.PageResult; import com.vincent.rsf.server.system.entity.User; import com.vincent.rsf.server.system.mapper.UserMapper; import com.vincent.rsf.server.system.service.RoleMenuService; import com.vincent.rsf.server.system.service.UserRoleService; import com.vincent.rsf.server.system.service.UserService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Service("userService") public class UserServiceImpl extends ServiceImpl implements UserService { /** 批量查询缓存:key = 排序后的 ids 拼接,value = (过期时间戳, 用户列表),TTL 5 分钟 */ private static final long CACHE_TTL_MS = 5 * 60 * 1000L; private static final ConcurrentHashMap>> USER_MANY_CACHE = new ConcurrentHashMap<>(64); @Resource private UserRoleService userRoleService; @Resource private RoleMenuService roleMenuService; @Resource private BCryptPasswordEncoder bCryptPasswordEncoder; @Override public PageResult pageRel(PageParam pageParam) { return new PageResult<>(this.baseMapper.selectPageRel(pageParam, pageParam.checkoutMap()), pageParam.getTotal()); } @Override public User getByUsername(String username, Long tenantId) { if (Cools.isEmpty(username)) { return null; } return baseMapper.selectByUsernameWithoutTenant(username, tenantId); } @Override public User getByEmail(String email, Long tenantId) { if (Cools.isEmpty(email)) { return null; } return baseMapper.selectByEmailWithoutTenant(email, tenantId); } @Override public User setUserAuthInfo(User user) { if (user != null) { user.setRoles(userRoleService.listByUserId(user.getId())); user.setAuthorities(roleMenuService.listMenuByUserId(user.getId(), null)); } return user; } @Override public boolean comparePassword(String dbPassword, String inputPassword) { return bCryptPasswordEncoder.matches(inputPassword, dbPassword); } @Override public String encodePassword(String password) { return password == null ? null : bCryptPasswordEncoder.encode(password); } @Override public User selectByUsernameWithoutTenant(String username, Long tenantId) { return baseMapper.selectByUsernameWithoutTenant(username,tenantId); } @Override public List listByIdsCached(Collection ids) { if (ids == null || ids.isEmpty()) { return Collections.emptyList(); } String key = ids.stream().sorted().map(Object::toString).collect(Collectors.joining(",")); long now = System.currentTimeMillis(); CacheEntry> entry = USER_MANY_CACHE.get(key); if (entry != null && entry.expireAt > now) { return entry.data; } List list = listByIds(ids); USER_MANY_CACHE.put(key, new CacheEntry<>(now + CACHE_TTL_MS, list)); return list; } private static class CacheEntry { final long expireAt; final T data; CacheEntry(long expireAt, T data) { this.expireAt = expireAt; this.data = data; } } }