|
@@ -1,27 +1,20 @@
|
|
|
package com.usky.system.controller.web;
|
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Collection;
|
|
|
-import java.util.Collections;
|
|
|
+import java.util.*;
|
|
|
import java.util.List;
|
|
|
-
|
|
|
+import java.util.stream.Collectors;
|
|
|
import com.usky.common.core.bean.ApiResult;
|
|
|
import com.usky.common.core.constants.CacheConstants;
|
|
|
-import com.usky.common.log.annotation.Log;
|
|
|
-import com.usky.common.log.enums.BusinessType;
|
|
|
+import com.usky.common.core.utils.StringUtils;
|
|
|
import com.usky.common.redis.core.RedisService;
|
|
|
-import com.usky.common.security.annotation.RequiresPermissions;
|
|
|
import com.usky.system.controller.web.page.TableDataInfo;
|
|
|
import com.usky.system.domain.SysUserOnline;
|
|
|
import com.usky.system.model.LoginUser;
|
|
|
import com.usky.system.service.ISysUserOnlineService;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.web.bind.annotation.DeleteMapping;
|
|
|
-import org.springframework.web.bind.annotation.GetMapping;
|
|
|
-import org.springframework.web.bind.annotation.PathVariable;
|
|
|
-import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
-import org.springframework.web.bind.annotation.RestController;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
|
/**
|
|
|
* 在线用户监控
|
|
@@ -29,63 +22,185 @@ import org.springframework.web.bind.annotation.RestController;
|
|
|
*/
|
|
|
@RestController
|
|
|
@RequestMapping("/online")
|
|
|
-public class SysUserOnlineController extends BaseController
|
|
|
-{
|
|
|
+public class SysUserOnlineController {
|
|
|
+ private final Logger logger = LoggerFactory.getLogger(SysUserOnlineController.class);
|
|
|
+
|
|
|
@Autowired
|
|
|
private ISysUserOnlineService userOnlineService;
|
|
|
|
|
|
@Autowired
|
|
|
private RedisService redisService;
|
|
|
|
|
|
- @RequiresPermissions("monitor:online:list")
|
|
|
+ private TableDataInfo getDataTable(List<SysUserOnline> userOnlineList, int pageNum, int pageSize, long total) {
|
|
|
+ TableDataInfo dataInfo = new TableDataInfo();
|
|
|
+ dataInfo.setRows(userOnlineList);
|
|
|
+ dataInfo.setTotal(total);
|
|
|
+ dataInfo.setPageNum(pageNum);
|
|
|
+ dataInfo.setPageSize(pageSize);
|
|
|
+ dataInfo.setPages((int) Math.ceil((double) total / pageSize));
|
|
|
+ return dataInfo;
|
|
|
+ }
|
|
|
+
|
|
|
@GetMapping("/list")
|
|
|
- public ApiResult<TableDataInfo> list(String ipaddr, String userName)
|
|
|
- {
|
|
|
- Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
|
|
|
- List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
|
|
|
- for (String key : keys)
|
|
|
- {
|
|
|
- LoginUser user = redisService.getCacheObject(key);
|
|
|
- if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
|
|
|
- {
|
|
|
- if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
|
|
|
- {
|
|
|
- userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
|
|
|
- }
|
|
|
+ public ApiResult<TableDataInfo> list(@RequestParam(required = false, defaultValue = "1") Integer page,
|
|
|
+ @RequestParam(required = false, defaultValue = "10") Integer size,
|
|
|
+ @RequestParam(required = false) String ipaddr,
|
|
|
+ @RequestParam(required = false) String userName) {
|
|
|
+ try {
|
|
|
+ Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
|
|
|
+ if (keys == null || keys.isEmpty()) {
|
|
|
+ logger.error("Redis密钥为null或为空");
|
|
|
+ return ApiResult.error("SYS-0000", "Redis密钥为null或为空");
|
|
|
}
|
|
|
- else if (StringUtils.isNotEmpty(ipaddr))
|
|
|
- {
|
|
|
- if (StringUtils.equals(ipaddr, user.getIpaddr()))
|
|
|
- {
|
|
|
- userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
|
|
|
+ Map<String, List<SysUserOnline>> userOnlineMap = new HashMap<>();
|
|
|
+
|
|
|
+ for (String key : keys) {
|
|
|
+ // 检查键是否存在并且未过期
|
|
|
+ if (redisService.hasKey(key)) {
|
|
|
+ LoginUser user = redisService.getCacheObject(key);
|
|
|
+ if (user != null) {
|
|
|
+ if (ipaddr != null && !ipaddr.equals(user.getIpaddr())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (userName != null && !userName.equals(user.getUsername())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ SysUserOnline online = userOnlineService.loginUserToUserOnline(user);
|
|
|
+ if (online != null) {
|
|
|
+ List<SysUserOnline> list = userOnlineMap.computeIfAbsent(user.getUsername(), k -> new ArrayList<>());
|
|
|
+ list.add(online);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- else if (StringUtils.isNotEmpty(userName))
|
|
|
- {
|
|
|
- if (StringUtils.equals(userName, user.getUsername()))
|
|
|
- {
|
|
|
- userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
|
|
|
+
|
|
|
+ List<SysUserOnline> userOnlineList = new ArrayList<>();
|
|
|
+ for (Map.Entry<String, List<SysUserOnline>> entry : userOnlineMap.entrySet()) {
|
|
|
+ List<SysUserOnline> sortedList = entry.getValue();
|
|
|
+ sortedList.sort(Comparator.comparing(SysUserOnline::getLoginTime).reversed());
|
|
|
+ if (!sortedList.isEmpty()) {
|
|
|
+ SysUserOnline lastOnline = sortedList.get(0);
|
|
|
+ lastOnline.setLoginCount(sortedList.size()); // 设置登录次数
|
|
|
+ userOnlineList.add(lastOnline);
|
|
|
}
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
|
|
|
+
|
|
|
+ // 按照登录时间降序排序
|
|
|
+ userOnlineList.sort(Comparator.comparing(SysUserOnline::getLoginTime).reversed());
|
|
|
+
|
|
|
+ long total = userOnlineList.size();
|
|
|
+ int start = (page - 1) * size;
|
|
|
+ int end = Math.min(start + size, (int) total);
|
|
|
+ List<SysUserOnline> pageList = userOnlineList.subList(start, end);
|
|
|
+
|
|
|
+ return ApiResult.success(getDataTable(pageList, page, size, total));
|
|
|
+ } catch (Exception ex) {
|
|
|
+ logger.error("处理/online/list错误", ex);
|
|
|
+ return ApiResult.error("SYS-0001", "内部系统错误", ex.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @GetMapping("/history")
|
|
|
+ public ApiResult<TableDataInfo> listOtherLogins(@RequestParam Long userid,
|
|
|
+ @RequestParam(required = false, defaultValue = "1") Integer page,
|
|
|
+ @RequestParam(required = false, defaultValue = "10") Integer size) {
|
|
|
+ try {
|
|
|
+ Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
|
|
|
+ if (keys == null || keys.isEmpty()) {
|
|
|
+ logger.error("Redis密钥为null或为空");
|
|
|
+ return ApiResult.error("SYS-0000", "Redis密钥为null或为空");
|
|
|
}
|
|
|
+ List<SysUserOnline> userOnlineList = new ArrayList<>();
|
|
|
+
|
|
|
+ for (String key : keys) {
|
|
|
+ if (redisService.hasKey(key)) {
|
|
|
+ LoginUser user = redisService.getCacheObject(key);
|
|
|
+ if (user != null && user.getUserid().equals(userid)) {
|
|
|
+ SysUserOnline online = userOnlineService.loginUserToUserOnline(user);
|
|
|
+ if (online != null) {
|
|
|
+ userOnlineList.add(online);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按照登录时间降序排序
|
|
|
+ userOnlineList.sort(Comparator.comparing(SysUserOnline::getLoginTime).reversed());
|
|
|
+ // 排除最后一条记录,只保留其他记录
|
|
|
+// if (!userOnlineList.isEmpty()) {
|
|
|
+// userOnlineList = userOnlineList.subList(1, userOnlineList.size());
|
|
|
+// }
|
|
|
+
|
|
|
+ long total = userOnlineList.size();
|
|
|
+ int start = (page - 1) * size;
|
|
|
+ int end = Math.min(start + size, (int) total);
|
|
|
+ List<SysUserOnline> pageList = userOnlineList.subList(start, end);
|
|
|
+
|
|
|
+ return ApiResult.success(getDataTable(pageList, page, size, total));
|
|
|
+ } catch (Exception ex) {
|
|
|
+ logger.error("处理/online/listOtherLogins错误", ex);
|
|
|
+ return ApiResult.error("SYS-0001", "内部服务器错误", ex.getMessage());
|
|
|
}
|
|
|
- Collections.reverse(userOnlineList);
|
|
|
- userOnlineList.removeAll(Collections.singleton(null));
|
|
|
- return ApiResult.success(getDataTable(userOnlineList));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 强退用户
|
|
|
*/
|
|
|
- @RequiresPermissions("monitor:online:forceLogout")
|
|
|
- @Log(title = "在线用户", businessType = BusinessType.FORCE)
|
|
|
+// @RequiresPermissions("monitor:online:forceLogout")
|
|
|
@DeleteMapping("/{tokenId}")
|
|
|
- public ApiResult forceLogout(@PathVariable String tokenId)
|
|
|
- {
|
|
|
- redisService.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
|
|
|
- return ApiResult.success();
|
|
|
+ public ApiResult forceLogout(@PathVariable String tokenId) {
|
|
|
+ try {
|
|
|
+ if (StringUtils.isBlank(tokenId)) {
|
|
|
+ logger.error("强制注销时Token为空");
|
|
|
+ return ApiResult.error("SYS-0004", "强制注销需要Token");
|
|
|
+ }
|
|
|
+
|
|
|
+ String key = CacheConstants.LOGIN_TOKEN_KEY + tokenId;
|
|
|
+ boolean deleted = redisService.deleteObject(key);
|
|
|
+ if (deleted) {
|
|
|
+ logger.info("tokenId为 {} 的用户已被强制注销.", tokenId);
|
|
|
+ return ApiResult.success();
|
|
|
+ } else {
|
|
|
+ logger.warn("未能找到并删除tokenId为 {} 的用户会话", tokenId);
|
|
|
+ return ApiResult.error("SYS-0002", "未找到会话或已删除会话");
|
|
|
+ }
|
|
|
+ } catch (Exception ex) {
|
|
|
+ logger.error("处理tokenId {} 的forceLogout时出错", tokenId, ex);
|
|
|
+ return ApiResult.error("SYS-0003", "强制注销时出现内部系统错误", ex.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @DeleteMapping("/logoutMany/{userid}")
|
|
|
+ public ApiResult forceLogoutMany(@PathVariable Long userid,
|
|
|
+ @RequestParam(required = false, defaultValue = "1") Integer page,
|
|
|
+ @RequestParam(required = false, defaultValue = "999") Integer size) {
|
|
|
+ try {
|
|
|
+ ApiResult<TableDataInfo> apiResult = listOtherLogins(userid, page, size);
|
|
|
+ if (apiResult.isSuccess() && apiResult.getData() != null) {
|
|
|
+ TableDataInfo tableDataInfo = apiResult.getData();
|
|
|
+ List<SysUserOnline> userOnlineList = (List<SysUserOnline>) tableDataInfo.getRows();
|
|
|
+ List<String> tokenIds = userOnlineList.stream()
|
|
|
+ .map(SysUserOnline::getTokenId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 执行强退操作
|
|
|
+ for (String tokenId : tokenIds) {
|
|
|
+ String key = CacheConstants.LOGIN_TOKEN_KEY + tokenId;
|
|
|
+ boolean deleted = redisService.deleteObject(key);
|
|
|
+ if (deleted) {
|
|
|
+ logger.info("tokenId为 {} 的用户已被强制注销.", tokenId);
|
|
|
+ } else {
|
|
|
+ logger.warn("未能找到并删除tokenId为 {} 的用户会话", tokenId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ApiResult.success("已强制注销所有选中token.");
|
|
|
+ } else {
|
|
|
+ logger.error("调用 listOtherLogins 方法失败,原因:{}", apiResult.getMsg());
|
|
|
+ return ApiResult.error("SYS-0003", "调用历史记录接口失败", apiResult.getMsg());
|
|
|
+ }
|
|
|
+ } catch (Exception ex) {
|
|
|
+ logger.error("处理forceLogoutMany时出错", ex);
|
|
|
+ return ApiResult.error("SYS-0003", "强制注销时出现内部系统错误", ex.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
+}
|