1. 增加字典数据的缓存与 util

2. 引入 Excel 组件
This commit is contained in:
YunaiV 2021-01-13 01:09:26 +08:00
parent ec00936532
commit fc444728c9
22 changed files with 277 additions and 98 deletions

85
pom.xml
View File

@ -11,6 +11,7 @@
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<packaging>jar</packaging>
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@ -54,19 +55,13 @@
<jjwt.version>0.9.1</jjwt.version>
<fastjson.version>1.2.75</fastjson.version>
<hutool.version>5.5.6</hutool.version>
<easyexcel.verion>2.2.7</easyexcel.verion>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- &lt;!&ndash;阿里数据库连接池 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba</groupId>-->
<!-- <artifactId>druid-spring-boot-starter</artifactId>-->
<!-- <version>${druid.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; 解析客户端操作系统、浏览器等 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>eu.bitwalker</groupId>-->
@ -74,13 +69,6 @@
<!-- <version>${bitwalker.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; pagehelper 分页插件 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.github.pagehelper</groupId>-->
<!-- <artifactId>pagehelper-spring-boot-starter</artifactId>-->
<!-- <version>${pagehelper.boot.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; 获取系统信息 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.github.oshi</groupId>-->
@ -100,30 +88,6 @@
<!-- <version>${jna.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; swagger2&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-swagger2</artifactId>-->
<!-- <version>${swagger.version}</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>io.swagger</groupId>-->
<!-- <artifactId>swagger-annotations</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>io.swagger</groupId>-->
<!-- <artifactId>swagger-models</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; swagger2-UI&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-swagger-ui</artifactId>-->
<!-- <version>${swagger.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash;io常用工具类 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>commons-io</groupId>-->
@ -138,39 +102,11 @@
<!-- <version>${commons.fileupload.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; excel工具 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.poi</groupId>-->
<!-- <artifactId>poi-ooxml</artifactId>-->
<!-- <version>${poi.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash;velocity代码生成使用模板 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.velocity</groupId>-->
<!-- <artifactId>velocity</artifactId>-->
<!-- <version>${velocity.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; 阿里JSON解析器 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba</groupId>-->
<!-- <artifactId>fastjson</artifactId>-->
<!-- <version>${fastjson.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash;Token生成与解析&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>io.jsonwebtoken</groupId>-->
<!-- <artifactId>jjwt</artifactId>-->
<!-- <version>${jwt.version}</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash;验证码 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.github.penggle</groupId>-->
<!-- <artifactId>kaptcha</artifactId>-->
<!-- <version>${kaptcha.version}</version>-->
<!-- </dependency>-->
<!-- 统一依赖管理 -->
@ -184,16 +120,6 @@
</dependencies>
</dependencyManagement>
<!-- <modules>-->
<!-- <module>ruoyi-admin</module>-->
<!-- <module>ruoyi-framework</module>-->
<!-- <module>ruoyi-system</module>-->
<!-- <module>ruoyi-quartz</module>-->
<!-- <module>ruoyi-generator</module>-->
<!-- <module>ruoyi-common</module>-->
<!-- </modules>-->
<packaging>jar</packaging>
<dependencies>
<!-- Spring 核心 -->
<dependency>
@ -306,6 +232,13 @@
<artifactId>hutool-captcha</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.verion}</version>
</dependency>
</dependencies>

View File

@ -0,0 +1,18 @@
package cn.iocoder.dashboard.framework.dict.config;
import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.dashboard.framework.dict.core.util.DictUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DictConfiguration {
@Bean
@SuppressWarnings("InstantiationOfUtilityClass")
public DictUtils dictUtils(DictDataFrameworkService service) {
DictUtils.init(service);
return new DictUtils();
}
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.dashboard.framework.dict.core.util;
import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
import lombok.extern.slf4j.Slf4j;
/**
@ -16,4 +17,12 @@ public class DictUtils {
log.info("[init][初始化 DictUtils 成功]");
}
public static SysDictDataDO getDictDataFromCache(String type, String value) {
return service.getDictDataFromCache(type, value);
}
public static SysDictDataDO parseDictDataFromCache(String type, String label) {
return service.getDictDataFromCache(type, label);
}
}

View File

@ -11,6 +11,7 @@ import java.math.BigDecimal;
*
* @author ruoyi
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

View File

@ -10,6 +10,7 @@ import java.lang.annotation.Target;
*
* @author ruoyi
*/
@Deprecated
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels

View File

@ -0,0 +1,19 @@
package cn.iocoder.dashboard.framework.excel.core.annotations;
import cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum;
import java.lang.annotation.*;
/**
* 字典格式化
*
* 实现将字典数据的值格式化成字典数据的标签
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DictFormat {
DictTypeEnum value();
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.dashboard.framework.excel.core.convert;
import cn.hutool.core.convert.Convert;
import cn.iocoder.dashboard.framework.dict.core.util.DictUtils;
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
import cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DictConvert implements Converter<Object> {
@Override
public Class<?> supportJavaTypeKey() {
throw new UnsupportedOperationException("暂不支持,也不需要");
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
throw new UnsupportedOperationException("暂不支持,也不需要");
}
@Override
public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// 使用字典解析
DictTypeEnum type = getType(contentProperty);
String label = cellData.getStringValue();
SysDictDataDO dictData = DictUtils.parseDictDataFromCache(type.getValue(), label);
if (dictData == null) {
log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label);
return null;
}
// String value 转换成对应的属性
Class<?> fieldClazz = contentProperty.getField().getType();
return Convert.convert(fieldClazz, dictData.getValue());
}
@Override
public CellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// 使用字典格式化
DictTypeEnum type = getType(contentProperty);
String value = String.valueOf(object);
SysDictDataDO dictData = DictUtils.getDictDataFromCache(type.getValue(), value);
if (dictData == null) {
log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);
return null;
}
// 生成 Excel 小表格
return new CellData<>(dictData.getValue());
}
private static DictTypeEnum getType(ExcelContentProperty contentProperty) {
return contentProperty.getField().getAnnotation(DictFormat.class).value();
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.dashboard.framework.excel.core;

View File

@ -0,0 +1,4 @@
/**
* 基于 EasyExcel 实现 Excel 相关的操作
*/
package cn.iocoder.dashboard.framework.excel;

View File

@ -48,7 +48,7 @@ public class SysDeptController {
}
@ApiOperation("获得部门信息")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping("/get")
public CommonResult<SysDeptRespVO> getDept(@RequestParam("id") Long id) {
@ -74,7 +74,7 @@ public class SysDeptController {
}
@ApiOperation("删除部门")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("delete")
// @PreAuthorize("@ss.hasPermi('system:dept:remove')")
// @Log(title = "部门管理", businessType = BusinessType.DELETE)

View File

@ -73,7 +73,7 @@ public class SysPostController {
}
@ApiOperation("获得岗位信息")
@ApiImplicitParam(name = "id", value = "岗位编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "岗位编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermi('system:post:query')")
@GetMapping(value = "/get")
public CommonResult<SysPostRespVO> getPost(@RequestParam("id") Long id) {

View File

@ -41,7 +41,7 @@ public class SysDictDataController {
}
@ApiOperation("/查询字典数据详细")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@GetMapping(value = "/get")
// @PreAuthorize("@ss.hasPermi('system:dict:query')")
public CommonResult<SysDictDataRespVO> getDictData(@RequestParam("id") Long id) {
@ -67,7 +67,7 @@ public class SysDictDataController {
}
@ApiOperation("删除字典数据")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("/delete")
// @PreAuthorize("@ss.hasPermi('system:dict:remove')")
public CommonResult<Boolean> deleteDictData(Long id) {

View File

@ -33,7 +33,7 @@ public class SysDictTypeController {
}
@ApiOperation("/查询字典类型详细")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@GetMapping(value = "/get")
// @PreAuthorize("@ss.hasPermi('system:dict:query')")
public CommonResult<SysDictTypeRespVO> getDictType(@RequestParam("id") Long id) {
@ -59,7 +59,7 @@ public class SysDictTypeController {
}
@ApiOperation("删除字典类型")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("/delete")
// @PreAuthorize("@ss.hasPermi('system:dict:remove')")
public CommonResult<Boolean> deleteDictType(Long id) {

View File

@ -88,7 +88,7 @@ public class SysMenuController {
@ApiOperation("删除菜单")
@PostMapping("/delete")
@ApiImplicitParam(name = "id", value = "角色编号", required= true, example = "1024")
@ApiImplicitParam(name = "id", value = "角色编号", required= true, example = "1024", dataTypeClass = Long.class)
// @Log(title = "菜单管理", businessType = BusinessType.DELETE)
public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
menuService.deleteMenu(id);

View File

@ -30,8 +30,8 @@ public class SysPermissionController {
private SysPermissionService permissionService;
@ApiOperation("获得角色拥有的菜单编号")
@ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class)
@GetMapping("/list-role-resources")
@ApiImplicitParam(name = "roleId", value = "角色编号", required = true)
// @RequiresPermissions("system:permission:assign-role-menu")
public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
return success(permissionService.listRoleMenuIds(roleId));
@ -55,7 +55,7 @@ public class SysPermissionController {
}
@ApiOperation("获得管理员拥有的角色编号列表")
@ApiImplicitParam(name = "userId", value = "用户编号", required = true)
@ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class)
@GetMapping("/list-user-roles")
// @RequiresPermissions("system:permission:assign-user-role")
public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) {

View File

@ -64,10 +64,10 @@ public class SysRoleController {
@ApiOperation("删除角色")
@PostMapping("/delete")
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1024")
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermi('system:role:remove')")
// @Log(title = "角色管理", businessType = BusinessType.DELETE)
public CommonResult<Boolean> remove(@RequestParam("id") Long id) {
public CommonResult<Boolean> deleteRole(@RequestParam("id") Long id) {
roleService.deleteRole(id);
return success(true);
}

View File

@ -63,7 +63,7 @@ public class SysUserController {
* 根据用户编号获取详细信息
*/
@ApiOperation("获得用户详情")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@GetMapping("/get")
// @PreAuthorize("@ss.hasPermi('system:user:query')")
public CommonResult<SysUserRespVO> getInfo(@RequestParam("id") Long id) {
@ -89,7 +89,7 @@ public class SysUserController {
}
@ApiOperation("删除用户")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("/delete")
// @PreAuthorize("@ss.hasPermi('system:user:remove')")
// @Log(title = "用户管理", businessType = BusinessType.DELETE)

View File

@ -11,20 +11,14 @@ import java.util.Date;
* 用户 Excel 导出响应 VO
*/
@Data
public class SysUserExcelRespVO {
public class SysUserExcelRespBackVO {
@Excel(name = "用户序号", cellType = Excel.ColumnType.NUMERIC, prompt = "用户编号")
private Long id;
/**
* 用户账号
*/
@Excel(name = "登录名称")
private String username;
/**
* 用户昵称
*/
@Excel(name = "用户名称")
private String nickname;

View File

@ -0,0 +1,54 @@
package cn.iocoder.dashboard.modules.system.controller.user.vo.user;
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
import static cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum.SYS_COMMON_STATUS;
import static cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum.SYS_USER_SEX;
/**
* 用户 Excel 导出 VO
*/
@Data
public class SysUserExcelVO {
@ExcelProperty("用户编号")
private Long id;
@ExcelProperty("用户名称")
private String username;
@ExcelProperty("用户名称")
private String nickname;
@ExcelProperty("用户邮箱")
private String email;
@ExcelProperty("手机号码")
private String mobile;
@ExcelProperty(value = "用户性别", converter = DictConvert.class)
@DictFormat(SYS_USER_SEX)
private Integer sex;
@ExcelProperty(value = "帐号状态", converter = DictConvert.class)
@DictFormat(SYS_COMMON_STATUS)
private Integer status;
@ExcelProperty("最后登录IP")
private String loginIp;
@ExcelProperty("最后登录时间")
private Date loginDate;
@ExcelProperty("部门名称")
private String deptName;
@ExcelProperty("部门负责人")
private String deptLeader;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.dashboard.modules.system.enums.dict;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 字典类型的类型枚举
*/
@Getter
@AllArgsConstructor
public enum DictTypeEnum {
SYS_USER_SEX("sys_user_sex"), // 用户性别
SYS_COMMON_STATUS("sys_common_status"), // 系统状态
;
/**
*
*/
private final String value;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.dashboard.modules.system.service.dict;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
@ -13,8 +14,18 @@ import java.util.List;
*
* @author ruoyi
*/
public interface SysDictDataService {
public interface SysDictDataService extends DictDataFrameworkService {
/**
* 初始化主要是初始化缓存
*/
void init();
/**
* 获得字典数据列表
*
* @return 字典数据全列表
*/
List<SysDictDataDO> listDictDatas();
/**

View File

@ -12,9 +12,11 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictData
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictTypeDO;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
import com.google.common.collect.ImmutableTable;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@ -32,12 +34,42 @@ public class SysDictDataServiceImpl implements SysDictDataService {
.comparing(SysDictDataDO::getDictType)
.thenComparingInt(SysDictDataDO::getSort);
/**
* 字典数据缓存第二个 key 使用 label
*
* key1字典类型 dictType
* key2字典标签 label
*/
private ImmutableTable<String, String, SysDictDataDO> labelDictDataCache;
/**
* 字典数据缓存第二个 key 使用 value
*
* key1字典类型 dictType
* key2字典值 value
*/
private ImmutableTable<String, String, SysDictDataDO> valueDictDataCache;
@Resource
private SysDictTypeService dictTypeService;
@Resource
private SysDictDataMapper dictDataMapper;
@Override
public void init() {
// 获得字典数据
List<SysDictDataDO> list = this.listDictDatas();
// 构建缓存
ImmutableTable.Builder<String, String, SysDictDataDO> labelDictDataBuilder = ImmutableTable.builder();
ImmutableTable.Builder<String, String, SysDictDataDO> valueDictDataBuilder = ImmutableTable.builder();
list.forEach(dictData -> {
labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData);
valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData);
});
labelDictDataCache = labelDictDataBuilder.build();
valueDictDataCache = valueDictDataBuilder.build();
}
@Override
public List<SysDictDataDO> listDictDatas() {
List<SysDictDataDO> list = dictDataMapper.selectList();
@ -130,4 +162,19 @@ public class SysDictDataServiceImpl implements SysDictDataService {
}
}
@Override
public SysDictDataDO getDictDataFromCache(String type, String value) {
return valueDictDataCache.get(type, value);
}
@Override
public SysDictDataDO parseDictDataFromCache(String type, String label) {
return labelDictDataCache.get(type, label);
}
@Override
public List<SysDictDataDO> listDictDatasFromCache(String type) {
return new ArrayList<>(labelDictDataCache.row(type).values());
}
}