发布 v3.4.0

This commit is contained in:
疯狂的狮子li
2021-11-29 14:26:23 +08:00
parent d81377a2ed
commit c76ab64e8a
172 changed files with 1674 additions and 3599 deletions

View File

@@ -4,6 +4,7 @@ MAINTAINER Lion Li
RUN mkdir -p /ruoyi/server
RUN mkdir -p /ruoyi/server/logs
RUN mkdir -p /ruoyi/server/temp
WORKDIR /ruoyi/server

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.3.0</version>
<version>3.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
@@ -48,7 +48,7 @@
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<!-- spring-boot-devtools -->
@@ -85,12 +85,6 @@
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
@@ -126,18 +120,6 @@
<artifactId>jaxb-impl</artifactId>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- pool 对象池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
@@ -174,16 +156,6 @@
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
@@ -225,11 +197,6 @@
<artifactId>tlog-webroot</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>tlog-feign</artifactId>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>tlog-xxl-job</artifactId>

View File

@@ -2,6 +2,7 @@ package com.ruoyi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
/**
* 启动程序
@@ -14,7 +15,9 @@ public class RuoYiApplication {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args);
SpringApplication application = new SpringApplication(RuoYiApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
System.out.println("(♥◠‿◠)ノ゙ RuoYi-Vue-Plus启动成功 ლ(´ڡ`ლ)゙");
}

View File

@@ -38,6 +38,11 @@ public class RuoYiConfig {
*/
private boolean demoEnabled;
/**
* 缓存懒加载
*/
private boolean cacheLazy;
/**
* 获取地址开关
*/

View File

@@ -133,13 +133,4 @@ public class Constants {
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi://";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap://";
}

View File

@@ -8,8 +8,10 @@ import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.core.service.DictService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
@@ -41,7 +43,7 @@ public class ExcelDictConvert implements Converter<Object> {
if (StringUtils.isBlank(type)) {
value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
} else {
value = ExcelUtil.reverseDictByExp(label, type, anno.separator());
value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator());
}
return Convert.convert(contentProperty.getField().getType(), value);
}
@@ -58,7 +60,7 @@ public class ExcelDictConvert implements Converter<Object> {
if (StringUtils.isBlank(type)) {
label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
} else {
label = ExcelUtil.convertDictByExp(value, type, anno.separator());
label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator());
}
return new CellData<>(label);
}

View File

@@ -2,7 +2,6 @@ package com.ruoyi.common.core.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

View File

@@ -1,67 +0,0 @@
package com.ruoyi.common.core.domain;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysMenu;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
/**
* Treeselect树结构实体类
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
@ApiModel("树结构实体类")
public class TreeSelect implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 节点ID
*/
@ApiModelProperty(value = "节点ID")
private Long id;
/**
* 节点名称
*/
@ApiModelProperty(value = "节点名称")
private String label;
/**
* 子节点
*/
@ApiModelProperty(value = "子节点")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children;
public TreeSelect(SysDept dept) {
this.id = dept.getDeptId();
this.label = dept.getDeptName();
this.children = dept.getChildren()
.stream()
.map(d -> new TreeSelect((SysDept) d))
.collect(Collectors.toList());
}
public TreeSelect(SysMenu menu) {
this.id = menu.getMenuId();
this.label = menu.getMenuName();
this.children = menu.getChildren()
.stream()
.map(d -> new TreeSelect((SysMenu) d))
.collect(Collectors.toList());
}
}

View File

