完成主要在线 session 的功能

This commit is contained in:
YunaiV 2021-01-30 01:21:25 +08:00
parent ab94fe2d4b
commit 753c7678ee
34 changed files with 1349 additions and 1260 deletions

View File

@ -13,12 +13,10 @@ import com.ruoyi.common.core.controller.BaseController;
*/ */
@Controller @Controller
@RequestMapping("/tool/swagger") @RequestMapping("/tool/swagger")
public class SwaggerController extends BaseController public class SwaggerController extends BaseController {
{
@PreAuthorize("@ss.hasPermi('tool:swagger:view')") @PreAuthorize("@ss.hasPermi('tool:swagger:view')")
@GetMapping() @GetMapping()
public String index() public String index() {
{
return redirect("/swagger-ui.html"); return redirect("/swagger-ui.html");
} }
} }

View File

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 查询在线用户列表 // 查询在线用户列表
export function list(query) { export function list(query) {
return request({ return request({
url: '/monitor/online/list', url: '/system/user-session/page',
method: 'get', method: 'get',
params: query params: query
}) })
@ -12,7 +12,7 @@ export function list(query) {
// 强退用户 // 强退用户
export function forceLogout(tokenId) { export function forceLogout(tokenId) {
return request({ return request({
url: '/monitor/online/' + tokenId, url: '/system/user-session/delete?id=' + tokenId,
method: 'delete' method: 'delete'
}) })
} }

View File

@ -1,18 +1,18 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
<el-form-item label="登录地址" prop="ipaddr"> <el-form-item label="登录地址" prop="userIp">
<el-input <el-input
v-model="queryParams.ipaddr" v-model="queryParams.userIp"
placeholder="请输入登录地址" placeholder="请输入登录地址"
clearable clearable
size="small" size="small"
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="username">
<el-input <el-input
v-model="queryParams.userName" v-model="queryParams.username"
placeholder="请输入用户名称" placeholder="请输入用户名称"
clearable clearable
size="small" size="small"
@ -27,24 +27,17 @@
</el-form> </el-form>
<el-table <el-table
v-loading="loading" v-loading="loading"
:data="list.slice((pageNum-1)*pageSize,pageNum*pageSize)" :data="list"
style="width: 100%;" style="width: 100%;"
> >
<el-table-column label="序号" type="index" align="center"> <el-table-column label="会话编号" align="center" prop="id" width="300" />
<el-table-column label="登录名称" align="center" prop="username" width="100" />
<el-table-column label="部门名称" align="center" prop="deptName" width="100" />
<el-table-column label="登陆地址" align="center" prop="userIp" width="100" />
<el-table-column label="userAgent" align="center" prop="userAgent" :show-overflow-tooltip="true" />
<el-table-column label="登录时间" align="center" prop="createTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span> <span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="会话编号" align="center" prop="tokenId" :show-overflow-tooltip="true" />
<el-table-column label="登录名称" align="center" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="部门名称" align="center" prop="deptName" />
<el-table-column label="主机" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
<el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
<el-table-column label="浏览器" align="center" prop="browser" />
<el-table-column label="操作系统" align="center" prop="os" />
<el-table-column label="登录时间" align="center" prop="loginTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.loginTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@ -54,18 +47,18 @@
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleForceLogout(scope.row)" @click="handleForceLogout(scope.row)"
v-hasPermi="['monitor:online:forceLogout']" v-hasPermi="['system:user-session:delete']"
>强退</el-button> >强退</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" /> <pagination v-show="total>0" :total="total" :page.sync="pageNo" :limit.sync="pageSize" />
</div> </div>
</template> </template>
<script> <script>
import { list, forceLogout } from "@/api/monitor/online"; import { list, forceLogout } from "@/api/system/session";
export default { export default {
name: "Online", name: "Online",
@ -77,12 +70,12 @@ export default {
total: 0, total: 0,
// //
list: [], list: [],
pageNum: 1,
pageSize: 10,
// //
queryParams: { queryParams: {
ipaddr: undefined, pageNo: 1,
userName: undefined pageSize: 10,
userIp: undefined,
username: undefined
} }
}; };
}, },
@ -94,14 +87,14 @@ export default {
getList() { getList() {
this.loading = true; this.loading = true;
list(this.queryParams).then(response => { list(this.queryParams).then(response => {
this.list = response.rows; this.list = response.data.list;
this.total = response.total; this.total = response.data.total;
this.loading = false; this.loading = false;
}); });
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.pageNum = 1; this.pageNo = 1;
this.getList(); this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
@ -111,12 +104,12 @@ export default {
}, },
/** 强退按钮操作 */ /** 强退按钮操作 */
handleForceLogout(row) { handleForceLogout(row) {
this.$confirm('是否确认强退名称为"' + row.userName + '"的数据项?', "警告", { this.$confirm('是否确认强退名称为"' + row.username + '"的数据项?', "警告", {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning" type: "warning"
}).then(function() { }).then(function() {
return forceLogout(row.tokenId); return forceLogout(row.id);
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("强退成功"); this.msgSuccess("强退成功");

View File

@ -4,8 +4,14 @@ import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
import cn.iocoder.dashboard.modules.system.convert.auth.SysUserSessionConvert;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService;
import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService;
import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
import cn.iocoder.dashboard.util.collection.MapUtils;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -14,26 +20,50 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static cn.iocoder.dashboard.common.pojo.CommonResult.success; import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
import static cn.iocoder.dashboard.util.collection.CollectionUtils.convertList;
@Api("用户 Session API") @Api("用户 Session API")
@RestController @RestController
@RequestMapping("/user-session") @RequestMapping("/system/user-session")
public class SysUserSessionController { public class SysUserSessionController {
@Resource @Resource
private SysUserSessionService userSessionService; private SysUserSessionService userSessionService;
@Resource
private SysUserService userService;
@Resource
private SysDeptService deptService;
@ApiOperation("获得 Session 分页列表") @ApiOperation("获得 Session 分页列表")
@PreAuthorize("@ss.hasPermission('system:user-session:page')") @PreAuthorize("@ss.hasPermission('system:user-session:page')")
@GetMapping("/page") @GetMapping("/page")
public CommonResult<PageResult<SysUserSessionPageItemRespVO>> getUserSessionPage(@Validated SysUserSessionPageReqVO reqVO) { public CommonResult<PageResult<SysUserSessionPageItemRespVO>> getUserSessionPage(@Validated SysUserSessionPageReqVO reqVO) {
// 获得 Session 分页 // 获得 Session 分页
PageResult<SysUserSessionDO> sessionPage = userSessionService.getUserSessionPage(reqVO); PageResult<SysUserSessionDO> pageResult = userSessionService.getUserSessionPage(reqVO);
// // 获得拼接需要的数据
return null; Map<Long, SysUserDO> userMap = userService.getUserMap(
convertList(pageResult.getList(), SysUserSessionDO::getUserId));
Map<Long, SysDeptDO> deptMap = deptService.getDeptMap(
convertList(userMap.values(), SysUserDO::getDeptId));
// 拼接结果返回
List<SysUserSessionPageItemRespVO> sessionList = new ArrayList<>(pageResult.getList().size());
pageResult.getList().forEach(session -> {
SysUserSessionPageItemRespVO respVO = SysUserSessionConvert.INSTANCE.convert(session);
sessionList.add(respVO);
// 设置用户账号
MapUtils.findAndThen(userMap, session.getUserId(), user -> {
respVO.setUsername(user.getUsername());
// 设置用户部门
MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> respVO.setDeptName(dept.getName()));
});
});
return success(new PageResult<>(sessionList, pageResult.getTotal()));
} }
@ApiOperation("删除 Session") @ApiOperation("删除 Session")

View File

@ -8,6 +8,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.Date;
@ApiModel(value = "用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息") @ApiModel(value = "用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -25,7 +27,7 @@ public class SysUserSessionPageItemRespVO extends PageParam {
private String userAgent; private String userAgent;
@ApiModelProperty(value = "登陆时间", required = true) @ApiModelProperty(value = "登陆时间", required = true)
private String createTime; private Date createTime;
@ApiModelProperty(value = "用户账号", required = true, example = "yudao") @ApiModelProperty(value = "用户账号", required = true, example = "yudao")
private String username; private String username;

View File

@ -14,7 +14,6 @@ import javax.validation.constraints.NotEmpty;
public class SysUserSessionPageReqVO extends PageParam { public class SysUserSessionPageReqVO extends PageParam {
@ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模糊匹配") @ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模糊匹配")
@NotEmpty(message = "用户 IP 不能为空")
private String userIp; private String userIp;
@ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配")

View File

@ -0,0 +1,16 @@
package cn.iocoder.dashboard.modules.system.convert.auth;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO;
import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageItemRespVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SysUserSessionConvert {
SysUserSessionConvert INSTANCE = Mappers.getMapper(SysUserSessionConvert.class);
SysUserSessionPageItemRespVO convert(SysUserSessionDO session);
}

View File

@ -1,9 +1,21 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth; package cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
@Mapper @Mapper
public interface SysUserSessionMapper extends BaseMapper<SysUserSessionDO> { public interface SysUserSessionMapper extends BaseMapperX<SysUserSessionDO> {
default PageResult<SysUserSessionDO> selectPage(SysUserSessionPageReqVO reqVO, Collection<Long> userIds) {
return selectPage(reqVO, new QueryWrapperX<SysUserSessionDO>()
.inIfPresent("user_id", userIds)
.likeIfPresent("user_ip", reqVO.getUserIp()));
}
} }

View File

@ -48,5 +48,9 @@ public interface SysUserMapper extends BaseMapperX<SysUserDO> {
return selectList(new QueryWrapperX<SysUserDO>().like("nickname", nickname)); return selectList(new QueryWrapperX<SysUserDO>().like("nickname", nickname));
} }
default List<SysUserDO> selectListByUsername(String username) {
return selectList(new QueryWrapperX<SysUserDO>().like("username", username));
}
} }

View File

@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.framework.security.core.LoginUser;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder; import lombok.Builder;
@ -27,7 +28,7 @@ public class SysUserSessionDO extends BaseDO {
/** /**
* 会话编号, sessionId * 会话编号, sessionId
*/ */
@TableId @TableId(type = IdType.INPUT)
private String id; private String id;
/** /**
* 用户编号 * 用户编号

View File

@ -30,8 +30,8 @@ public class SysLoginUserRedisDAO {
stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(loginUser), LOGIN_USER.getTimeout()); stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(loginUser), LOGIN_USER.getTimeout());
} }
public void delete(String accessToken) { public void delete(String sessionId) {
String redisKey = formatKey(accessToken); String redisKey = formatKey(sessionId);
stringRedisTemplate.delete(redisKey); stringRedisTemplate.delete(redisKey);
} }

View File

@ -0,0 +1 @@
package cn.iocoder.dashboard.modules.system.job;

View File

@ -1,19 +1,26 @@
package cn.iocoder.dashboard.modules.system.service.auth.impl; package cn.iocoder.dashboard.modules.system.service.auth.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.framework.security.config.SecurityProperties; import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.framework.security.core.LoginUser;
import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth.SysUserSessionMapper; import cn.iocoder.dashboard.modules.system.dal.mysql.dao.auth.SysUserSessionMapper;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.auth.SysUserSessionDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO;
import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService;
import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Collection;
import java.util.Date; import java.util.Date;
import static cn.iocoder.dashboard.util.collection.CollectionUtils.convertSet;
/** /**
* 在线用户 Session Service 实现类 * 在线用户 Session Service 实现类
* *
@ -27,10 +34,12 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
@Resource @Resource
private SysLoginUserRedisDAO loginUserRedisDAO; private SysLoginUserRedisDAO loginUserRedisDAO;
@Resource @Resource
private SysUserSessionMapper userSessionMapper; private SysUserSessionMapper userSessionMapper;
@Resource
private SysUserService userService;
@Override @Override
public String createUserSession(LoginUser loginUser, String userIp, String userAgent) { public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {
// 生成 Session 编号 // 生成 Session 编号
@ -39,8 +48,8 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
loginUser.setUpdateTime(new Date()); loginUser.setUpdateTime(new Date());
loginUserRedisDAO.set(sessionId, loginUser); loginUserRedisDAO.set(sessionId, loginUser);
// 写入 DB // 写入 DB
SysUserSessionDO userSession = SysUserSessionDO.builder().userId(loginUser.getId()) SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)
.userIp(userIp).userAgent(userAgent).build(); .userId(loginUser.getId()).userIp(userIp).userAgent(userAgent).build();
userSessionMapper.insert(userSession); userSessionMapper.insert(userSession);
// 返回 Session 编号 // 返回 Session 编号
return sessionId; return sessionId;
@ -59,7 +68,10 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
@Override @Override
public void deleteUserSession(String sessionId) { public void deleteUserSession(String sessionId) {
// 删除 Redis 缓存
loginUserRedisDAO.delete(sessionId);
// 删除 DB 记录
userSessionMapper.deleteById(sessionId);
} }
@Override @Override
@ -74,7 +86,15 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
@Override @Override
public PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO) { public PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO) {
return null; // 处理基于用户昵称的查询
Collection<Long> userIds = null;
if (StrUtil.isNotEmpty(reqVO.getUsername())) {
userIds = convertSet(userService.listUsersByUsername(reqVO.getUsername()), SysUserDO::getId);
if (CollUtil.isEmpty(userIds)) {
return PageResult.empty();
}
}
return userSessionMapper.selectPage(reqVO, userIds);
} }
/** /**

View File

@ -79,6 +79,14 @@ public interface SysUserService {
*/ */
List<SysUserDO> listUsersByNickname(String nickname); List<SysUserDO> listUsersByNickname(String nickname);
/**
* 获得用户列表基于用户账号模糊匹配
*
* @param username 用户账号
* @return 用户列表
*/
List<SysUserDO> listUsersByUsername(String username);
/** /**
* 创建用户 * 创建用户
* *

View File

@ -92,6 +92,11 @@ public class SysUserServiceImpl implements SysUserService {
return userMapper.selectListByNickname(nickname); return userMapper.selectListByNickname(nickname);
} }
@Override
public List<SysUserDO> listUsersByUsername(String username) {
return userMapper.selectListByUsername(username);
}
/** /**
* 获得部门条件查询指定部门的子部门编号们包括自身 * 获得部门条件查询指定部门的子部门编号们包括自身
* *

View File

@ -26,35 +26,35 @@ public class CollectionUtils {
return from.stream().filter(predicate).collect(Collectors.toList()); return from.stream().filter(predicate).collect(Collectors.toList());
} }
public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) { public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new ArrayList<>(); return new ArrayList<>();
} }
return from.stream().map(func).collect(Collectors.toList()); return from.stream().map(func).collect(Collectors.toList());
} }
public static <T, U> Set<U> convertSet(List<T> from, Function<T, U> func) { public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashSet<>(); return new HashSet<>();
} }
return from.stream().map(func).collect(Collectors.toSet()); return from.stream().map(func).collect(Collectors.toSet());
} }
public static <T, K> Map<K, T> convertMap(List<T> from, Function<T, K> keyFunc) { public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashMap<>(); return new HashMap<>();
} }
return from.stream().collect(Collectors.toMap(keyFunc, item -> item)); return from.stream().collect(Collectors.toMap(keyFunc, item -> item));
} }
public static <T, K, V> Map<K, V> convertMap(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) { public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashMap<>(); return new HashMap<>();
} }
return from.stream().collect(Collectors.toMap(keyFunc, valueFunc)); return from.stream().collect(Collectors.toMap(keyFunc, valueFunc));
} }
public static <T, K> Map<K, List<T>> convertMultiMap(List<T> from, Function<T, K> keyFunc) { public static <T, K> Map<K, List<T>> convertMultiMap(Collection<T> from, Function<T, K> keyFunc) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashMap<>(); return new HashMap<>();
} }
@ -62,7 +62,7 @@ public class CollectionUtils {
Collectors.mapping(t -> t, Collectors.toList()))); Collectors.mapping(t -> t, Collectors.toList())));
} }
public static <T, K, V> Map<K, List<V>> convertMultiMap(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) { public static <T, K, V> Map<K, List<V>> convertMultiMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashMap<>(); return new HashMap<>();
} }
@ -71,7 +71,7 @@ public class CollectionUtils {
} }
// 暂时没想好名字先以 2 结尾噶 // 暂时没想好名字先以 2 结尾噶
public static <T, K, V> Map<K, Set<V>> convertMultiMap2(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) { public static <T, K, V> Map<K, Set<V>> convertMultiMap2(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashMap<>(); return new HashMap<>();
} }