package com.oying.modules.system.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.oying.modules.security.service.UserCacheManager; import com.oying.modules.security.service.dto.AuthorityDto; import com.oying.modules.system.domain.Menu; import com.oying.modules.system.domain.Role; import com.oying.modules.system.domain.User; import com.oying.modules.system.domain.dto.RoleQueryCriteria; import com.oying.modules.system.mapper.RoleDeptMapper; import com.oying.modules.system.mapper.RoleMapper; import com.oying.modules.system.mapper.RoleMenuMapper; import com.oying.modules.system.mapper.UserMapper; import com.oying.utils.*; import lombok.RequiredArgsConstructor; import com.oying.exception.BadRequestException; import com.oying.exception.EntityExistException; import com.oying.modules.system.service.RoleService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * @author Z * @date 2018-12-03 */ @Service @RequiredArgsConstructor public class RoleServiceImpl extends ServiceImpl implements RoleService { private final RoleMapper roleMapper; private final RoleDeptMapper roleDeptMapper; private final RoleMenuMapper roleMenuMapper; private final RedisUtils redisUtils; private final UserMapper userMapper; private final UserCacheManager userCacheManager; @Override public List queryAll() { return roleMapper.queryAll(); } @Override public List queryAll(RoleQueryCriteria criteria) { return roleMapper.findAll(criteria); } @Override public PageResult queryAll(RoleQueryCriteria criteria, Page page) { criteria.setOffset(page.offset()); List roles = roleMapper.findAll(criteria); Long total = roleMapper.countAll(criteria); return PageUtil.toPage(roles, total); } @Override public Role findById(long id) { String key = CacheKey.ROLE_ID + id; Role role = redisUtils.get(key, Role.class); if (role == null) { role = roleMapper.findById(id); redisUtils.set(key, role, 1, TimeUnit.DAYS); } return role; } @Override @Transactional(rollbackFor = Exception.class) public void create(Role resources) { if (roleMapper.findByName(resources.getName()) != null) { throw new EntityExistException(Role.class, "username", resources.getName()); } save(resources); // 判断是否有机构数据,若有,则需创建关联 } @Override @Transactional(rollbackFor = Exception.class) public void update(Role resources) { Role role = getById(resources.getId()); Role role1 = roleMapper.findByName(resources.getName()); if (role1 != null && !role1.getId().equals(role.getId())) { throw new EntityExistException(Role.class, "username", resources.getName()); } role.setName(resources.getName()); role.setDescription(resources.getDescription()); role.setDataScope(resources.getDataScope()); role.setLevel(resources.getLevel()); // 更新 saveOrUpdate(role); // 删除关联机构数据 roleDeptMapper.deleteByRoleId(resources.getId()); // 判断是否有机构数据,若有,则需更新关联 // 更新相关缓存 delCaches(role.getId(), null); } @Override public void updateMenu(Role role) { List users = userMapper.findByRoleId(role.getId()); // 更新菜单 roleMenuMapper.deleteByRoleId(role.getId()); // 判断是否为空 if(CollUtil.isNotEmpty(role.getMenus())){ roleMenuMapper.insertData(role.getId(), role.getMenus()); } // 更新缓存 delCaches(role.getId(), users); } @Override @Transactional(rollbackFor = Exception.class) public void delete(Set ids) { for (Long id : ids) { // 更新相关缓存 delCaches(id, null); } removeBatchByIds(ids); // 删除角色机构关联数据、角色菜单关联数据 roleDeptMapper.deleteByRoleIds(ids); roleMenuMapper.deleteByRoleIds(ids); } @Override public List findByUsersId(Long userId) { String key = CacheKey.ROLE_USER + userId; List roles = redisUtils.getList(key, Role.class); if (CollUtil.isEmpty(roles)) { roles = roleMapper.findByUserId(userId); redisUtils.set(key, roles, 1, TimeUnit.DAYS); } return roles; } @Override public Integer findByRoles(Set roles) { if (CollUtil.isEmpty(roles)) { return Integer.MAX_VALUE; } Set roleSet = new HashSet<>(); for (Role role : roles) { roleSet.add(findById(role.getId())); } return Collections.min(roleSet.stream().map(Role::getLevel).collect(Collectors.toList())); } @Override public List buildPermissions(User user) { String key = CacheKey.ROLE_AUTH + user.getId(); List authorityDtos = redisUtils.getList(key, AuthorityDto.class); if (CollUtil.isEmpty(authorityDtos)) { Set permissions = new HashSet<>(); // 如果是管理员直接返回 if (user.getIsAdmin()) { permissions.add("admin"); return permissions.stream().map(AuthorityDto::new) .collect(Collectors.toList()); } List roles = roleMapper.findByUserId(user.getId()); permissions = roles.stream().flatMap(role -> role.getMenus().stream()) .map(Menu::getPermission) .filter(StringUtils::isNotBlank).collect(Collectors.toSet()); authorityDtos = permissions.stream().map(AuthorityDto::new) .collect(Collectors.toList()); redisUtils.set(key, authorityDtos, 1, TimeUnit.HOURS); } return authorityDtos; } @Override public void download(List roles, HttpServletResponse response) throws IOException { List> list = new ArrayList<>(); for (Role role : roles) { Map map = new LinkedHashMap<>(); map.put("角色名称", role.getName()); map.put("角色级别", role.getLevel()); map.put("描述", role.getDescription()); map.put("创建日期", role.getCreateTime()); list.add(map); } FileUtil.downloadExcel(list, response); } @Override public void verification(Set ids) { if (userMapper.countByRoles(ids) > 0) { throw new BadRequestException("所选角色存在用户关联,请解除关联再试!"); } } @Override public List findByMenuId(Long menuId) { return roleMapper.findByMenuId(menuId); } /** * 清理缓存 * @param id / */ public void delCaches(Long id, List users) { users = CollectionUtil.isEmpty(users) ? userMapper.findByRoleId(id) : users; if (CollectionUtil.isNotEmpty(users)) { users.forEach(item -> userCacheManager.cleanUserCache(item.getUsername())); Set userIds = users.stream().map(User::getId).collect(Collectors.toSet()); redisUtils.delByKeys(CacheKey.DATA_USER, userIds); redisUtils.delByKeys(CacheKey.MENU_USER, userIds); redisUtils.delByKeys(CacheKey.ROLE_AUTH, userIds); redisUtils.delByKeys(CacheKey.ROLE_USER, userIds); } redisUtils.del(CacheKey.ROLE_ID + id); } }