@@ -1,7 +1,6 @@
package com.ruoyi.common.core.domain.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.core.domain.entity.SysUser;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@@ -75,31 +74,38 @@ public class LoginUser implements UserDetails {
private Set<String> permissions;
/**
* 用户信息
* 用户
*/
private SysUser user;
private String username;
public LoginUser(SysUser user, Set<String> permissions) {
this.user = user;
/**
* 密码
*/
private String password;
public LoginUser(String username, String password, Set<String> permissions) {
this.username = username;
this.password = password;
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions) {
public LoginUser(Long userId, Long deptId, String username, String password, Set<String> permissions) {
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.username = username;
this.password = password;
this.permissions = permissions;
}
@JsonIgnore
@Override
public String getPassword() {
return user.getPassword();
return password;
}
@Override
public String getUsername() {
return user.getUserName();
return username;
}
/**

View File

@@ -1,91 +0,0 @@
package com.ruoyi.common.core.mybatisplus.cache;
import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.common.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* mybatis-redis 二级缓存
*
* 使用方法 配置文件开启 mybatis-plus 二级缓存
* 在 XxxMapper.java 类上添加注解 @CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
*
* @deprecated 3.4.0删除 推荐使用spirng-cache
* @author Lion Li
*/
@Slf4j
public class MybatisPlusRedisCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
private String id;
public MybatisPlusRedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
if (value != null) {
RedisUtils.setCacheObject(key.toString(), value);
}
}
@Override
public Object getObject(Object key) {
try {
if (key != null) {
return RedisUtils.getCacheObject(key.toString());
}
} catch (Exception e) {
e.printStackTrace();
log.error("缓存出错");
}
return null;
}
@Override
public Object removeObject(Object key) {
if (key != null) {
RedisUtils.deleteObject(key.toString());
}
return null;
}
@Override
public void clear() {
log.debug("清空缓存");
Collection<String> keys = RedisUtils.keys("*:" + this.id + "*");
if (!CollectionUtils.isEmpty(keys)) {
RedisUtils.deleteObject(keys);
}
}
@Override
public int getSize() {
RedisTemplate<String, Object> redisTemplate = SpringUtil.getBean("redisTemplate");
Long size = redisTemplate.execute(RedisServerCommands::dbSize);
return size.intValue();
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
}

View File

@@ -2,6 +2,11 @@ package com.ruoyi.common.core.service;
import javax.servlet.http.HttpServletRequest;
/**
* 通用 系统访问日志
*
* @author Lion Li
*/
public interface LogininforService {
void recordLogininfor(String username, String status, String message,

View File

@@ -3,7 +3,13 @@ package com.ruoyi.common.core.service;
import com.ruoyi.common.core.domain.dto.OperLogDTO;
import org.springframework.scheduling.annotation.Async;
/**
* 通用 操作日志
*
* @author Lion Li
*/
public interface OperLogService {
@Async
void recordOper(OperLogDTO operLogDTO);
}

View File

@@ -1,61 +0,0 @@
package com.ruoyi.common.exception.file;
import lombok.*;
import org.apache.commons.fileupload.FileUploadException;
import java.util.Arrays;
/**
* 文件上传 误异常类
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class InvalidExtensionException extends FileUploadException {
private static final long serialVersionUID = 1L;
private String[] allowedExtension;
private String extension;
private String filename;
public InvalidExtensionException(String[] allowedExtension, String extension, String filename) {
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;
}
public static class InvalidImageExtensionException extends InvalidExtensionException {
private static final long serialVersionUID = 1L;
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) {
super(allowedExtension, extension, filename);
}
}
public static class InvalidFlashExtensionException extends InvalidExtensionException {
private static final long serialVersionUID = 1L;
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) {
super(allowedExtension, extension, filename);
}
}
public static class InvalidMediaExtensionException extends InvalidExtensionException {
private static final long serialVersionUID = 1L;
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) {
super(allowedExtension, extension, filename);
}
}
public static class InvalidVideoExtensionException extends InvalidExtensionException {
private static final long serialVersionUID = 1L;
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) {
super(allowedExtension, extension, filename);
}
}
}

View File

@@ -11,7 +11,9 @@ import java.util.List;
* 字典工具类
*
* @author ruoyi
* @deprecated 3.5.0 版本删除 迁移至 {@link com.ruoyi.common.core.service.DictService}
*/
@Deprecated
public class DictUtils {
/**
@@ -36,9 +38,8 @@ public class DictUtils {
* @return dictDatas 字典数据列表
*/
public static List<SysDictData> getDictCache(String key) {
Object cacheObj = RedisUtils.getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj)) {
List<SysDictData> dictDatas = (List<SysDictData>) cacheObj;
List<SysDictData> dictDatas = RedisUtils.getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(dictDatas)) {
return dictDatas;
}
return null;

View File

@@ -1,5 +1,6 @@
package com.ruoyi.common.utils;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -63,7 +64,9 @@ public class PageUtils {
}
PagePlus<T, K> page = new PagePlus<>(pageNum, pageSize);
OrderItem orderItem = buildOrderItem(orderByColumn, isAsc);
page.addOrder(orderItem);
if (ObjectUtil.isNotNull(orderItem)) {
page.addOrder(orderItem);
}
return page;
}
@@ -87,7 +90,9 @@ public class PageUtils {
}
Page<T> page = new Page<>(pageNum, pageSize);
OrderItem orderItem = buildOrderItem(orderByColumn, isAsc);
page.addOrder(orderItem);
if (ObjectUtil.isNotNull(orderItem)) {
page.addOrder(orderItem);
}
return page;
}

View File

@@ -88,7 +88,30 @@ public class RedisUtils {
* @param value 缓存的值
*/
public static <T> void setCacheObject(final String key, final T value) {
client.getBucket(key).set(value);
setCacheObject(key, value, false);
}
/**
* 缓存基本的对象,保留当前对象 TTL 有效期
*
* @param key 缓存的键值
* @param value 缓存的值
* @param isSaveTtl 是否保留TTL有效期(例如: set之前ttl剩余90 set之后还是为90)
* @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案
*/
public static <T> void setCacheObject(final String key, final T value, final boolean isSaveTtl) {
RBucket<Object> bucket = client.getBucket(key);
if (isSaveTtl) {
try {
bucket.setAndKeepTTL(value);
} catch (Exception e) {
long timeToLive = bucket.remainTimeToLive();
bucket.set(value);
bucket.expire(timeToLive, TimeUnit.MILLISECONDS);
}
} else {
bucket.set(value);
}
}
/**
@@ -99,7 +122,7 @@ public class RedisUtils {
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public static <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
public static <T> void setCacheObject(final String key, final T value, final long timeout, final TimeUnit timeUnit) {
RBucket<T> result = client.getBucket(key);
result.set(value);
result.expire(timeout, timeUnit);
@@ -140,6 +163,17 @@ public class RedisUtils {
return rBucket.get();
}
/**
* 获得key剩余存活时间
*
* @param key 缓存键值
* @return 剩余存活时间
*/
public static <T> long getTimeToLive(final String key) {
RBucket<T> rBucket = client.getBucket(key);
return rBucket.remainTimeToLive();
}
/**
* 删除单个对象
*

View File

@@ -4,7 +4,9 @@ import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.ruoyi.common.convert.ExcelBigNumberConvert;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.excel.DefaultExcelListener;
import com.ruoyi.common.excel.ExcelListener;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
@@ -21,129 +23,133 @@ import java.util.List;
*/
public class ExcelUtil {
/**
* 对excel表单默认第一个索引名转换成listEasyExcel
*
* @param is 输入流
* @return 转换后集合
*/
public static <T> List<T> importExcel(InputStream is, Class<T> clazz) {
return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync();
}
/**
* 同步导入(适用于小数据量)
*
* @param is 输入流
* @return 转换后集合
*/
public static <T> List<T> importExcel(InputStream is, Class<T> clazz) {
return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync();
}
/**
* 对list数据源将其里面的数据导入到excel表单EasyExcel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
try {
String filename = encodingFilename(sheetName);
response.reset();
FileUtils.setAttachmentResponseHeader(response, filename);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
ServletOutputStream os = response.getOutputStream();
EasyExcel.write(os, clazz)
.autoCloseStream(false)
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.sheet(sheetName).doWrite(list);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 解析导出值 0=男,1=女,2=未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String convertByExp(String propertyValue, String converterExp, String separator) {
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue)) {
for (String value : propertyValue.split(separator)) {
if (itemArray[0].equals(value)) {
propertyString.append(itemArray[1] + separator);
break;
}
}
} else {
if (itemArray[0].equals(propertyValue)) {
return itemArray[1];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 使用校验监听器 异步导入 同步返回
*
* @param is 输入流
* @param clazz 对象类型
* @param isValidate 是否 Validator 检验 默认为是
* @return 转换后集合
*/
public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, boolean isValidate) {
DefaultExcelListener<T> listener = new DefaultExcelListener<>(isValidate);
EasyExcel.read(is, clazz, listener).sheet().doRead();
return listener.getExcelResult();
}
/**
* 反向解析值 男=0,女=1,未知=2
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String reverseByExp(String propertyValue, String converterExp, String separator) {
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue)) {
for (String value : propertyValue.split(separator)) {
if (itemArray[1].equals(value)) {
propertyString.append(itemArray[0] + separator);
break;
}
}
} else {
if (itemArray[1].equals(propertyValue)) {
return itemArray[0];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 使用自定义监听器 异步导入 自定义返回
*
* @param is 输入流
* @param clazz 对象类型
* @param listener 自定义监听器
* @return 转换后集合
*/
public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) {
EasyExcel.read(is, clazz, listener).sheet().doRead();
return listener.getExcelResult();
}
/**
* 解析字典值
*
* @param dictValue 字典值
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典标签
*/
public static String convertDictByExp(String dictValue, String dictType, String separator) {
return DictUtils.getDictLabel(dictType, dictValue, separator);
}
/**
* 导出excel
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @return 结果
*/
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
try {
String filename = encodingFilename(sheetName);
response.reset();
FileUtils.setAttachmentResponseHeader(response, filename);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
ServletOutputStream os = response.getOutputStream();
EasyExcel.write(os, clazz)
.autoCloseStream(false)
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.sheet(sheetName).doWrite(list);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 反向解析值字典值
*
* @param dictLabel 字典标签
* @param dictType 字典类型
* @param separator 分隔符
* @return 字典
*/
public static String reverseDictByExp(String dictLabel, String dictType, String separator) {
return DictUtils.getDictValue(dictType, dictLabel, separator);
}
/**
* 解析导出值 0=男,1=女,2=未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后
*/
public static String convertByExp(String propertyValue, String converterExp, String separator) {
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue)) {
for (String value : propertyValue.split(separator)) {
if (itemArray[0].equals(value)) {
propertyString.append(itemArray[1] + separator);
break;
}
}
} else {
if (itemArray[0].equals(propertyValue)) {
return itemArray[1];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 编码文件名
*/
public static String encodingFilename(String filename) {
return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
}
/**
* 反向解析值 男=0,女=1,未知=2
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @param separator 分隔符
* @return 解析后值
*/
public static String reverseByExp(String propertyValue, String converterExp, String separator) {
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (StringUtils.containsAny(separator, propertyValue)) {
for (String value : propertyValue.split(separator)) {
if (itemArray[1].equals(value)) {
propertyString.append(itemArray[0] + separator);
break;
}
}
} else {
if (itemArray[1].equals(propertyValue)) {
return itemArray[0];
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 编码文件名
*/
public static String encodingFilename(String filename) {
return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
}
}

View File

@@ -1,37 +0,0 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.demo.feign.FeignTestService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* feign测试controller
*
* @author Lion Li
* @deprecated 由于使用人数较少 决定与 3.4.0 版本移除
*/
@Api(value = "feign测试", tags = {"feign测试"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/feign/test")
public class FeignTestController {
private final FeignTestService feignTestService;
/**
* 搜索数据
*/
@ApiOperation("测试使用feign请求数据")
@GetMapping("/search/{wd}")
public AjaxResult search(@PathVariable String wd) {
String search = feignTestService.search(wd);
return AjaxResult.success("操作成功",search);
}
}

View File

@@ -28,75 +28,75 @@ import java.util.concurrent.TimeUnit;
@RequestMapping("/demo/cache")
public class RedisCacheController {
/**
* 测试 @Cacheable
*
* 表示这个方法有了缓存的功能,方法的返回值会被缓存下来
* 下一次调用该方法前,会去检查是否缓存中已经有值
* 如果有就直接返回,不调用方法
* 如果没有,就调用方法,然后把结果缓存起来
* 这个注解「一般用在查询方法上」
*
* 重点说明: 缓存注解严谨与其他筛选数据功能一起使用
* 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题
*
* cacheNames 为配置文件内 groupId
*/
@ApiOperation("测试 @Cacheable")
@Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test1")
public AjaxResult<String> test1(String key, String value){
return AjaxResult.success("操作成功", value);
}
/**
* 测试 @Cacheable
* <p>
* 表示这个方法有了缓存的功能,方法的返回值会被缓存下来
* 下一次调用该方法前,会去检查是否缓存中已经有值
* 如果有就直接返回,不调用方法
* 如果没有,就调用方法,然后把结果缓存起来
* 这个注解「一般用在查询方法上」
* <p>
* 重点说明: 缓存注解严谨与其他筛选数据功能一起使用
* 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题
* <p>
* cacheNames 为配置文件内 groupId
*/
@ApiOperation("测试 @Cacheable")
@Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test1")
public AjaxResult<String> test1(String key, String value) {
return AjaxResult.success("操作成功", value);
}
/**
* 测试 @CachePut
*
* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用
* 它「通常用在新增方法上」
*
* cacheNames 为 配置文件内 groupId
*/
@ApiOperation("测试 @CachePut")
@CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test2")
public AjaxResult<String> test2(String key, String value){
return AjaxResult.success("操作成功", value);
}
/**
* 测试 @CachePut
* <p>
* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用
* 它「通常用在新增方法上」
* <p>
* cacheNames 为 配置文件内 groupId
*/
@ApiOperation("测试 @CachePut")
@CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test2")
public AjaxResult<String> test2(String key, String value) {
return AjaxResult.success("操作成功", value);
}
/**
* 测试 @CacheEvict
*
* 使用了CacheEvict注解的方法,会清空指定缓存
* 「一般用在更新或者删除的方法上」
*
* cacheNames 为 配置文件内 groupId
*/
@ApiOperation("测试 @CacheEvict")
@CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test3")
public AjaxResult<String> test3(String key, String value){
return AjaxResult.success("操作成功", value);
}
/**
* 测试 @CacheEvict
* <p>
* 使用了CacheEvict注解的方法,会清空指定缓存
* 「一般用在更新或者删除的方法上」
* <p>
* cacheNames 为 配置文件内 groupId
*/
@ApiOperation("测试 @CacheEvict")
@CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test3")
public AjaxResult<String> test3(String key, String value) {
return AjaxResult.success("操作成功", value);
}
/**
* 测试设置过期时间
* 手动设置过期时间10秒
* 11秒后获取 判断是否相等
*/
@ApiOperation("测试设置过期时间")
@GetMapping("/test6")
public AjaxResult<Boolean> test6(String key, String value){
RedisUtils.setCacheObject(key, value);
boolean flag = RedisUtils.expire(key, 10, TimeUnit.SECONDS);
System.out.println("***********" + flag);
try {
Thread.sleep(11 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object obj = RedisUtils.getCacheObject(key);
return AjaxResult.success("操作成功", value.equals(obj));
}
/**
* 测试设置过期时间
* 手动设置过期时间10秒
* 11秒后获取 判断是否相等
*/
@ApiOperation("测试设置过期时间")
@GetMapping("/test6")
public AjaxResult<Boolean> test6(String key, String value) {
RedisUtils.setCacheObject(key, value);
boolean flag = RedisUtils.expire(key, 10, TimeUnit.SECONDS);
System.out.println("***********" + flag);
try {
Thread.sleep(11 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object obj = RedisUtils.getCacheObject(key);
return AjaxResult.success("操作成功", value.equals(obj));
}
}

View File

@@ -9,7 +9,6 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -28,59 +27,50 @@ import java.time.LocalTime;
@RequestMapping("/demo/redisLock")
public class RedisLockController {
@Autowired
private LockTemplate lockTemplate;
@Autowired
private LockTemplate lockTemplate;
/**
* 测试lock4j 注解
*/
@ApiOperation("测试lock4j 注解")
@Lock4j(keys = {"#key"})
@GetMapping("/testLock4j")
public AjaxResult<String> testLock4j(String key,String value){
System.out.println("start:"+key+",time:"+ LocalTime.now().toString());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end :"+key+",time:"+LocalTime.now().toString());
return AjaxResult.success("操作成功",value);
}
/**
* 测试lock4j 注解
*/
@ApiOperation("测试lock4j 注解")
@Lock4j(keys = {"#key"})
@GetMapping("/testLock4j")
public AjaxResult<String> testLock4j(String key, String value) {
System.out.println("start:" + key + ",time:" + LocalTime.now().toString());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end :" + key + ",time:" + LocalTime.now().toString());
return AjaxResult.success("操作成功", value);
}
/**
* 测试lock4j 工具
*/
@ApiOperation("测试lock4j 工具")
@GetMapping("/testLock4jLockTemaplate")
public AjaxResult<String> testLock4jLockTemaplate(String key,String value){
final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
if (null == lockInfo) {
throw new RuntimeException("业务处理中,请稍后再试");
}
// 获取锁成功,处理业务
try {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
//
}
System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName());
} finally {
//释放锁
lockTemplate.releaseLock(lockInfo);
}
//结束
return AjaxResult.success("操作成功",value);
}
/**
* 测试lock4j 工具
*/
@ApiOperation("测试lock4j 工具")
@GetMapping("/testLock4jLockTemaplate")
public AjaxResult<String> testLock4jLockTemaplate(String key, String value) {
final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
if (null == lockInfo) {
throw new RuntimeException("业务处理中,请稍后再试");
}
// 获取锁成功,处理业务
try {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
//
}
System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName());
} finally {
//释放锁
lockTemplate.releaseLock(lockInfo);
}
//结束
return AjaxResult.success("操作成功", value);
}
/**
* 测试spring-cache注解
*/
@ApiOperation("测试spring-cache注解")
@Cacheable(value = "test", key = "#key")
@GetMapping("/testCache")
public AjaxResult<String> testCache(String key) {
return AjaxResult.success("操作成功", key);
}
}

View File

@@ -4,6 +4,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.RedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -21,22 +22,22 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/demo/redis/pubsub")
public class RedisPubSubController {
@ApiOperation("发布消息")
@GetMapping("/pub")
public AjaxResult<Void> pub(String key, String value){
RedisUtils.publish(key, value, consumer -> {
System.out.println("发布通道 => " + key + ", 发送值 => " + value);
});
return AjaxResult.success("操作成功");
}
@ApiOperation("发布消息")
@GetMapping("/pub")
public AjaxResult<Void> pub(@ApiParam("通道Key") String key, @ApiParam("发送内容") String value) {
RedisUtils.publish(key, value, consumer -> {
System.out.println("发布通道 => " + key + ", 发送值 => " + value);
});
return AjaxResult.success("操作成功");
}
@ApiOperation("订阅消息")
@GetMapping("/sub")
public AjaxResult<Void> sub(String key){
RedisUtils.subscribe(key, String.class, msg -> {
System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
});
return AjaxResult.success("操作成功");
}
@ApiOperation("订阅消息")
@GetMapping("/sub")
public AjaxResult<Void> sub(@ApiParam("通道Key") String key) {
RedisUtils.subscribe(key, String.class, msg -> {
System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
});
return AjaxResult.success("操作成功");
}
}

View File

@@ -22,37 +22,37 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/demo/rateLimiter")
public class RedisRateLimiterController {
/**
* 测试全局限流
* 全局影响
*/
@ApiOperation("测试全局限流")
@RateLimiter(count = 2, time = 10)
@GetMapping("/test")
public AjaxResult<String> test(String value){
return AjaxResult.success("操作成功",value);
}
/**
* 测试全局限流
* 全局影响
*/
@ApiOperation("测试全局限流")
@RateLimiter(count = 2, time = 10)
@GetMapping("/test")
public AjaxResult<String> test(String value) {
return AjaxResult.success("操作成功", value);
}
/**
* 测试请求IP限流
* 同一IP请求受影响
*/
@ApiOperation("测试请求IP限流")
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
@GetMapping("/testip")
public AjaxResult<String> testip(String value){
return AjaxResult.success("操作成功",value);
}
/**
* 测试请求IP限流
* 同一IP请求受影响
*/
@ApiOperation("测试请求IP限流")
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
@GetMapping("/testip")
public AjaxResult<String> testip(String value) {
return AjaxResult.success("操作成功", value);
}
/**
* 测试集群实例限流
* 启动两个后端服务互不影响
*/
@ApiOperation("测试集群实例限流")
@RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
@GetMapping("/testcluster")
public AjaxResult<String> testcluster(String value){
return AjaxResult.success("操作成功",value);
}
/**
* 测试集群实例限流
* 启动两个后端服务互不影响
*/
@ApiOperation("测试集群实例限流")
@RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
@GetMapping("/testcluster")
public AjaxResult<String> testcluster(String value) {
return AjaxResult.success("操作成功", value);
}
}

View File

@@ -21,18 +21,18 @@ import org.springframework.web.multipart.MultipartFile;
@RequestMapping("/swagger/demo")
public class Swagger3DemoController {
/**
* 上传请求
* 必须使用 @RequestPart 注解标注为文件
* dataType 必须为 "java.io.File"
*/
@ApiOperation(value = "通用上传请求")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
})
@PostMapping(value = "/upload")
public AjaxResult<String> upload(@RequestPart("file") MultipartFile file) {
return AjaxResult.success("操作成功", file.getOriginalFilename());
}
/**
* 上传请求
* 必须使用 @RequestPart 注解标注为文件
* dataType 必须为 "java.io.File"
*/
@ApiOperation(value = "通用上传请求")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
})
@PostMapping(value = "/upload")
public AjaxResult<String> upload(@RequestPart("file") MultipartFile file) {
return AjaxResult.success("操作成功", file.getOriginalFilename());
}
}

View File

@@ -34,48 +34,48 @@ public class TestBatchController extends BaseController {
/**
* 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大)
*/
@ApiOperation(value = "新增批量方法")
@ApiOperation(value = "新增批量方法")
@PostMapping("/add")
// @DataSource(DataSourceType.SLAVE)
public AjaxResult<Void> add() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
}
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
}
return toAjax(iTestDemoService.saveAll(list) ? 1 : 0);
}
/**
* 新增或更新 可完美替代 saveOrUpdateBatch 高性能
*/
@ApiOperation(value = "新增或更新批量方法")
@PostMapping("/addOrUpdate")
/**
* 新增或更新 可完美替代 saveOrUpdateBatch 高性能
*/
@ApiOperation(value = "新增或更新批量方法")
@PostMapping("/addOrUpdate")
// @DataSource(DataSourceType.SLAVE)
public AjaxResult<Void> addOrUpdate() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
}
iTestDemoService.saveAll(list);
for (int i = 0; i < list.size(); i++) {
TestDemo testDemo = list.get(i);
testDemo.setTestKey("批量新增或修改").setValue("批量新增或修改");
if (i % 2 == 0) {
testDemo.setId(null);
}
}
return toAjax(iTestDemoService.saveOrUpdateAll(list) ? 1 : 0);
}
public AjaxResult<Void> addOrUpdate() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
}
iTestDemoService.saveAll(list);
for (int i = 0; i < list.size(); i++) {
TestDemo testDemo = list.get(i);
testDemo.setTestKey("批量新增或修改").setValue("批量新增或修改");
if (i % 2 == 0) {
testDemo.setId(null);
}
}
return toAjax(iTestDemoService.saveOrUpdateAll(list) ? 1 : 0);
}
/**
* 删除批量方法
*/
@ApiOperation(value = "删除批量方法")
@ApiOperation(value = "删除批量方法")
@DeleteMapping()
// @DataSource(DataSourceType.SLAVE)
public AjaxResult<Void> remove() {
return toAjax(iTestDemoService.remove(new LambdaQueryWrapper<TestDemo>()
.eq(TestDemo::getOrderNum, -1L)) ? 1 : 0);
.eq(TestDemo::getOrderNum, -1L)) ? 1 : 0);
}
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.demo.controller;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
@@ -9,17 +10,21 @@ import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ValidatorUtils;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.domain.bo.TestDemoBo;
import com.ruoyi.demo.domain.bo.TestDemoImportVo;
import com.ruoyi.demo.domain.vo.TestDemoVo;
import com.ruoyi.demo.service.ITestDemoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
@@ -53,30 +58,45 @@ public class TestDemoController extends BaseController {
return iTestDemoService.queryPageList(bo);
}
/**
* 自定义分页查询
*/
@ApiOperation("自定义分页查询")
@PreAuthorize("@ss.hasPermi('demo:demo:list')")
@GetMapping("/page")
public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo) {
return iTestDemoService.customPageList(bo);
}
/**
* 自定义分页查询
*/
@ApiOperation("自定义分页查询")
@PreAuthorize("@ss.hasPermi('demo:demo:list')")
@GetMapping("/page")
public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo) {
return iTestDemoService.customPageList(bo);
}
/**
@ApiOperation("导入测试-校验")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "导入文件", dataType = "java.io.File", required = true),
})
@Log(title = "测试单表", businessType = BusinessType.IMPORT)
@PreAuthorize("@ss.hasPermi('demo:demo:import')")
@PostMapping("/importData")
public AjaxResult<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
ExcelResult<TestDemoImportVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true);
List<TestDemoImportVo> volist = excelResult.getList();
List<TestDemo> list = BeanUtil.copyToList(volist, TestDemo.class);
iTestDemoService.saveAll(list);
return AjaxResult.success(excelResult.getAnalysis());
}
/**
* 导出测试单表列表
*/
@ApiOperation("导出测试单表列表")
@PreAuthorize("@ss.hasPermi('demo:demo:export')")
@Log(title = "测试单表", businessType = BusinessType.EXPORT)
@GetMapping("/export")
@PostMapping("/export")
public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
List<TestDemoVo> list = iTestDemoService.queryList(bo);
// 测试雪花id导出
// 测试雪花id导出
// for (TestDemoVo vo : list) {
// vo.setId(1234567891234567893L);
// }
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
}
/**
@@ -85,8 +105,9 @@ public class TestDemoController extends BaseController {
@ApiOperation("获取测试单表详细信息")
@PreAuthorize("@ss.hasPermi('demo:demo:query')")
@GetMapping("/{id}")
public AjaxResult<TestDemoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
public AjaxResult<TestDemoVo> getInfo(@ApiParam("测试ID")
@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return AjaxResult.success(iTestDemoService.queryById(id));
}
@@ -98,7 +119,10 @@ public class TestDemoController extends BaseController {
@Log(title = "测试单表", businessType = BusinessType.INSERT)
@RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "不允许重复提交")
@PostMapping()
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody TestDemoBo bo) {
public AjaxResult<Void> add(@RequestBody TestDemoBo bo) {
// 使用校验工具对标 @Validated(AddGroup.class) 注解
// 用于在非 Controller 的地方校验对象
ValidatorUtils.validate(bo, AddGroup.class);
return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0);
}
@@ -119,10 +143,11 @@ public class TestDemoController extends BaseController {
*/
@ApiOperation("删除测试单表")
@PreAuthorize("@ss.hasPermi('demo:demo:remove')")
@Log(title = "测试单表" , businessType = BusinessType.DELETE)
@Log(title = "测试单表", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
public AjaxResult<Void> remove(@ApiParam("测试ID串")
@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
}
}

View File

@@ -4,16 +4,24 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 测试国际化
*
* @author Lion Li
*/
@Validated
@Api(value = "测试国际化控制器", tags = {"测试国际化管理"})
@RestController
@RequestMapping("/demo/i18n")
@@ -27,7 +35,42 @@ public class TestI18nController {
*/
@ApiOperation("通过code获取国际化内容")
@GetMapping()
public AjaxResult<Void> get(String code) {
public AjaxResult<Void> get(@ApiParam("国际化code") String code) {
return AjaxResult.success(MessageUtils.message(code));
}
/**
* Validator 校验国际化
* 不传值 分别查看异常返回
*
* 测试使用 not.null
*/
@ApiOperation("Validator 校验国际化")
@GetMapping("/test1")
public AjaxResult<Void> test1(@NotBlank(message = "{not.null}") String str) {
return AjaxResult.success(str);
}
/**
* Bean 校验国际化
* 不传值 分别查看异常返回
*
* 测试使用 not.null
*/
@ApiOperation("Bean 校验国际化")
@GetMapping("/test2")
public AjaxResult<TestI18nBo> test2(@Validated TestI18nBo bo) {
return AjaxResult.success(bo);
}
@Data
public static class TestI18nBo {
@NotBlank(message = "{not.null}")
private String name;
@NotNull(message = "{not.null}")
@Range(min = 0, max = 100, message = "{length.not.valid}")
private Integer age;
}
}

View File

@@ -14,6 +14,7 @@ import com.ruoyi.demo.domain.vo.TestTreeVo;
import com.ruoyi.demo.service.ITestTreeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -61,7 +62,7 @@ public class TestTreeController extends BaseController {
@GetMapping("/export")
public void export(@Validated TestTreeBo bo, HttpServletResponse response) {
List<TestTreeVo> list = iTestTreeService.queryList(bo);
ExcelUtil.exportExcel(list, "测试树表", TestTreeVo.class, response);
ExcelUtil.exportExcel(list, "测试树表", TestTreeVo.class, response);
}
/**
@@ -70,8 +71,9 @@ public class TestTreeController extends BaseController {
@ApiOperation("获取测试树表详细信息")
@PreAuthorize("@ss.hasPermi('demo:tree:query')")
@GetMapping("/{id}")
public AjaxResult<TestTreeVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
public AjaxResult<TestTreeVo> getInfo(@ApiParam("测试树ID")
@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return AjaxResult.success(iTestTreeService.queryById(id));
}
@@ -104,10 +106,11 @@ public class TestTreeController extends BaseController {
*/
@ApiOperation("删除测试树表")
@PreAuthorize("@ss.hasPermi('demo:tree:remove')")
@Log(title = "测试树表" , businessType = BusinessType.DELETE)
@Log(title = "测试树表", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
public AjaxResult<Void> remove(@ApiParam("测试树ID串")
@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
}
}

View File

@@ -1,27 +0,0 @@
package com.ruoyi.demo.feign;
import com.ruoyi.demo.feign.constant.FeignTestConstant;
import com.ruoyi.demo.feign.fallback.FeignTestFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* feign测试service
* 规范接口 Service 无感调用
* 常量管理请求路径 更加规范
* 自定义容错处理 安全可靠 (需自行配置熔断器)
* 增加 feign 的目的为使 http 请求接口化
*
* @author Lion Li
* @deprecated 由于使用人数较少 决定与 3.4.0 版本移除
*/
@FeignClient(
name = FeignTestConstant.BAIDU_NAME,
url = FeignTestConstant.BAIDU_URL,
fallback = FeignTestFallback.class)
public interface FeignTestService {
@GetMapping("/s")
String search(@RequestParam("wd") String wd);
}

View File

@@ -1,13 +0,0 @@
package com.ruoyi.demo.feign.constant;
/**
* @deprecated 由于使用人数较少 决定与 3.4.0 版本移除
*/
@Deprecated
public class FeignTestConstant {
public static final String BAIDU_NAME = "baidu";
public static final String BAIDU_URL = "http://www.baidu.com";
}

View File

@@ -1,28 +0,0 @@
package com.ruoyi.demo.feign.fallback;
import com.ruoyi.demo.feign.FeignTestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* feign测试fallback
* 自定义封装结构体熔断
* 需重写解码器 根据自定义实体 自行解析熔断
*
* 熔断器需要自行添加配置
*
* @see {com.ruoyi.framework.config.FeignConfig#errorDecoder()}
* @author Lion Li
* @deprecated 由于使用人数较少 决定与 3.4.0 版本移除
*/
@Slf4j
@Component
public class FeignTestFallback implements FeignTestService {
@Override
public String search(String wd) {
log.error("fallback");
return "报错啦";
}
}

View File

@@ -1 +0,0 @@
package com.ruoyi.demo.feign.fallback;

View File

@@ -1 +0,0 @@
package com.ruoyi.demo.feign;

View File

@@ -2,11 +2,9 @@ package com.ruoyi.demo.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.domain.vo.TestDemoVo;
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.annotations.Param;
/**
@@ -15,8 +13,6 @@ import org.apache.ibatis.annotations.Param;
* @author Lion Li
* @date 2021-07-26
*/
// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象
@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class)
public interface TestDemoMapper extends BaseMapperPlus<TestDemo> {
Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper);

View File

@@ -5,9 +5,11 @@ import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.service.UserService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@@ -64,8 +66,8 @@ public class DataScopeAspect {
// 获取当前的用户
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNotNull(loginUser)) {
SysUser currentUser = loginUser.getUser();
// 如果是超级管理员,则不过滤数据
SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId());
// 如果是超级管理员,则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), controllerDataScope.isUser());

View File

@@ -1,13 +1,12 @@
package com.ruoyi.framework.aspectj;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.properties.TokenProperties;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
@@ -18,8 +17,14 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 防止重复提交
@@ -34,7 +39,6 @@ public class RepeatSubmitAspect {
private final TokenProperties tokenProperties;
private final RepeatSubmitProperties repeatSubmitProperties;
private final LockTemplate lockTemplate;
@Before("@annotation(repeatSubmit)")
public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
@@ -47,7 +51,7 @@ public class RepeatSubmitAspect {
throw new ServiceException("重复提交间隔时间不能小于'1'秒");
}
HttpServletRequest request = ServletUtils.getRequest();
String nowParams = StrUtil.join(",", point.getArgs());
String nowParams = argsArrayToString(point.getArgs());
// 请求地址作为存放cache的key值
String url = request.getRequestURI();
@@ -60,10 +64,58 @@ public class RepeatSubmitAspect {
submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
// 唯一标识指定key + 消息头)
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
LockInfo lock = lockTemplate.lock(cacheRepeatKey, interval, interval / 2);
if (lock == null) {
String key = RedisUtils.getCacheObject(cacheRepeatKey);
if (key == null) {
RedisUtils.setCacheObject(cacheRepeatKey, "", interval, TimeUnit.MILLISECONDS);
} else {
throw new ServiceException(repeatSubmit.message());
}
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) {
for (Object o : paramsArray) {
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
try {
params.append(JsonUtils.toJsonString(o)).append(" ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return params.toString().trim();
}
/**
* 判断是否需要过滤的对象。
*
* @param o 对象信息。
* @return 如果是需要过滤的对象则返回true否则返回false。
*/
@SuppressWarnings("rawtypes")
public boolean isFilterObject(final Object o) {
Class<?> clazz = o.getClass();
if (clazz.isArray()) {
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
} else if (Collection.class.isAssignableFrom(clazz)) {
Collection collection = (Collection) o;
for (Object value : collection) {
return value instanceof MultipartFile;
}
} else if (Map.class.isAssignableFrom(clazz)) {
Map map = (Map) o;
for (Object value : map.entrySet()) {
Map.Entry entry = (Map.Entry) value;
return entry.getValue() instanceof MultipartFile;
}
}
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|| o instanceof BindingResult;
}
}

View File

@@ -1,95 +0,0 @@
package com.ruoyi.framework.config;
import feign.*;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* openfeign配置类
*
* @author Lion Li
* @deprecated 由于使用人数较少 决定与 3.4.0 版本移除
*/
@Deprecated
@EnableFeignClients("${feign.package}")
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignConfig {
@Bean
public OkHttpClient okHttpClient(){
return new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool())
.build();
}
@Bean
public Contract feignContract() {
return new SpringMvcContract();
}
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.BASIC;
}
@Bean
public Request.Options feignRequestOptions() {
return new Request.Options(10, TimeUnit.SECONDS, 60,TimeUnit.SECONDS,true);
}
@Bean
public Retryer feignRetry() {
return new Retryer.Default();
}
// /**
// * 自定义异常解码器
// * 用于自定义返回体异常熔断
// */
// @Bean
// public ErrorDecoder errorDecoder() {
// return new CustomErrorDecoder();
// }
//
//
// /**
// * 自定义返回体解码器
// */
// @Slf4j
// public static class CustomErrorDecoder implements ErrorDecoder {
//
// @Override
// public Exception decode(String methodKey, Response response) {
// Exception exception = null;
// try {
// // 获取原始的返回内容
// String json = JsonUtils.toJsonString(response.body().asReader(StandardCharsets.UTF_8));
// exception = new RuntimeException(json);
// // 将返回内容反序列化为Result这里应根据自身项目作修改
// AjaxResult result = JsonUtils.parseObject(json, AjaxResult.class);
// // 业务异常抛出简单的 RuntimeException保留原来错误信息
// if (result.getCode() != 200) {
// exception = new RuntimeException(result.getMsg());
// }
// } catch (IOException e) {
// log.error(e.getMessage(), e);
// }
// return exception;
// }
// }
}

View File

@@ -20,7 +20,6 @@ import java.util.Map;
* @author Lion Li
*/
@Configuration
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public class FilterConfig {
@Autowired
@@ -28,6 +27,7 @@ public class FilterConfig {
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);

View File

@@ -1,7 +1,6 @@
package com.ruoyi.framework.config;
import cn.hutool.core.util.StrUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
@@ -28,7 +27,6 @@ public class I18nConfig {
*/
static class I18nLocaleResolver implements LocaleResolver {
@NotNull
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String language = httpServletRequest.getHeader("content-language");
@@ -41,7 +39,7 @@ public class I18nConfig {
}
@Override
public void setLocale(@NotNull HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}

View File

@@ -21,18 +21,17 @@ import org.springframework.web.filter.CorsFilter;
/**
* spring security配置
*
*
* @author ruoyi
*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 自定义用户认证逻辑
*/
@Autowired
private UserDetailsService userDetailsService;
/**
* 认证失败处理类
*/
@@ -50,7 +49,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域过滤器
*/
@@ -68,8 +67,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@@ -89,31 +87,30 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* authenticated | 用户登录后可访问
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// CSRF禁用因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
.antMatchers(securityProperties.getAnonymous()).anonymous()
.antMatchers(securityProperties.getPermitAll()).permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
// CSRF禁用因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
.antMatchers(securityProperties.getAnonymous()).anonymous()
.antMatchers(securityProperties.getPermitAll()).permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl(securityProperties.getLogoutUrl()).logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
@@ -126,8 +123,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@@ -135,8 +131,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}

View File

@@ -1,6 +1,7 @@
package com.ruoyi.framework.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import com.ruoyi.common.properties.TokenProperties;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
@@ -35,6 +36,9 @@ public class SwaggerConfig {
@Autowired
private TokenProperties tokenProperties;
@Autowired
private OpenApiExtensionResolver openApiExtensionResolver;
/**
* 创建API
*/
@@ -59,6 +63,7 @@ public class SwaggerConfig {
// 设置安全模式swagger可以设置访问token
.securitySchemes(securitySchemes())
.securityContexts(securityContexts())
.extensions(openApiExtensionResolver.buildExtensions(group.getName()))
.pathMapping(swaggerProperties.getPathMapping());
String beanName = StringUtils.substringAfterLast(basePackage, ".") + "Docket";
SpringUtils.registerBean(beanName, docket);

View File

@@ -1,7 +1,6 @@
package com.ruoyi.framework.config;
import com.yomahub.tlog.core.aop.AspectLogAop;
import com.yomahub.tlog.feign.filter.TLogFeignFilter;
import com.yomahub.tlog.spring.TLogPropertyInit;
import com.yomahub.tlog.spring.TLogSpringAware;
import com.yomahub.tlog.springboot.property.TLogProperty;
@@ -41,9 +40,4 @@ public class TLogConfig {
return new AspectLogAop();
}
@Bean
public TLogFeignFilter tLogFeignFilter() {
return new TLogFeignFilter();
}
}

View File

@@ -1,12 +1,14 @@
package com.ruoyi.framework.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Properties;
/**
* 校验框架配置类
@@ -16,16 +18,26 @@ import javax.validation.ValidatorFactory;
@Configuration
public class ValidatorConfig {
@Autowired
private MessageSource messageSource;
/**
* 配置校验框架 快速返回模式
*/
@Bean
public Validator validator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory();
return validatorFactory.getValidator();
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
// 国际化
factoryBean.setValidationMessageSource(messageSource);
// 设置使用 HibernateValidator 校验器
factoryBean.setProviderClass(HibernateValidator.class);
Properties properties = new Properties();
// 设置 快速异常返回
properties.setProperty("hibernate.validator.fail_fast", "true");
factoryBean.setValidationProperties(properties);
// 加载配置
factoryBean.afterPropertiesSet();
return factoryBean.getValidator();
}
}

View File

@@ -14,7 +14,7 @@ import java.util.concurrent.ScheduledExecutorService;
*
* @author Lion Li
*/
@Slf4j(topic = "sys-user")
@Slf4j
@Component
public class ShutdownManager {

View File

@@ -6,6 +6,7 @@ import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
@@ -14,7 +15,9 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
/**
* 全局异常处理器
@@ -82,7 +85,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(BindException.class)
public AjaxResult<Void> handleBindException(BindException e) {
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
String message = e.getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", "));
return AjaxResult.error(message);
}
@@ -92,7 +97,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public AjaxResult<Void> constraintViolationException(ConstraintViolationException e) {
log.error(e.getMessage(), e);
String message = e.getConstraintViolations().iterator().next().getMessage();
String message = e.getConstraintViolations().stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
return AjaxResult.error(message);
}

View File

@@ -1,6 +1,7 @@
package com.ruoyi.generator.controller;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -13,7 +14,6 @@ import com.ruoyi.generator.service.IGenTableService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
@@ -201,6 +201,6 @@ public class GenController extends BaseController {
response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8");
IOUtils.write(data, response.getOutputStream());
IoUtil.write(response.getOutputStream(), false, data);
}
}
}

View File

@@ -2,6 +2,7 @@ package com.ruoyi.generator.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.GenConstants;
@@ -21,7 +22,7 @@ import com.ruoyi.generator.util.GenUtils;
import com.ruoyi.generator.util.VelocityInitializer;
import com.ruoyi.generator.util.VelocityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.poi.util.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
@@ -33,6 +34,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
@@ -341,8 +343,8 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
try {
// 添加到zip
zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
IOUtils.write(sw.toString(), zip, Constants.UTF8);
IOUtils.closeQuietly(sw);
IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
IoUtil.close(sw);
zip.flush();
zip.closeEntry();
} catch (IOException e) {

View File

@@ -19,10 +19,9 @@ public class VelocityInitializer {
Properties p = new Properties();
try {
// 加载classpath目录下的vm文件
p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 定义字符集
p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
p.setProperty(Velocity.OUTPUT_ENCODING, Constants.UTF8);
// 初始化Velocity引擎指定配置Properties
Velocity.init(p);
} catch (Exception e) {

View File

@@ -247,7 +247,8 @@ public class VelocityUtils {
List<String> dicts = new ArrayList<String>();
for (GenTableColumn column : columns) {
if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
column.getHtmlType(), new String[]{GenConstants.HTML_SELECT, GenConstants.HTML_RADIO})) {
column.getHtmlType(),
new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) {
dicts.add("'" + column.getDictType() + "'");
}
}

View File

@@ -1,38 +0,0 @@
package com.ruoyi.oss.constant;
import java.util.Arrays;
import java.util.List;
/**
* 对象存储常量
*
* @author Lion Li
*/
public class CloudConstant {
/**
* OSS模块KEY
*/
public static final String SYS_OSS_KEY = "sys_oss:";
/**
* 对象存储配置KEY
*/
public static final String CLOUD_STORAGE_CONFIG_KEY = "CloudStorageConfig";
/**
* 缓存配置KEY
*/
public static final String CACHE_CONFIG_KEY = SYS_OSS_KEY + CLOUD_STORAGE_CONFIG_KEY;
/**
* 预览列表资源开关Key
*/
public static final String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
/**
* 系统数据ids
*/
public static final List<Integer> SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
}

View File

@@ -1,63 +0,0 @@
package com.ruoyi.oss.enumd;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.service.impl.AliyunCloudStorageStrategy;
import com.ruoyi.oss.service.impl.MinioCloudStorageStrategy;
import com.ruoyi.oss.service.impl.QcloudCloudStorageStrategy;
import com.ruoyi.oss.service.impl.QiniuCloudStorageStrategy;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 对象存储服务商枚举
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum CloudServiceEnumd {
/**
* 七牛云
*/
QINIU("qiniu", QiniuCloudStorageStrategy.class),
/**
* 阿里云
*/
ALIYUN("aliyun", AliyunCloudStorageStrategy.class),
/**
* 腾讯云
*/
QCLOUD("qcloud", QcloudCloudStorageStrategy.class),
/**
* minio
*/
MINIO("minio", MinioCloudStorageStrategy.class);
private final String value;
private final Class<?> serviceClass;
public static Class<?> getServiceClass(String value) {
for (CloudServiceEnumd clazz : values()) {
if (clazz.getValue().equals(value)) {
return clazz.getServiceClass();
}
}
return null;
}
public static String getServiceName(String value) {
for (CloudServiceEnumd clazz : values()) {
if (clazz.getValue().equals(value)) {
return StringUtils.uncapitalize(clazz.getServiceClass().getSimpleName());
}
}
return null;
}
}

View File

@@ -1,16 +1,15 @@
package com.ruoyi.oss.factory;
import cn.hutool.core.convert.Convert;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.oss.constant.CloudConstant;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.constant.OssConstant;
import com.ruoyi.oss.enumd.OssEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.ICloudStorageStrategy;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import com.ruoyi.oss.properties.OssProperties;
import com.ruoyi.oss.service.IOssStrategy;
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@@ -24,24 +23,31 @@ import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class OssFactory {
static {
RedisUtils.subscribe(CloudConstant.CACHE_CONFIG_KEY, String.class, msg -> {
refreshService(msg);
log.info("订阅刷新OSS配置 => " + msg);
});
}
/**
* 服务实例缓存
*/
private static final Map<String, ICloudStorageStrategy> SERVICES = new ConcurrentHashMap<>();
private static final Map<String, IOssStrategy> SERVICES = new ConcurrentHashMap<>();
/**
* 初始化工厂
*/
public static void init() {
log.info("初始化OSS工厂");
RedisUtils.subscribe(OssConstant.CACHE_CONFIG_KEY, String.class, type -> {
// 没有的实例不处理
if (SERVICES.containsKey(type)) {
refreshService(type);
log.info("订阅刷新OSS配置 => " + type);
}
});
}
/**
* 获取默认实例
*/
public static ICloudStorageStrategy instance() {
public static IOssStrategy instance() {
// 获取redis 默认类型
String type = Convert.toStr(RedisUtils.getCacheObject(CloudConstant.CACHE_CONFIG_KEY));
String type = RedisUtils.getCacheObject(OssConstant.CACHE_CONFIG_KEY);
if (StringUtils.isEmpty(type)) {
throw new OssException("文件存储服务类型无法找到!");
}
@@ -51,8 +57,8 @@ public class OssFactory {
/**
* 根据类型获取实例
*/
public static ICloudStorageStrategy instance(String type) {
ICloudStorageStrategy service = SERVICES.get(type);
public static IOssStrategy instance(String type) {
IOssStrategy service = SERVICES.get(type);
if (service == null) {
refreshService(type);
service = SERVICES.get(type);
@@ -61,14 +67,14 @@ public class OssFactory {
}
private static void refreshService(String type) {
Object json = RedisUtils.getCacheObject(CloudConstant.SYS_OSS_KEY + type);
CloudStorageProperties properties = JsonUtils.parseObject(json.toString(), CloudStorageProperties.class);
Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + type);
OssProperties properties = JsonUtils.parseObject(json.toString(), OssProperties.class);
if (properties == null) {
throw new OssException("系统异常, '" + type + "'配置信息不存在!");
}
// 获取redis配置信息 创建对象 并缓存
ICloudStorageStrategy service = (ICloudStorageStrategy) ReflectUtils.newInstance(CloudServiceEnumd.getServiceClass(type));
((AbstractCloudStorageStrategy)service).init(properties);
IOssStrategy service = (IOssStrategy) ReflectUtils.newInstance(OssEnumd.getServiceClass(type));
((AbstractOssStrategy)service).init(properties);
SERVICES.put(type, service);
}

View File

@@ -1,55 +0,0 @@
package com.ruoyi.oss.properties;
import lombok.Data;
import java.util.Date;
/**
* OSS对象存储 配置属性
*
* @author Lion Li
*/
@Data
public class CloudStorageProperties {
/**
* 域名
*/
private String endpoint;
/**
* 前缀
*/
private String prefix;
/**
* ACCESS_KEY
*/
private String accessKey;
/**
* SECRET_KEY
*/
private String secretKey;
/**
* 存储空间名
*/
private String bucketName;
/**
* 存储区域
*/
private String region;
/**
* 是否httpsY=是,N=否)
*/
private String isHttps;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@@ -1,74 +0,0 @@
package com.ruoyi.oss.service;
import com.ruoyi.oss.entity.UploadResult;
import java.io.InputStream;
/**
* 对象存储策略
*
* @author Lion Li
*/
public interface ICloudStorageStrategy {
void createBucket();
/**
* 获取服务商类型
*/
String getServiceType();
/**
* 文件路径
*
* @param prefix 前缀
* @param suffix 后缀
* @return 返回上传路径
*/
String getPath(String prefix, String suffix);
/**
* 文件上传
*
* @param data 文件字节数组
* @param path 文件路径,包含文件名
* @return 返回http地址
*/
UploadResult upload(byte[] data, String path, String contentType);
/**
* 文件删除
*
* @param path 文件路径,包含文件名
*/
void delete(String path);
/**
* 文件上传
*
* @param data 文件字节数组
* @param suffix 后缀
* @return 返回http地址
*/
UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
/**
* 文件上传
*
* @param inputStream 字节流
* @param path 文件路径,包含文件名
* @return 返回http地址
*/
UploadResult upload(InputStream inputStream, String path, String contentType);
/**
* 文件上传
*
* @param inputStream 字节流
* @param suffix 后缀
* @return 返回http地址
*/
UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
String getEndpointLink();
}

View File

@@ -1,62 +0,0 @@
package com.ruoyi.oss.service.abstractd;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.ICloudStorageStrategy;
import java.io.InputStream;
/**
* 对象存储策略(支持七牛、阿里云、腾讯云、minio)
*
* @author Lion Li
*/
public abstract class AbstractCloudStorageStrategy implements ICloudStorageStrategy {
protected CloudStorageProperties properties;
public abstract void init(CloudStorageProperties properties);
@Override
public abstract void createBucket();
@Override
public abstract String getServiceType();
@Override
public String getPath(String prefix, String suffix) {
// 生成uuid
String uuid = IdUtil.fastSimpleUUID();
// 文件路径
String path = DateUtils.datePath() + "/" + uuid;
if (StringUtils.isNotBlank(prefix)) {
path = prefix + "/" + path;
}
return path + suffix;
}
@Override
public abstract UploadResult upload(byte[] data, String path, String contentType);
@Override
public abstract void delete(String path);
@Override
public UploadResult upload(InputStream inputStream, String path, String contentType) {
byte[] data = IoUtil.readBytes(inputStream);
return this.upload(data, path, contentType);
}
@Override
public abstract UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
@Override
public abstract UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
@Override
public abstract String getEndpointLink();
}

View File

@@ -1,113 +0,0 @@
package com.ruoyi.oss.service.impl;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* 阿里云存储策略
*
* @author Lion Li
*/
public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
private OSSClient client;
@Override
public void init(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
ClientConfiguration configuration = new ClientConfiguration();
DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider(
properties.getAccessKey(), properties.getSecretKey());
client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
createBucket();
} catch (Exception e) {
throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
}
}
@Override
public void createBucket() {
try {
String bucketName = properties.getBucketName();
if (client.doesBucketExist(bucketName)) {
return;
}
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
client.createBucket(createBucketRequest);
} catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]");
}
}
@Override
public String getServiceType() {
return CloudServiceEnumd.ALIYUN.getValue();
}
@Override
public UploadResult upload(byte[] data, String path, String contentType) {
return upload(new ByteArrayInputStream(data), path, contentType);
}
@Override
public UploadResult upload(InputStream inputStream, String path, String contentType) {
try {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(contentType);
client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
} catch (Exception e) {
throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
}
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
}
@Override
public void delete(String path) {
path = path.replace(getEndpointLink() + "/", "");
try {
client.deleteObject(properties.getBucketName(), path);
} catch (Exception e) {
throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
}
}
@Override
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public String getEndpointLink() {
String endpoint = properties.getEndpoint();
StringBuilder sb = new StringBuilder(endpoint);
if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
sb.insert(7, properties.getBucketName() + ".");
} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
sb.insert(8, properties.getBucketName() + ".");
} else {
throw new OssException("Endpoint配置错误");
}
return sb.toString();
}
}

View File

@@ -1,181 +0,0 @@
package com.ruoyi.oss.service.impl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.enumd.PolicyType;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import io.minio.*;
import org.springframework.http.MediaType;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* minio存储策略
*
* @author Lion Li
*/
public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
private MinioClient minioClient;
@Override
public void init(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
minioClient = MinioClient.builder()
.endpoint(properties.getEndpoint())
.credentials(properties.getAccessKey(), properties.getSecretKey())
.build();
createBucket();
} catch (Exception e) {
throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
}
}
@Override
public void createBucket() {
try {
String bucketName = properties.getBucketName();
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (exists) {
return;
}
// 不存在就创建桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(getPolicy(bucketName, PolicyType.READ))
.build());
} catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]");
}
}
@Override
public String getServiceType() {
return CloudServiceEnumd.MINIO.getValue();
}
@Override
public UploadResult upload(byte[] data, String path, String contentType) {
return upload(new ByteArrayInputStream(data), path, contentType);
}
@Override
public UploadResult upload(InputStream inputStream, String path, String contentType) {
try {
minioClient.putObject(PutObjectArgs.builder()
.bucket(properties.getBucketName())
.object(path)
.contentType(StringUtils.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE))
.stream(inputStream, inputStream.available(), -1)
.build());
} catch (Exception e) {
throw new OssException("上传文件失败请核对Minio配置信息:[" + e.getMessage() + "]");
}
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
}
@Override
public void delete(String path) {
path = path.replace(getEndpointLink() + "/", "");
try {
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(properties.getBucketName())
.object(path)
.build());
} catch (Exception e) {
throw new OssException(e.getMessage());
}
}
@Override
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public String getEndpointLink() {
return properties.getEndpoint() + "/" + properties.getBucketName();
}
private String getPolicy(String bucketName, PolicyType policyType) {
StringBuilder builder = new StringBuilder();
builder.append("{\n");
builder.append(" \"Statement\": [\n");
builder.append(" {\n");
builder.append(" \"Action\": [\n");
if (policyType == PolicyType.WRITE) {
builder.append(" \"s3:GetBucketLocation\",\n");
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
} else if (policyType == PolicyType.READ_WRITE) {
builder.append(" \"s3:GetBucketLocation\",\n");
builder.append(" \"s3:ListBucket\",\n");
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
} else {
builder.append(" \"s3:GetBucketLocation\"\n");
}
builder.append(" ],\n");
builder.append(" \"Effect\": \"Allow\",\n");
builder.append(" \"Principal\": \"*\",\n");
builder.append(" \"Resource\": \"arn:aws:s3:::");
builder.append(bucketName);
builder.append("\"\n");
builder.append(" },\n");
if (PolicyType.READ.equals(policyType)) {
builder.append(" {\n");
builder.append(" \"Action\": [\n");
builder.append(" \"s3:ListBucket\"\n");
builder.append(" ],\n");
builder.append(" \"Effect\": \"Deny\",\n");
builder.append(" \"Principal\": \"*\",\n");
builder.append(" \"Resource\": \"arn:aws:s3:::");
builder.append(bucketName);
builder.append("\"\n");
builder.append(" },\n");
}
builder.append(" {\n");
builder.append(" \"Action\": ");
switch (policyType) {
case WRITE:
builder.append("[\n");
builder.append(" \"s3:AbortMultipartUpload\",\n");
builder.append(" \"s3:DeleteObject\",\n");
builder.append(" \"s3:ListMultipartUploadParts\",\n");
builder.append(" \"s3:PutObject\"\n");
builder.append(" ],\n");
break;
case READ_WRITE:
builder.append("[\n");
builder.append(" \"s3:AbortMultipartUpload\",\n");
builder.append(" \"s3:DeleteObject\",\n");
builder.append(" \"s3:GetObject\",\n");
builder.append(" \"s3:ListMultipartUploadParts\",\n");
builder.append(" \"s3:PutObject\"\n");
builder.append(" ],\n");
break;
default:
builder.append("\"s3:GetObject\",\n");
break;
}
builder.append(" \"Effect\": \"Allow\",\n");
builder.append(" \"Principal\": \"*\",\n");
builder.append(" \"Resource\": \"arn:aws:s3:::");
builder.append(bucketName);
builder.append("/*\"\n");
builder.append(" }\n");
builder.append(" ],\n");
builder.append(" \"Version\": \"2012-10-17\"\n");
builder.append("}\n");
return builder.toString();
}
}

View File

@@ -1,121 +0,0 @@
package com.ruoyi.oss.service.impl;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* 腾讯云存储策略
*
* @author Lion Li
*/
public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
private COSClient client;
@Override
public void init(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
COSCredentials credentials = new BasicCOSCredentials(
properties.getAccessKey(), properties.getSecretKey());
// 初始化客户端配置
ClientConfig clientConfig = new ClientConfig();
// 设置bucket所在的区域华南gz 华北tj 华东sh
clientConfig.setRegion(new Region(properties.getRegion()));
if ("Y".equals(properties.getIsHttps())) {
clientConfig.setHttpProtocol(HttpProtocol.https);
} else {
clientConfig.setHttpProtocol(HttpProtocol.http);
}
client = new COSClient(credentials, clientConfig);
createBucket();
} catch (Exception e) {
throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
}
}
@Override
public void createBucket() {
try {
String bucketName = properties.getBucketName();
if (client.doesBucketExist(bucketName)) {
return;
}
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
client.createBucket(createBucketRequest);
} catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]");
}
}
@Override
public String getServiceType() {
return CloudServiceEnumd.QCLOUD.getValue();
}
@Override
public UploadResult upload(byte[] data, String path, String contentType) {
return upload(new ByteArrayInputStream(data), path, contentType);
}
@Override
public UploadResult upload(InputStream inputStream, String path, String contentType) {
try {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(contentType);
client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
} catch (Exception e) {
throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]");
}
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
}
@Override
public void delete(String path) {
path = path.replace(getEndpointLink() + "/", "");
try {
client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path));
} catch (Exception e) {
throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]");
}
}
@Override
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public String getEndpointLink() {
String endpoint = properties.getEndpoint();
StringBuilder sb = new StringBuilder(endpoint);
if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
sb.insert(7, properties.getBucketName() + ".");
} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
sb.insert(8, properties.getBucketName() + ".");
} else {
throw new OssException("Endpoint配置错误");
}
return sb.toString();
}
}

View File

@@ -1,127 +0,0 @@
package com.ruoyi.oss.service.impl;
import cn.hutool.core.util.ArrayUtil;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import java.io.InputStream;
/**
* 七牛云存储策略
*
* @author Lion Li
*/
public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
private UploadManager uploadManager;
private BucketManager bucketManager;
private String token;
@Override
public void init(CloudStorageProperties cloudStorageProperties) {
properties = cloudStorageProperties;
try {
Configuration config = new Configuration(getRegion(properties.getRegion()));
// https设置
config.useHttpsDomains = false;
config.useHttpsDomains = "Y".equals(properties.getIsHttps());
uploadManager = new UploadManager(config);
Auth auth = Auth.create(properties.getAccessKey(), properties.getSecretKey());
String bucketName = properties.getBucketName();
token = auth.uploadToken(bucketName);
bucketManager = new BucketManager(auth, config);
if (!ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
bucketManager.createBucket(bucketName, properties.getRegion());
}
} catch (Exception e) {
throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
}
}
@Override
public void createBucket() {
try {
String bucketName = properties.getBucketName();
if (ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
return;
}
bucketManager.createBucket(bucketName, properties.getRegion());
} catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]");
}
}
@Override
public String getServiceType() {
return CloudServiceEnumd.QINIU.getValue();
}
@Override
public UploadResult upload(byte[] data, String path, String contentType) {
try {
Response res = uploadManager.put(data, path, token, null, contentType, false);
if (!res.isOK()) {
throw new RuntimeException("上传七牛出错:" + res.toString());
}
} catch (Exception e) {
throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]");
}
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
}
@Override
public void delete(String path) {
try {
path = path.replace(getEndpointLink() + "/", "");
Response res = bucketManager.delete(properties.getBucketName(), path);
if (!res.isOK()) {
throw new RuntimeException("删除七牛文件出错:" + res.toString());
}
} catch (Exception e) {
throw new OssException(e.getMessage());
}
}
@Override
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
return upload(data, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
}
@Override
public String getEndpointLink() {
return properties.getEndpoint();
}
private Region getRegion(String region) {
switch (region) {
case "z0":
return Region.region0();
case "z1":
return Region.region1();
case "z2":
return Region.region2();
case "na0":
return Region.regionNa0();
case "as0":
return Region.regionAs0();
default:
return Region.autoRegion();
}
}
}

View File

@@ -67,7 +67,7 @@ public class SysUserImportVo implements Serializable {
* 帐号状态0正常 1停用
*/
@ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_common_status")
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
}

View File

@@ -58,6 +58,6 @@ public interface SysMenuMapper extends BaseMapperPlus<SysMenu> {
* @param menuCheckStrictly 菜单树选择项是否关联显示
* @return 选中菜单列表
*/
List<Integer> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
}

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.service;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import java.util.List;
@@ -20,21 +20,13 @@ public interface ISysDeptService extends IService<SysDept> {
*/
List<SysDept> selectDeptList(SysDept dept);
/**
* 构建前端所需要树结构
*
* @param depts 部门列表
* @return 树结构列表
*/
List<SysDept> buildDeptTree(List<SysDept> depts);
/**
* 构建前端所需要下拉树结构
*
* @param depts 部门列表
* @return 下拉树结构列表
*/
List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts);
List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts);
/**
* 根据角色ID查询部门树信息

View File

@@ -1,7 +1,7 @@
package com.ruoyi.system.service;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.system.domain.vo.RouterVo;
@@ -54,7 +54,7 @@ public interface ISysMenuService extends IService<SysMenu> {
* @param roleId 角色ID
* @return 选中菜单列表
*/
List<Integer> selectMenuListByRoleId(Long roleId);
List<Long> selectMenuListByRoleId(Long roleId);
/**
* 构建前端路由所需要的菜单
@@ -64,21 +64,13 @@ public interface ISysMenuService extends IService<SysMenu> {
*/
List<RouterVo> buildMenus(List<SysMenu> menus);
/**
* 构建前端所需要树结构
*
* @param menus 菜单列表
* @return 树结构列表
*/
List<SysMenu> buildMenuTree(List<SysMenu> menus);
/**
* 构建前端所需要下拉树结构
*
* @param menus 菜单列表
* @return 下拉树结构列表
*/
List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus);
List<Tree<Long>> buildMenuTreeSelect(List<SysMenu> menus);
/**
* 根据菜单ID查询信息

View File

@@ -17,6 +17,11 @@ import java.util.Collection;
*/
public interface ISysOssConfigService extends IServicePlus<SysOssConfig, SysOssConfigVo> {
/**
* 初始化OSS配置
*/
void init();
/**
* 查询单个
*/

View File

@@ -3,6 +3,7 @@ package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.UserService;
import java.util.List;
@@ -11,7 +12,7 @@ import java.util.List;
*
* @author Lion Li
*/
public interface ISysUserService extends IService<SysUser> {
public interface ISysUserService extends IService<SysUser>, UserService {
TableDataInfo<SysUser> selectPageUserList(SysUser user);
@@ -46,6 +47,7 @@ public interface ISysUserService extends IService<SysUser> {
* @param userName 用户名
* @return 用户对象信息
*/
@Override
SysUser selectUserByUserName(String userName);
/**
@@ -54,6 +56,7 @@ public interface ISysUserService extends IService<SysUser> {
* @param userId 用户ID
* @return 用户对象信息
*/
@Override
SysUser selectUserById(Long userId);
/**

View File

@@ -1,9 +1,12 @@
package com.ruoyi.system.service;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.service.UserService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@@ -91,10 +94,14 @@ public class PermissionService {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
if (StringUtils.isNull(loginUser)) {
return false;
}
for (SysRole sysRole : loginUser.getUser().getRoles()) {
SysUser sysUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId());
if (CollectionUtils.isEmpty(sysUser.getRoles())) {
return false;
}
for (SysRole sysRole : sysUser.getRoles()) {
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) {
return true;
@@ -124,7 +131,11 @@ public class PermissionService {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
if (StringUtils.isNull(loginUser)) {
return false;
}
SysUser sysUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId());
if (CollectionUtils.isEmpty(sysUser.getRoles())) {
return false;
}
for (String role : roles.split(ROLE_DELIMETER)) {

View File

@@ -7,6 +7,7 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.ConfigService;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils;
@@ -17,7 +18,6 @@ import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -29,29 +29,17 @@ import java.util.Map;
* @author Lion Li
*/
@Service
public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysConfig, SysConfig> implements ISysConfigService {
/**
* 项目启动时,初始化参数到缓存
*/
@PostConstruct
public void init() {
loadingConfigCache();
}
public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysConfig, SysConfig> implements ISysConfigService, ConfigService {
@Override
public TableDataInfo<SysConfig> selectPageConfigList(SysConfig config) {
Map<String, Object> params = config.getParams();
LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
.like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
.eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
.like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"));
.like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
.eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
.like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
return PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
}
@@ -75,12 +63,12 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
*/
@Override
public String selectConfigByKey(String configKey) {
String configValue = Convert.toStr(RedisUtils.getCacheObject(getCacheKey(configKey)));
String configValue = RedisUtils.getCacheObject(getCacheKey(configKey));
if (StringUtils.isNotEmpty(configValue)) {
return configValue;
}
SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
.eq(SysConfig::getConfigKey, configKey));
.eq(SysConfig::getConfigKey, configKey));
if (StringUtils.isNotNull(retConfig)) {
RedisUtils.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
return retConfig.getConfigValue();
@@ -112,15 +100,11 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
public List<SysConfig> selectConfigList(SysConfig config) {
Map<String, Object> params = config.getParams();
LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
.like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
.eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
.like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"));
.like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
.eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
.like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
return baseMapper.selectList(lqw);
}
@@ -217,6 +201,17 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
return UserConstants.UNIQUE;
}
/**
* 根据参数 key 获取参数值
*
* @param configKey 参数 key
* @return 参数值
*/
@Override
public String getConfigValue(String configKey) {
return selectConfigByKey(configKey);
}
/**
* 设置cache key
*

View File

@@ -1,11 +1,11 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
@@ -13,6 +13,7 @@ import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TreeBuildUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper;
@@ -21,10 +22,8 @@ import com.ruoyi.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 部门管理 服务实现
@@ -52,32 +51,6 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
return baseMapper.selectDeptList(dept);
}
/**
* 构建前端所需要树结构
*
* @param depts 部门列表
* @return 树结构列表
*/
@Override
public List<SysDept> buildDeptTree(List<SysDept> depts) {
List<SysDept> returnList = new ArrayList<SysDept>();
List<Long> tempList = new ArrayList<Long>();
for (SysDept dept : depts) {
tempList.add(dept.getDeptId());
}
for (SysDept dept : depts) {
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(dept.getParentId())) {
recursionFn(depts, dept);
returnList.add(dept);
}
}
if (returnList.isEmpty()) {
returnList = depts;
}
return returnList;
}
/**
* 构建前端所需要下拉树结构
*
@@ -85,9 +58,12 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
* @return 下拉树结构列表
*/
@Override
public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts) {
List<SysDept> deptTrees = buildDeptTree(depts);
return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
public List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts) {
return TreeBuildUtils.build(depts, (dept, tree) ->
tree.setId(dept.getDeptId())
.setParentId(dept.getParentId())
.setName(dept.getDeptName())
.setWeight(dept.getOrderNum()));
}
/**
@@ -122,8 +98,8 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
@Override
public long selectNormalChildrenDeptById(Long deptId) {
return count(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getStatus, 0)
.apply("find_in_set({0}, ancestors)", deptId));
.eq(SysDept::getStatus, 0)
.apply("find_in_set({0}, ancestors)", deptId));
}
/**
@@ -135,8 +111,7 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
@Override
public boolean hasChildByDeptId(Long deptId) {
long result = count(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getParentId, deptId)
.last("limit 1"));
.eq(SysDept::getParentId, deptId));
return result > 0;
}
@@ -149,7 +124,7 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
@Override
public boolean checkDeptExistUser(Long deptId) {
long result = userMapper.selectCount(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getDeptId, deptId));
.eq(SysUser::getDeptId, deptId));
return result > 0;
}
@@ -162,11 +137,11 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
@Override
public String checkDeptNameUnique(SysDept dept) {
Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
SysDept info = getOne(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getDeptName, dept.getDeptName())
.eq(SysDept::getParentId, dept.getParentId())
.last("limit 1"));
if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue()) {
long count = count(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getDeptName, dept.getDeptName())
.eq(SysDept::getParentId, dept.getParentId())
.ne(SysDept::getDeptId, deptId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
@@ -224,7 +199,7 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
}
int result = baseMapper.updateById(dept);
if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
&& !StringUtils.equals("0", dept.getAncestors())) {
&& !StringUtils.equals("0", dept.getAncestors())) {
// 如果该部门是启用状态,则启用该部门的所有上级部门
updateParentDeptStatusNormal(dept);
}
@@ -240,8 +215,8 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
String ancestors = dept.getAncestors();
Long[] deptIds = Convert.toLongArray(ancestors);
update(null, new LambdaUpdateWrapper<SysDept>()
.set(SysDept::getStatus, "0")
.in(SysDept::getDeptId, Arrays.asList(deptIds)));
.set(SysDept::getStatus, "0")
.in(SysDept::getDeptId, Arrays.asList(deptIds)));
}
/**
@@ -253,7 +228,7 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
*/
public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
List<SysDept> children = list(new LambdaQueryWrapper<SysDept>()
.apply("find_in_set({0},ancestors)", deptId));
.apply("find_in_set({0},ancestors)", deptId));
for (SysDept child : children) {
child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
}
@@ -273,37 +248,4 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
return baseMapper.deleteById(deptId);
}
/**
* 递归列表
*/
private void recursionFn(List<SysDept> list, SysDept t) {
// 得到子节点列表
List<SysDept> childList = getChildList(list, t);
t.setChildren(childList);
for (SysDept tChild : childList) {
if (hasChild(list, tChild)) {
recursionFn(list, tChild);
}
}
}
/**
* 得到子节点列表
*/
private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
List<SysDept> tlist = new ArrayList<SysDept>();
for (SysDept n : list) {
if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) {
tlist.add(n);
}
}
return tlist;
}
/**
* 判断是否有子节点
*/
private boolean hasChild(List<SysDept> list, SysDept t) {
return getChildList(list, t).size() > 0;
}
}

View File

@@ -1,11 +1,12 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.service.ISysDictDataService;
@@ -85,7 +86,7 @@ public class SysDictDataServiceImpl extends ServicePlusImpl<SysDictDataMapper, S
SysDictData data = selectDictDataById(dictCode);
removeById(dictCode);
List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType());
DictUtils.setDictCache(data.getDictType(), dictDatas);
RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas);
}
}
@@ -100,7 +101,7 @@ public class SysDictDataServiceImpl extends ServicePlusImpl<SysDictDataMapper, S
int row = baseMapper.insert(data);
if (row > 0) {
List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType());
DictUtils.setDictCache(data.getDictType(), dictDatas);
RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas);
}
return row;
}
@@ -116,8 +117,18 @@ public class SysDictDataServiceImpl extends ServicePlusImpl<SysDictDataMapper, S
int row = baseMapper.updateById(data);
if (row > 0) {
List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType());
DictUtils.setDictCache(data.getDictType(), dictDatas);
RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas);
}
return row;
}
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
String getCacheKey(String configKey) {
return Constants.SYS_DICT_KEY + configKey;
}
}

View File

@@ -3,14 +3,16 @@ package com.ruoyi.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.DictService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.mapper.SysDictTypeMapper;
@@ -19,8 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -30,32 +32,20 @@ import java.util.Map;
* @author Lion Li
*/
@Service
public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, SysDictType, SysDictType> implements ISysDictTypeService {
public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, SysDictType, SysDictType> implements ISysDictTypeService, DictService {
@Autowired
private SysDictDataMapper dictDataMapper;
/**
* 项目启动时,初始化字典到缓存
*/
@PostConstruct
public void init() {
loadingDictCache();
}
@Override
public TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType) {
Map<String, Object> params = dictType.getParams();
LambdaQueryWrapper<SysDictType> lqw = new LambdaQueryWrapper<SysDictType>()
.like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
.eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
.like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"));
.like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
.eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
.like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime"));
return PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
}
@@ -69,15 +59,11 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
public List<SysDictType> selectDictTypeList(SysDictType dictType) {
Map<String, Object> params = dictType.getParams();
return list(new LambdaQueryWrapper<SysDictType>()
.like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
.eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
.like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(create_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(create_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime")));
.like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
.eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
.like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime")));
}
/**
@@ -98,13 +84,13 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
*/
@Override
public List<SysDictData> selectDictDataByType(String dictType) {
List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
if (CollUtil.isNotEmpty(dictDatas)) {
List<SysDictData> dictDatas = RedisUtils.getCacheObject(getCacheKey(dictType));
if (StringUtils.isNotEmpty(dictDatas)) {
return dictDatas;
}
dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (CollUtil.isNotEmpty(dictDatas)) {
DictUtils.setDictCache(dictType, dictDatas);
RedisUtils.setCacheObject(getCacheKey(dictType), dictDatas);
return dictDatas;
}
return null;
@@ -143,10 +129,10 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
for (Long dictId : dictIds) {
SysDictType dictType = selectDictTypeById(dictId);
if (dictDataMapper.selectCount(new LambdaQueryWrapper<SysDictData>()
.eq(SysDictData::getDictType, dictType.getDictType())) > 0) {
.eq(SysDictData::getDictType, dictType.getDictType())) > 0) {
throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
}
DictUtils.removeDictCache(dictType.getDictType());
RedisUtils.deleteObject(getCacheKey(dictType.getDictType()));
}
baseMapper.deleteBatchIds(Arrays.asList(dictIds));
}
@@ -159,7 +145,7 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
List<SysDictType> dictTypeList = list();
for (SysDictType dictType : dictTypeList) {
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
DictUtils.setDictCache(dictType.getDictType(), dictDatas);
RedisUtils.setCacheObject(getCacheKey(dictType.getDictType()), dictDatas);
}
}
@@ -168,7 +154,8 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
*/
@Override
public void clearDictCache() {
DictUtils.clearDictCache();
Collection<String> keys = RedisUtils.keys(Constants.SYS_DICT_KEY + "*");
RedisUtils.deleteObject(keys);
}
/**
@@ -190,7 +177,7 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
public int insertDictType(SysDictType dict) {
int row = baseMapper.insert(dict);
if (row > 0) {
DictUtils.setDictCache(dict.getDictType(), null);
RedisUtils.setCacheObject(getCacheKey(dict.getDictType()), null);
}
return row;
}
@@ -206,12 +193,12 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
public int updateDictType(SysDictType dict) {
SysDictType oldDict = getById(dict.getDictId());
dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>()
.set(SysDictData::getDictType, dict.getDictType())
.eq(SysDictData::getDictType, oldDict.getDictType()));
.set(SysDictData::getDictType, dict.getDictType())
.eq(SysDictData::getDictType, oldDict.getDictType()));
int row = baseMapper.updateById(dict);
if (row > 0) {
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType());
DictUtils.setDictCache(dict.getDictType(), dictDatas);
RedisUtils.setCacheObject(getCacheKey(dict.getDictType()), dictDatas);
}
return row;
}
@@ -225,12 +212,86 @@ public class SysDictTypeServiceImpl extends ServicePlusImpl<SysDictTypeMapper, S
@Override
public String checkDictTypeUnique(SysDictType dict) {
Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId();
SysDictType dictType = getOne(new LambdaQueryWrapper<SysDictType>()
.eq(SysDictType::getDictType, dict.getDictType())
.last("limit 1"));
if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue()) {
long count = count(new LambdaQueryWrapper<SysDictType>()
.eq(SysDictType::getDictType, dict.getDictType())
.ne(SysDictType::getDictId, dictId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
@Override
public String getDictLabel(String dictType, String dictValue, String separator) {
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = selectDictDataByType(dictType);
if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) {
for (SysDictData dict : datas) {
for (String value : dictValue.split(separator)) {
if (value.equals(dict.getDictValue())) {
propertyString.append(dict.getDictLabel() + separator);
break;
}
}
}
} else {
for (SysDictData dict : datas) {
if (dictValue.equals(dict.getDictValue())) {
return dict.getDictLabel();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
@Override
public String getDictValue(String dictType, String dictLabel, String separator) {
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = selectDictDataByType(dictType);
if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) {
for (SysDictData dict : datas) {
for (String label : dictLabel.split(separator)) {
if (label.equals(dict.getDictLabel())) {
propertyString.append(dict.getDictValue() + separator);
break;
}
}
}
} else {
for (SysDictData dict : datas) {
if (dictLabel.equals(dict.getDictLabel())) {
return dict.getDictValue();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
String getCacheKey(String configKey) {
return Constants.SYS_DICT_KEY + configKey;
}
}

View File

@@ -90,16 +90,12 @@ public class SysLogininforServiceImpl extends ServicePlusImpl<SysLogininforMappe
public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor) {
Map<String, Object> params = logininfor.getParams();
LambdaQueryWrapper<SysLogininfor> lqw = new LambdaQueryWrapper<SysLogininfor>()
.like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
.eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
.like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(login_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(login_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"));
return PageUtils.buildDataInfo(page(PageUtils.buildPage("info_id","desc"), lqw));
.like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
.eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
.like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"));
return PageUtils.buildDataInfo(page(PageUtils.buildPage("info_id", "desc"), lqw));
}
/**
@@ -123,16 +119,12 @@ public class SysLogininforServiceImpl extends ServicePlusImpl<SysLogininforMappe
public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor) {
Map<String, Object> params = logininfor.getParams();
return list(new LambdaQueryWrapper<SysLogininfor>()
.like(StringUtils.isNotBlank(logininfor.getIpaddr()),SysLogininfor::getIpaddr,logininfor.getIpaddr())
.eq(StringUtils.isNotBlank(logininfor.getStatus()),SysLogininfor::getStatus,logininfor.getStatus())
.like(StringUtils.isNotBlank(logininfor.getUserName()),SysLogininfor::getUserName,logininfor.getUserName())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(login_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(login_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"))
.orderByDesc(SysLogininfor::getInfoId));
.like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
.eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
.like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"))
.orderByDesc(SysLogininfor::getInfoId));
}
/**

View File

@@ -1,15 +1,16 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TreeBuildUtils;
import com.ruoyi.system.domain.SysRoleMenu;
import com.ruoyi.system.domain.vo.MetaVo;
import com.ruoyi.system.domain.vo.RouterVo;
@@ -21,7 +22,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 菜单 业务层处理
@@ -60,11 +60,11 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
// 管理员显示所有菜单信息
if (SysUser.isAdmin(userId)) {
menuList = list(new LambdaQueryWrapper<SysMenu>()
.like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName())
.eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible())
.eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus())
.orderByAsc(SysMenu::getParentId)
.orderByAsc(SysMenu::getOrderNum));
.like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName())
.eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible())
.eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus())
.orderByAsc(SysMenu::getParentId)
.orderByAsc(SysMenu::getOrderNum));
} else {
menu.getParams().put("userId", userId);
menuList = baseMapper.selectMenuListByUserId(menu);
@@ -114,7 +114,7 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
* @return 选中菜单列表
*/
@Override
public List<Integer> selectMenuListByRoleId(Long roleId) {
public List<Long> selectMenuListByRoleId(Long roleId) {
SysRole role = roleMapper.selectById(roleId);
return baseMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
}
@@ -170,32 +170,6 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
return routers;
}
/**
* 构建前端所需要树结构
*
* @param menus 菜单列表
* @return 树结构列表
*/
@Override
public List<SysMenu> buildMenuTree(List<SysMenu> menus) {
List<SysMenu> returnList = new ArrayList<SysMenu>();
List<Long> tempList = new ArrayList<Long>();
for (SysMenu dept : menus) {
tempList.add(dept.getMenuId());
}
for (SysMenu menu : menus) {
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(menu.getParentId())) {
recursionFn(menus, menu);
returnList.add(menu);
}
}
if (returnList.isEmpty()) {
returnList = menus;
}
return returnList;
}
/**
* 构建前端所需要下拉树结构
*
@@ -203,9 +177,12 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
* @return 下拉树结构列表
*/
@Override
public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
List<SysMenu> menuTrees = buildMenuTree(menus);
return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
public List<Tree<Long>> buildMenuTreeSelect(List<SysMenu> menus) {
return TreeBuildUtils.build(menus, (menu, tree) ->
tree.setId(menu.getMenuId())
.setParentId(menu.getParentId())
.setName(menu.getMenuName())
.setWeight(menu.getOrderNum()));
}
/**
@@ -285,11 +262,11 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
@Override
public String checkMenuNameUnique(SysMenu menu) {
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
SysMenu info = getOne(new LambdaQueryWrapper<SysMenu>()
.eq(SysMenu::getMenuName, menu.getMenuName())
.eq(SysMenu::getParentId, menu.getParentId())
.last("limit 1"));
if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) {
long count = count(new LambdaQueryWrapper<SysMenu>()
.eq(SysMenu::getMenuName, menu.getMenuName())
.eq(SysMenu::getParentId, menu.getParentId())
.ne(SysMenu::getMenuId, menuId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
@@ -324,7 +301,7 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
}
// 非外链并且是一级目录(类型为目录)
if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
&& UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
&& UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
routerPath = "/" + menu.getPath();
}
// 非外链并且是一级目录(类型为菜单)
@@ -360,7 +337,7 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
*/
public boolean isMenuFrame(SysMenu menu) {
return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
}
/**

View File

@@ -47,23 +47,19 @@ public class SysOperLogServiceImpl extends ServicePlusImpl<SysOperLogMapper, Sys
public TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog) {
Map<String, Object> params = operLog.getParams();
LambdaQueryWrapper<SysOperLog> lqw = new LambdaQueryWrapper<SysOperLog>()
.like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
.eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
SysOperLog::getBusinessType, operLog.getBusinessType())
.func(f -> {
if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
}
})
.eq(operLog.getStatus() != null,
SysOperLog::getStatus, operLog.getStatus())
.like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(oper_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(oper_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"));
.like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
.eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
SysOperLog::getBusinessType, operLog.getBusinessType())
.func(f -> {
if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
}
})
.eq(operLog.getStatus() != null,
SysOperLog::getStatus, operLog.getStatus())
.like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"));
return PageUtils.buildDataInfo(page(PageUtils.buildPage("oper_id", "desc"), lqw));
}
@@ -88,24 +84,20 @@ public class SysOperLogServiceImpl extends ServicePlusImpl<SysOperLogMapper, Sys
public List<SysOperLog> selectOperLogList(SysOperLog operLog) {
Map<String, Object> params = operLog.getParams();
return list(new LambdaQueryWrapper<SysOperLog>()
.like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
.eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
SysOperLog::getBusinessType, operLog.getBusinessType())
.func(f -> {
if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
}
})
.eq(operLog.getStatus() != null && operLog.getStatus() > 0,
SysOperLog::getStatus, operLog.getStatus())
.like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
.apply(StringUtils.isNotEmpty(params.get("beginTime")),
"date_format(oper_time,'%y%m%d') >= date_format({0},'%y%m%d')",
params.get("beginTime"))
.apply(StringUtils.isNotEmpty(params.get("endTime")),
"date_format(oper_time,'%y%m%d') <= date_format({0},'%y%m%d')",
params.get("endTime"))
.orderByDesc(SysOperLog::getOperId));
.like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
.eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
SysOperLog::getBusinessType, operLog.getBusinessType())
.func(f -> {
if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
}
})
.eq(operLog.getStatus() != null && operLog.getStatus() > 0,
SysOperLog::getStatus, operLog.getStatus())
.like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
.between(params.get("beginTime") != null && params.get("endTime") != null,
SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"))
.orderByDesc(SysOperLog::getOperId));
}
/**

View File

@@ -15,7 +15,8 @@ import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.constant.CloudConstant;
import com.ruoyi.oss.constant.OssConstant;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.system.domain.SysOssConfig;
import com.ruoyi.system.domain.bo.SysOssConfigBo;
import com.ruoyi.system.domain.vo.SysOssConfigVo;
@@ -27,7 +28,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.List;
@@ -46,16 +46,19 @@ public class SysOssConfigServiceImpl extends ServicePlusImpl<SysOssConfigMapper,
/**
* 项目启动时,初始化参数到缓存,加载配置类
*/
@PostConstruct
@Override
public void init() {
List<SysOssConfig> list = list();
// 加载OSS初始化配置
for (SysOssConfig config : list) {
String configKey = config.getConfigKey();
if ("0".equals(config.getStatus())) {
RedisUtils.setCacheObject(CloudConstant.CACHE_CONFIG_KEY, configKey);
RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, configKey);
}
setConfigCache(true, config);
}
// 初始化OSS工厂
OssFactory.init();
}
@Override
@@ -110,7 +113,7 @@ public class SysOssConfigServiceImpl extends ServicePlusImpl<SysOssConfigMapper,
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
if (CollUtil.containsAny(ids, CloudConstant.SYSTEM_DATA_IDS)) {
if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) {
throw new ServiceException("系统内置, 不可删除!");
}
}
@@ -153,7 +156,7 @@ public class SysOssConfigServiceImpl extends ServicePlusImpl<SysOssConfigMapper,
.set(SysOssConfig::getStatus, "1"));
row += baseMapper.updateById(sysOssConfig);
if (row > 0) {
RedisUtils.setCacheObject(CloudConstant.CACHE_CONFIG_KEY, sysOssConfig.getConfigKey());
RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, sysOssConfig.getConfigKey());
}
return row;
}
@@ -165,7 +168,7 @@ public class SysOssConfigServiceImpl extends ServicePlusImpl<SysOssConfigMapper,
* @return 缓存键key
*/
private String getCacheKey(String configKey) {
return CloudConstant.SYS_OSS_KEY + configKey;
return OssConstant.SYS_OSS_KEY + configKey;
}
/**
@@ -180,7 +183,7 @@ public class SysOssConfigServiceImpl extends ServicePlusImpl<SysOssConfigMapper,
RedisUtils.setCacheObject(
getCacheKey(config.getConfigKey()),
JsonUtils.toJsonString(config));
RedisUtils.publish(CloudConstant.CACHE_CONFIG_KEY, config.getConfigKey(), msg -> {
RedisUtils.publish(OssConstant.CACHE_CONFIG_KEY, config.getConfigKey(), msg -> {
log.info("发布刷新OSS配置 => " + msg);
});
}

View File

@@ -10,7 +10,7 @@ import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.oss.service.ICloudStorageStrategy;
import com.ruoyi.oss.service.IOssStrategy;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
@@ -56,7 +56,7 @@ public class SysOssServiceImpl extends ServicePlusImpl<SysOssMapper, SysOss, Sys
public SysOss upload(MultipartFile file) {
String originalfileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
ICloudStorageStrategy storage = OssFactory.instance();
IOssStrategy storage = OssFactory.instance();
UploadResult uploadResult;
try {
uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
@@ -81,7 +81,7 @@ public class SysOssServiceImpl extends ServicePlusImpl<SysOssMapper, SysOss, Sys
}
List<SysOss> list = listByIds(ids);
for (SysOss sysOss : list) {
ICloudStorageStrategy storage = OssFactory.instance(sysOss.getService());
IOssStrategy storage = OssFactory.instance(sysOss.getService());
storage.delete(sysOss.getUrl());
}
return removeByIds(ids);

View File

@@ -93,9 +93,10 @@ public class SysPostServiceImpl extends ServicePlusImpl<SysPostMapper, SysPost,
@Override
public String checkPostNameUnique(SysPost post) {
Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
SysPost info = getOne(new LambdaQueryWrapper<SysPost>()
.eq(SysPost::getPostName, post.getPostName()).last("limit 1"));
if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) {
long count = count(new LambdaQueryWrapper<SysPost>()
.eq(SysPost::getPostName, post.getPostName())
.ne(SysPost::getPostId, postId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
@@ -110,9 +111,10 @@ public class SysPostServiceImpl extends ServicePlusImpl<SysPostMapper, SysPost,
@Override
public String checkPostCodeUnique(SysPost post) {
Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
SysPost info = getOne(new LambdaQueryWrapper<SysPost>()
.eq(SysPost::getPostCode, post.getPostCode()).last("limit 1"));
if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) {
long count = count(new LambdaQueryWrapper<SysPost>()
.eq(SysPost::getPostCode, post.getPostCode())
.ne(SysPost::getPostId, postId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;

View File

@@ -141,9 +141,10 @@ public class SysRoleServiceImpl extends ServicePlusImpl<SysRoleMapper, SysRole,
@Override
public String checkRoleNameUnique(SysRole role) {
Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
SysRole info = getOne(new LambdaQueryWrapper<SysRole>()
.eq(SysRole::getRoleName, role.getRoleName()).last("limit 1"));
if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) {
long count = count(new LambdaQueryWrapper<SysRole>()
.eq(SysRole::getRoleName, role.getRoleName())
.ne(SysRole::getRoleId, roleId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
@@ -158,9 +159,10 @@ public class SysRoleServiceImpl extends ServicePlusImpl<SysRoleMapper, SysRole,
@Override
public String checkRoleKeyUnique(SysRole role) {
Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
SysRole info = getOne(new LambdaQueryWrapper<SysRole>()
.eq(SysRole::getRoleKey, role.getRoleKey()).last("limit 1"));
if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) {
long count = count(new LambdaQueryWrapper<SysRole>()
.eq(SysRole::getRoleKey, role.getRoleKey())
.ne(SysRole::getRoleId, roleId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;

View File

@@ -1,9 +1,12 @@
package com.ruoyi.system.service.impl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
@@ -14,6 +17,9 @@ import org.springframework.stereotype.Service;
@Service
public class SysUserOnlineServiceImpl implements ISysUserOnlineService {
@Autowired
private ISysUserService userService;
/**
* 通过登录地址查询信息
*
@@ -68,9 +74,10 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService {
*/
@Override
public SysUserOnline loginUserToUserOnline(LoginUser user) {
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser())) {
if (StringUtils.isNull(user)) {
return null;
}
SysUser sysUser = userService.selectUserById(user.getUserId());
SysUserOnline sysUserOnline = new SysUserOnline();
sysUserOnline.setTokenId(user.getToken());
sysUserOnline.setUserName(user.getUsername());
@@ -79,8 +86,8 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService {
sysUserOnline.setBrowser(user.getBrowser());
sysUserOnline.setOs(user.getOs());
sysUserOnline.setLoginTime(user.getLoginTime());
if (StringUtils.isNotNull(user.getUser().getDept())) {
sysUserOnline.setDeptName(user.getUser().getDept().getDeptName());
if (StringUtils.isNotNull(sysUser.getDept())) {
sysUserOnline.setDeptName(sysUser.getDept().getDeptName());
}
return sysUserOnline;
}

View File

@@ -8,6 +8,7 @@ import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.UserService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
@@ -35,7 +36,7 @@ import java.util.List;
*/
@Slf4j
@Service
public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser, SysUser> implements ISysUserService {
public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser, SysUser> implements ISysUserService, UserService {
@Autowired
private SysRoleMapper roleMapper;
@@ -162,7 +163,7 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
*/
@Override
public String checkUserNameUnique(String userName) {
long count = count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, userName).last("limit 1"));
long count = count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, userName));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
@@ -178,10 +179,11 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
@Override
public String checkPhoneUnique(SysUser user) {
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
SysUser info = getOne(new LambdaQueryWrapper<SysUser>()
long count = count(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserId, SysUser::getPhonenumber)
.eq(SysUser::getPhonenumber, user.getPhonenumber()).last("limit 1"));
if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
.eq(SysUser::getPhonenumber, user.getPhonenumber())
.ne(SysUser::getUserId, userId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;
@@ -196,10 +198,11 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
@Override
public String checkEmailUnique(SysUser user) {
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
SysUser info = getOne(new LambdaQueryWrapper<SysUser>()
long count = count(new LambdaQueryWrapper<SysUser>()
.select(SysUser::getUserId, SysUser::getEmail)
.eq(SysUser::getEmail, user.getEmail()).last("limit 1"));
if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
.eq(SysUser::getEmail, user.getEmail())
.ne(SysUser::getUserId, userId));
if (count > 0) {
return UserConstants.NOT_UNIQUE;
}
return UserConstants.UNIQUE;

View File

@@ -47,6 +47,6 @@ public class UserDetailsServiceImpl implements UserDetailsService {
}
public UserDetails createLoginUser(SysUser user) {
return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUserName(), user.getPassword(), permissionService.getMenuPermission(user));
}
}

View File

@@ -43,7 +43,7 @@ public class SysLogininforController extends BaseController {
@ApiOperation("导出系统访问记录列表")
@Log(title = "登录日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysLogininfor logininfor, HttpServletResponse response) {
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
ExcelUtil.exportExcel(list, "登录日志", SysLogininfor.class, response);

View File

@@ -43,7 +43,7 @@ public class SysOperlogController extends BaseController {
@ApiOperation("导出操作日志记录列表")
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysOperLog operLog, HttpServletResponse response) {
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
ExcelUtil.exportExcel(list, "操作日志", SysOperLog.class, response);

View File

@@ -53,7 +53,7 @@ public class SysUserOnlineController extends BaseController {
if (StringUtils.equals(ipaddr, user.getIpaddr())) {
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
}
} else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) {
} else if (StringUtils.isNotEmpty(userName)) {
if (StringUtils.equals(userName, user.getUsername())) {
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
}

View File

@@ -1,7 +1,6 @@
package com.ruoyi.web.controller.system;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -12,6 +11,7 @@ import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -48,7 +48,7 @@ public class SysConfigController extends BaseController {
@ApiOperation("导出参数配置列表")
@Log(title = "参数管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:config:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysConfig config, HttpServletResponse response) {
List<SysConfig> list = configService.selectConfigList(config);
ExcelUtil.exportExcel(list, "参数数据", SysConfig.class, response);
@@ -60,7 +60,7 @@ public class SysConfigController extends BaseController {
@ApiOperation("根据参数编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:config:query')")
@GetMapping(value = "/{configId}")
public AjaxResult<SysConfig> getInfo(@PathVariable Long configId) {
public AjaxResult<SysConfig> getInfo(@ApiParam("参数ID") @PathVariable Long configId) {
return AjaxResult.success(configService.selectConfigById(configId));
}
@@ -69,7 +69,7 @@ public class SysConfigController extends BaseController {
*/
@ApiOperation("根据参数键名查询参数值")
@GetMapping(value = "/configKey/{configKey}")
public AjaxResult<Void> getConfigKey(@PathVariable String configKey) {
public AjaxResult<Void> getConfigKey(@ApiParam("参数Key") @PathVariable String configKey) {
return AjaxResult.success(configService.selectConfigByKey(configKey));
}
@@ -80,7 +80,6 @@ public class SysConfigController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:config:add')")
@Log(title = "参数管理", businessType = BusinessType.INSERT)
@PostMapping
@RepeatSubmit
public AjaxResult<Void> add(@Validated @RequestBody SysConfig config) {
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
@@ -109,7 +108,7 @@ public class SysConfigController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{configIds}")
public AjaxResult<Void> remove(@PathVariable Long[] configIds) {
public AjaxResult<Void> remove(@ApiParam("参数ID串") @PathVariable Long[] configIds) {
configService.deleteConfigByIds(configIds);
return success();
}

View File

@@ -1,17 +1,18 @@
package com.ruoyi.web.controller.system;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -53,7 +54,7 @@ public class SysDeptController extends BaseController {
@ApiOperation("查询部门列表(排除节点)")
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list/exclude/{deptId}")
public AjaxResult<List<SysDept>> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
public AjaxResult<List<SysDept>> excludeChild(@ApiParam("部门ID") @PathVariable(value = "deptId", required = false) Long deptId) {
List<SysDept> depts = deptService.selectDeptList(new SysDept());
depts.removeIf(d -> d.getDeptId().equals(deptId)
|| ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
@@ -66,7 +67,7 @@ public class SysDeptController extends BaseController {
@ApiOperation("根据部门编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping(value = "/{deptId}")
public AjaxResult<SysDept> getInfo(@PathVariable Long deptId) {
public AjaxResult<SysDept> getInfo(@ApiParam("部门ID") @PathVariable Long deptId) {
deptService.checkDeptDataScope(deptId);
return AjaxResult.success(deptService.selectDeptById(deptId));
}
@@ -76,7 +77,7 @@ public class SysDeptController extends BaseController {
*/
@ApiOperation("获取部门下拉树列表")
@GetMapping("/treeselect")
public AjaxResult<List<TreeSelect>> treeselect(SysDept dept) {
public AjaxResult<List<Tree<Long>>> treeselect(SysDept dept) {
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
}
@@ -86,7 +87,7 @@ public class SysDeptController extends BaseController {
*/
@ApiOperation("加载对应角色部门列表树")
@GetMapping(value = "/roleDeptTreeselect/{roleId}")
public AjaxResult<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
public AjaxResult<Map<String, Object>> roleDeptTreeselect(@ApiParam("角色ID") @PathVariable("roleId") Long roleId) {
List<SysDept> depts = deptService.selectDeptList(new SysDept());
Map<String, Object> ajax = new HashMap<>();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
@@ -134,7 +135,7 @@ public class SysDeptController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:dept:remove')")
@Log(title = "部门管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{deptId}")
public AjaxResult<Void> remove(@PathVariable Long deptId) {
public AjaxResult<Void> remove(@ApiParam("部门ID串") @PathVariable Long deptId) {
if (deptService.hasChildByDeptId(deptId)) {
return AjaxResult.error("存在下级部门,不允许删除");
}

View File

@@ -12,6 +12,7 @@ import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -47,7 +48,7 @@ public class SysDictDataController extends BaseController {
@ApiOperation("导出字典数据列表")
@Log(title = "字典数据", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysDictData dictData, HttpServletResponse response) {
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
ExcelUtil.exportExcel(list, "字典数据", SysDictData.class, response);
@@ -59,7 +60,7 @@ public class SysDictDataController extends BaseController {
@ApiOperation("查询字典数据详细")
@PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictCode}")
public AjaxResult<SysDictData> getInfo(@PathVariable Long dictCode) {
public AjaxResult<SysDictData> getInfo(@ApiParam("字典code") @PathVariable Long dictCode) {
return AjaxResult.success(dictDataService.selectDictDataById(dictCode));
}
@@ -68,7 +69,7 @@ public class SysDictDataController extends BaseController {
*/
@ApiOperation("根据字典类型查询字典数据信息")
@GetMapping(value = "/type/{dictType}")
public AjaxResult<List<SysDictData>> dictType(@PathVariable String dictType) {
public AjaxResult<List<SysDictData>> dictType(@ApiParam("字典类型") @PathVariable String dictType) {
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data)) {
data = new ArrayList<>();
@@ -105,7 +106,7 @@ public class SysDictDataController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictCodes}")
public AjaxResult<Void> remove(@PathVariable Long[] dictCodes) {
public AjaxResult<Void> remove(@ApiParam("字典code串") @PathVariable Long[] dictCodes) {
dictDataService.deleteDictDataByIds(dictCodes);
return success();
}

View File

@@ -11,6 +11,7 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -44,7 +45,7 @@ public class SysDictTypeController extends BaseController {
@ApiOperation("导出字典类型列表")
@Log(title = "字典类型", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysDictType dictType, HttpServletResponse response) {
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
ExcelUtil.exportExcel(list, "字典类型", SysDictType.class, response);
@@ -56,7 +57,7 @@ public class SysDictTypeController extends BaseController {
@ApiOperation("查询字典类型详细")
@PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictId}")
public AjaxResult<SysDictType> getInfo(@PathVariable Long dictId) {
public AjaxResult<SysDictType> getInfo(@ApiParam("字典ID") @PathVariable Long dictId) {
return AjaxResult.success(dictTypeService.selectDictTypeById(dictId));
}
@@ -95,7 +96,7 @@ public class SysDictTypeController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictIds}")
public AjaxResult<Void> remove(@PathVariable Long[] dictIds) {
public AjaxResult<Void> remove(@ApiParam("字典ID串") @PathVariable Long[] dictIds) {
dictTypeService.deleteDictTypeByIds(dictIds);
return success();
}

View File

@@ -8,6 +8,7 @@ import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.vo.RouterVo;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.SysLoginService;
import com.ruoyi.system.service.SysPermissionService;
import io.swagger.annotations.Api;
@@ -31,13 +32,14 @@ import java.util.Set;
* @author Lion Li
*/
@Validated
@Api(value = "数据字典信息控制器", tags = {"数据字典信息管理"})
@Api(value = "登录验证控制器", tags = {"登录验证管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
public class SysLoginController {
private final SysLoginService loginService;
private final ISysMenuService menuService;
private final ISysUserService userService;
private final SysPermissionService permissionService;
/**
@@ -65,7 +67,7 @@ public class SysLoginController {
@ApiOperation("获取用户信息")
@GetMapping("getInfo")
public AjaxResult<Map<String, Object>> getInfo() {
SysUser user = SecurityUtils.getLoginUser().getUser();
SysUser user = userService.selectUserById(SecurityUtils.getUserId());
// 角色集合
Set<String> roles = permissionService.getRolePermission(user);
// 权限集合

View File

@@ -1,16 +1,17 @@
package com.ruoyi.web.controller.system;
import cn.hutool.core.lang.tree.Tree;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -52,7 +53,7 @@ public class SysMenuController extends BaseController {
@ApiOperation("根据菜单编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:menu:query')")
@GetMapping(value = "/{menuId}")
public AjaxResult<SysMenu> getInfo(@PathVariable Long menuId) {
public AjaxResult<SysMenu> getInfo(@ApiParam("菜单ID") @PathVariable Long menuId) {
return AjaxResult.success(menuService.selectMenuById(menuId));
}
@@ -61,7 +62,7 @@ public class SysMenuController extends BaseController {
*/
@ApiOperation("获取菜单下拉树列表")
@GetMapping("/treeselect")
public AjaxResult<List<TreeSelect>> treeselect(SysMenu menu) {
public AjaxResult<List<Tree<Long>>> treeselect(SysMenu menu) {
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
}
@@ -71,7 +72,7 @@ public class SysMenuController extends BaseController {
*/
@ApiOperation("加载对应角色菜单列表树")
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult<Map<String, Object>> roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
public AjaxResult<Map<String, Object>> roleMenuTreeselect(@ApiParam("角色ID") @PathVariable("roleId") Long roleId) {
List<SysMenu> menus = menuService.selectMenuList(getUserId());
Map<String, Object> ajax = new HashMap<>();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
@@ -120,7 +121,7 @@ public class SysMenuController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:menu:remove')")
@Log(title = "菜单管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{menuId}")
public AjaxResult<Void> remove(@PathVariable("menuId") Long menuId) {
public AjaxResult<Void> remove(@ApiParam("菜单ID") @PathVariable("menuId") Long menuId) {
if (menuService.hasChildByMenuId(menuId)) {
return AjaxResult.error("存在子菜单,不允许删除");
}

View File

@@ -9,6 +9,7 @@ import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -45,7 +46,7 @@ public class SysNoticeController extends BaseController {
@ApiOperation("根据通知公告编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:notice:query')")
@GetMapping(value = "/{noticeId}")
public AjaxResult<SysNotice> getInfo(@PathVariable Long noticeId) {
public AjaxResult<SysNotice> getInfo(@ApiParam("公告ID") @PathVariable Long noticeId) {
return AjaxResult.success(noticeService.selectNoticeById(noticeId));
}
@@ -78,7 +79,7 @@ public class SysNoticeController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:notice:remove')")
@Log(title = "通知公告", businessType = BusinessType.DELETE)
@DeleteMapping("/{noticeIds}")
public AjaxResult<Void> remove(@PathVariable Long[] noticeIds) {
public AjaxResult<Void> remove(@ApiParam("公告ID串") @PathVariable Long[] noticeIds) {
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
}
}

View File

@@ -14,6 +14,7 @@ import com.ruoyi.system.domain.vo.SysOssConfigVo;
import com.ruoyi.system.service.ISysOssConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -56,7 +57,8 @@ public class SysOssConfigController extends BaseController {
@ApiOperation("获取对象存储配置详细信息")
@PreAuthorize("@ss.hasPermi('system:oss:query')")
@GetMapping("/{ossConfigId}")
public AjaxResult<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空")
public AjaxResult<SysOssConfigVo> getInfo(@ApiParam("OSS配置ID")
@NotNull(message = "主键不能为空")
@PathVariable("ossConfigId") Integer ossConfigId) {
return AjaxResult.success(iSysOssConfigService.queryById(ossConfigId));
}
@@ -92,7 +94,8 @@ public class SysOssConfigController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:oss:remove')")
@Log(title = "对象存储配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ossConfigIds}")
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
public AjaxResult<Void> remove(@ApiParam("OSS配置ID串")
@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ossConfigIds) {
return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0);
}

View File

@@ -16,17 +16,14 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.oss.constant.CloudConstant;
import com.ruoyi.oss.constant.OssConstant;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysOssService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
@@ -37,6 +34,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
@@ -72,7 +70,7 @@ public class SysOssController extends BaseController {
*/
@ApiOperation("上传OSS对象存储")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
@ApiImplicitParam(name = "file", value = "文件", dataTypeClass = File.class, required = true),
})
@PreAuthorize("@ss.hasPermi('system:oss:upload')")
@Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
@@ -92,7 +90,7 @@ public class SysOssController extends BaseController {
@ApiOperation("下载OSS对象存储")
@PreAuthorize("@ss.hasPermi('system:oss:download')")
@GetMapping("/download/{ossId}")
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
public void download(@ApiParam("OSS对象ID") @PathVariable Long ossId, HttpServletResponse response) throws IOException {
SysOss sysOss = iSysOssService.getById(ossId);
if (ObjectUtil.isNull(sysOss)) {
throw new ServiceException("文件数据不存在!");
@@ -120,7 +118,8 @@ public class SysOssController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:oss:remove')")
@Log(title = "OSS对象存储", businessType = BusinessType.DELETE)
@DeleteMapping("/{ossIds}")
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
public AjaxResult<Void> remove(@ApiParam("OSS对象ID串")
@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ossIds) {
return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0);
}
@@ -135,7 +134,7 @@ public class SysOssController extends BaseController {
public AjaxResult<Void> changePreviewListResource(@RequestBody String body) {
Map<String, Boolean> map = JsonUtils.parseMap(body);
SysConfig config = iSysConfigService.getOne(new LambdaQueryWrapper<SysConfig>()
.eq(SysConfig::getConfigKey, CloudConstant.PEREVIEW_LIST_RESOURCE_KEY));
.eq(SysConfig::getConfigKey, OssConstant.PEREVIEW_LIST_RESOURCE_KEY));
config.setConfigValue(map.get("previewListResource").toString());
return toAjax(iSysConfigService.updateConfig(config));
}

View File

@@ -11,6 +11,7 @@ import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.service.ISysPostService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -47,7 +48,7 @@ public class SysPostController extends BaseController {
@ApiOperation("导出岗位列表")
@Log(title = "岗位管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:post:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysPost post, HttpServletResponse response) {
List<SysPost> list = postService.selectPostList(post);
ExcelUtil.exportExcel(list, "岗位数据", SysPost.class, response);
@@ -59,7 +60,7 @@ public class SysPostController extends BaseController {
@ApiOperation("根据岗位编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:post:query')")
@GetMapping(value = "/{postId}")
public AjaxResult<SysPost> getInfo(@PathVariable Long postId) {
public AjaxResult<SysPost> getInfo(@ApiParam("岗位ID") @PathVariable Long postId) {
return AjaxResult.success(postService.selectPostById(postId));
}
@@ -102,7 +103,7 @@ public class SysPostController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:post:remove')")
@Log(title = "岗位管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{postIds}")
public AjaxResult<Void> remove(@PathVariable Long[] postIds) {
public AjaxResult<Void> remove(@ApiParam("岗位ID串") @PathVariable Long[] postIds) {
return toAjax(postService.deletePostByIds(postIds));
}

View File

@@ -20,6 +20,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@@ -46,7 +47,7 @@ public class SysProfileController extends BaseController {
@GetMapping
public AjaxResult<Map<String, Object>> profile() {
LoginUser loginUser = getLoginUser();
SysUser user = loginUser.getUser();
SysUser user = userService.selectUserById(loginUser.getUserId());
Map<String, Object> ajax = new HashMap<>();
ajax.put("user", user);
ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
@@ -70,16 +71,11 @@ public class SysProfileController extends BaseController {
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
LoginUser loginUser = getLoginUser();
SysUser sysUser = loginUser.getUser();
SysUser sysUser = userService.selectUserById(loginUser.getUserId());
user.setUserId(sysUser.getUserId());
user.setUserName(null);
user.setPassword(null);
if (userService.updateUserProfile(user) > 0) {
// 更新缓存用户信息
sysUser.setNickName(user.getNickName());
sysUser.setPhonenumber(user.getPhonenumber());
sysUser.setEmail(user.getEmail());
sysUser.setSex(user.getSex());
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
}
return AjaxResult.error("修改个人信息异常,请联系管理员");
@@ -89,6 +85,10 @@ public class SysProfileController extends BaseController {
* 重置密码
*/
@ApiOperation("重置密码")
@ApiImplicitParams({
@ApiImplicitParam(name = "oldPassword", value = "旧密码", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "newPassword", value = "新密码", paramType = "query", dataTypeClass = String.class)
})
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd")
public AjaxResult<Void> updatePwd(String oldPassword, String newPassword) {
@@ -103,7 +103,7 @@ public class SysProfileController extends BaseController {
}
if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {
// 更新缓存用户密码
loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
loginUser.setPassword(SecurityUtils.encryptPassword(newPassword));
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
}
@@ -115,7 +115,7 @@ public class SysProfileController extends BaseController {
*/
@ApiOperation("头像上传")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "用户头像", dataType = "java.io.File", required = true),
@ApiImplicitParam(name = "avatarfile", value = "用户头像", dataTypeClass = File.class, required = true),
})
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
@PostMapping("/avatar")
@@ -127,9 +127,6 @@ public class SysProfileController extends BaseController {
String avatar = oss.getUrl();
if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) {
ajax.put("imgUrl", avatar);
// 更新缓存用户头像
loginUser.getUser().setAvatar(avatar);
tokenService.setLoginUser(loginUser);
return AjaxResult.success(ajax);
}
}

View File

@@ -16,8 +16,7 @@ import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.SysPermissionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -54,7 +53,7 @@ public class SysRoleController extends BaseController {
@ApiOperation("导出角色信息列表")
@Log(title = "角色管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:role:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysRole role, HttpServletResponse response) {
List<SysRole> list = roleService.selectRoleList(role);
ExcelUtil.exportExcel(list, "角色数据", SysRole.class, response);
@@ -66,7 +65,7 @@ public class SysRoleController extends BaseController {
@ApiOperation("根据角色编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/{roleId}")
public AjaxResult<SysRole> getInfo(@PathVariable Long roleId) {
public AjaxResult<SysRole> getInfo(@ApiParam("角色ID") @PathVariable Long roleId) {
roleService.checkRoleDataScope(roleId);
return AjaxResult.success(roleService.selectRoleById(roleId));
}
@@ -106,9 +105,9 @@ public class SysRoleController extends BaseController {
if (roleService.updateRole(role) > 0) {
// 更新缓存用户权限
LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) {
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
SysUser sysUser = userService.selectUserById(loginUser.getUserId());
if (StringUtils.isNotNull(sysUser) && !sysUser.isAdmin()) {
loginUser.setPermissions(permissionService.getMenuPermission(sysUser));
tokenService.setLoginUser(loginUser);
}
return AjaxResult.success();
@@ -147,7 +146,7 @@ public class SysRoleController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:role:remove')")
@Log(title = "角色管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{roleIds}")
public AjaxResult<Void> remove(@PathVariable Long[] roleIds) {
public AjaxResult<Void> remove(@ApiParam("岗位ID串") @PathVariable Long[] roleIds) {
return toAjax(roleService.deleteRoleByIds(roleIds));
}
@@ -196,6 +195,10 @@ public class SysRoleController extends BaseController {
* 批量取消授权用户
*/
@ApiOperation("批量取消授权用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "roleId", value = "角色ID", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "userIds", value = "用户ID串", paramType = "query", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
@@ -207,6 +210,10 @@ public class SysRoleController extends BaseController {
* 批量选择用户授权
*/
@ApiOperation("批量选择用户授权")
@ApiImplicitParams({
@ApiImplicitParam(name = "roleId", value = "角色ID", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "userIds", value = "用户ID串", paramType = "query", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/selectAll")

View File

@@ -12,18 +12,17 @@ import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.vo.SysUserExportVo;
import com.ruoyi.system.domain.vo.SysUserImportVo;
import com.ruoyi.system.listener.SysUserImportListener;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -67,7 +66,7 @@ public class SysUserController extends BaseController {
@ApiOperation("导出用户列表")
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:user:export')")
@GetMapping("/export")
@PostMapping("/export")
public void export(SysUser user, HttpServletResponse response) {
List<SysUser> list = userService.selectUserList(user);
List<SysUserExportVo> listVo = BeanUtil.copyToList(list, SysUserExportVo.class);
@@ -90,15 +89,12 @@ public class SysUserController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:user:import')")
@PostMapping("/importData")
public AjaxResult<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
List<SysUserImportVo> userListVo = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class);
List<SysUser> userList = BeanUtil.copyToList(userListVo, SysUser.class);
String operName = getUsername();
String message = userService.importUser(userList, updateSupport, operName);
return AjaxResult.success(message);
ExcelResult<SysUserImportVo> result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport));
return AjaxResult.success(result.getAnalysis());
}
@ApiOperation("下载导入模板")
@GetMapping("/importTemplate")
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) {
ExcelUtil.exportExcel(new ArrayList<>(), "用户数据", SysUserImportVo.class, response);
}
@@ -109,7 +105,7 @@ public class SysUserController extends BaseController {
@ApiOperation("根据用户编号获取详细信息")
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping(value = {"/", "/{userId}"})
public AjaxResult<Map<String, Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId) {
public AjaxResult<Map<String, Object>> getInfo(@ApiParam("用户ID") @PathVariable(value = "userId", required = false) Long userId) {
userService.checkUserDataScope(userId);
Map<String, Object> ajax = new HashMap<>();
List<SysRole> roles = roleService.selectRoleAll();
@@ -170,7 +166,7 @@ public class SysUserController extends BaseController {
@PreAuthorize("@ss.hasPermi('system:user:remove')")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{userIds}")
public AjaxResult<Void> remove(@PathVariable Long[] userIds) {
public AjaxResult<Void> remove(@ApiParam("角色ID串") @PathVariable Long[] userIds) {
if (ArrayUtil.contains(userIds, getUserId())) {
return error("当前用户不能删除");
}
@@ -208,7 +204,7 @@ public class SysUserController extends BaseController {
@ApiOperation("根据用户编号获取授权角色")
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult<Map<String, Object>> authRole(@PathVariable("userId") Long userId) {
public AjaxResult<Map<String, Object>> authRole(@ApiParam("用户ID") @PathVariable("userId") Long userId) {
SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
Map<String, Object> ajax = new HashMap<>();
@@ -221,6 +217,10 @@ public class SysUserController extends BaseController {
* 用户授权角色
*/
@ApiOperation("用户授权角色")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户Id", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "roleIds", value = "角色ID串", paramType = "query", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")

View File

@@ -1,3 +1,10 @@
--- # 配置临时路径存储
spring:
servlet:
multipart:
# 临时文件存储位置 避免临时文件被系统清理报错
location: /ruoyi/server/temp
--- # 监控配置
spring:
boot:

View File

@@ -10,6 +10,8 @@ ruoyi:
demoEnabled: true
# 获取ip地址开关
addressEnabled: true
# 缓存懒加载
cacheLazy: true
captcha:
# 页面 <参数设置> 可开启关闭 验证码校验
@@ -214,6 +216,22 @@ swagger:
- name: 3.代码生成模块
basePackage: com.ruoyi.generator
knife4j:
# 是否开启Knife4j增强模式
enable: true
# 是否开启生产环境保护策略
production: @knife4j.production@
# 前端Ui的个性化配置属性
setting:
# 默认语言
language: zh-CN
# 是否显示Footer
enableFooter: false
# 是否开启动态参数调试功能
enableDynamicParameter: true
# 是否在每个Debug调试栏后显示刷新变量按钮
enableReloadCacheParameter: true
# 防止XSS攻击
xss:
# 过滤开关
@@ -242,22 +260,6 @@ thread-pool:
# ABORT_POLICY 中止
rejectedExecutionHandler: CALLER_RUNS_POLICY
# feign 相关配置
feign:
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
# 例如 com.**.**.feign
package: com.ruoyi.**.feign
# 开启压缩
compression:
request:
enabled: true
response:
enabled: true
okhttp:
enabled: true
circuitbreaker:
enabled: true
--- # redisson 缓存配置
redisson:
cacheGroup:
@@ -293,34 +295,3 @@ management:
endpoint:
logfile:
external-file: ./logs/sys-console.log
--- # 定时任务配置
spring:
quartz:
scheduler-name: RuoyiScheduler
startup-delay: 1s
overwrite-existing-jobs: true
auto-startup: true
job-store-type: jdbc
properties:
org:
quartz:
# Scheduler 相关配置
scheduler:
instanceName: RuoyiScheduler
instanceId: AUTO
# 线程池相关配置
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 20
threadPriority: 5
# JobStore 集群配置
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
isClustered: true
clusterCheckinInterval: 15000
txIsolationLevelSerializable: true
misfireThreshold: 60000
tablePrefix: QRTZ_
# sqlserver 启用
# selectWithLockSQL: SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?

View File

@@ -31,7 +31,7 @@
<level>INFO</level>
</filter>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
@@ -54,7 +54,7 @@
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
@@ -76,21 +76,7 @@
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
@@ -99,16 +85,12 @@
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
<appender-ref ref="file_console" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>
</configuration>

View File

@@ -117,7 +117,7 @@
order by m.parent_id, m.order_num
</select>
<select id="selectMenuListByRoleId" resultType="Integer">
<select id="selectMenuListByRoleId" resultType="Long">
select m.menu_id
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
@@ -147,4 +147,4 @@
and ur.user_id = #{userId}
</select>
</mapper>
</mapper>

Some files were not shown because too many files have changed in this diff Show More