!86 同步dev分支

Merge pull request !86 from 疯狂的狮子Li/dev
This commit is contained in:
疯狂的狮子Li 2021-09-07 05:50:21 +00:00 committed by Gitee
commit c2efaa5c3c
157 changed files with 3744 additions and 882 deletions

View File

@ -10,9 +10,6 @@ end_of_line = lf
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[*.java]
indent_style = tab
[*.{json,yml}] [*.{json,yml}]
indent_size = 2 indent_size = 2

View File

@ -4,7 +4,7 @@
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
<br> <br>
[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-3.0.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) [![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-3.1.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.5-blue.svg)]() [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.5-blue.svg)]()
[![JDK-8+](https://img.shields.io/badge/JDK-8+-green.svg)]() [![JDK-8+](https://img.shields.io/badge/JDK-8+-green.svg)]()
[![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]() [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]()

View File

@ -22,11 +22,16 @@ port(){
##放置挂载文件 ##放置挂载文件
mount(){ mount(){
#挂载配置文件 #挂载 nginx 配置文件
if test ! -f "/docker/nginx/conf/nginx.conf" ;then if test ! -f "/docker/nginx/conf/nginx.conf" ;then
mkdir -p /docker/nginx/conf mkdir -p /docker/nginx/conf
cp nginx/nginx.conf /docker/nginx/conf/nginx.conf cp nginx/nginx.conf /docker/nginx/conf/nginx.conf
fi fi
#挂载 redis 配置文件
if test ! -f "/docker/redis/conf/redis.conf" ;then
mkdir -p /docker/redis/conf
cp redis/redis.conf /docker/redis/conf/redis.conf
fi
} }
#启动基础模块 #启动基础模块

View File

@ -65,10 +65,10 @@ services:
TZ: Asia/Shanghai TZ: Asia/Shanghai
volumes: volumes:
# 配置文件 # 配置文件
- /docker/redis/conf/redis.conf:/redis.conf:rw - /docker/redis/conf:/redis/config:rw
# 数据文件 # 数据文件
- /docker/redis/data:/data:rw - /docker/redis/data:/redis/data:rw
command: "redis-server --appendonly yes" command: "redis-server /redis/config/redis.conf --appendonly yes"
privileged: true privileged: true
restart: always restart: always
networks: networks:
@ -77,7 +77,7 @@ services:
minio: minio:
image: minio/minio:RELEASE.2021-07-08T01-15-01Z image: minio/minio:RELEASE.2021-07-08T01-15-01Z
hostname: "minio" container_name: minio
ports: ports:
# api 端口 # api 端口
- 9000:9000 - 9000:9000
@ -103,14 +103,14 @@ services:
ipv4_address: 172.30.0.54 ipv4_address: 172.30.0.54
ruoyi-server1: ruoyi-server1:
image: "ruoyi/ruoyi-server:3.0.0" image: "ruoyi/ruoyi-server:3.1.0"
container_name: ruoyi-server1
environment: environment:
# 时区上海 # 时区上海
TZ: Asia/Shanghai TZ: Asia/Shanghai
volumes: volumes:
# 配置文件 # 配置文件
- /docker/server1/logs/:/ruoyi/server/logs/ - /docker/server1/logs/:/ruoyi/server/logs/
- /docker/ruoyi/uploadPath/:/ruoyi/server/ruoyi/uploadPath/
privileged: true privileged: true
restart: always restart: always
networks: networks:
@ -118,14 +118,14 @@ services:
ipv4_address: 172.30.0.60 ipv4_address: 172.30.0.60
ruoyi-server2: ruoyi-server2:
image: "ruoyi/ruoyi-server:3.0.0" image: "ruoyi/ruoyi-server:3.1.0"
container_name: ruoyi-server2
environment: environment:
# 时区上海 # 时区上海
TZ: Asia/Shanghai TZ: Asia/Shanghai
volumes: volumes:
# 配置文件 # 配置文件
- /docker/server2/logs/:/ruoyi/server/logs/ - /docker/server2/logs/:/ruoyi/server/logs/
- /docker/ruoyi/uploadPath/:/ruoyi/server/ruoyi/uploadPath/
privileged: true privileged: true
restart: always restart: always
networks: networks:
@ -133,7 +133,8 @@ services:
ipv4_address: 172.30.0.61 ipv4_address: 172.30.0.61
ruoyi-monitor-admin: ruoyi-monitor-admin:
image: "ruoyi/ruoyi-monitor-admin:3.0.0" image: "ruoyi/ruoyi-monitor-admin:3.1.0"
container_name: ruoyi-monitor-admin
environment: environment:
# 时区上海 # 时区上海
TZ: Asia/Shanghai TZ: Asia/Shanghai

View File

@ -22,6 +22,7 @@ http {
access_log /var/log/nginx/access.log main; access_log /var/log/nginx/access.log main;
upstream server { upstream server {
ip_hash;
server 172.30.0.60:8080; server 172.30.0.60:8080;
server 172.30.0.61:8080; server 172.30.0.61:8080;
} }

2
docker/redis/redis.conf Normal file
View File

@ -0,0 +1,2 @@
# redis 密码
# requirepass 123456

24
pom.xml
View File

@ -6,41 +6,41 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<name>RuoYi-Vue-Plus</name> <name>RuoYi-Vue-Plus</name>
<url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url> <url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
<description>RuoYi-Vue-Plus后台管理系统</description> <description>RuoYi-Vue-Plus后台管理系统</description>
<properties> <properties>
<ruoyi-vue-plus.version>3.0.0</ruoyi-vue-plus.version> <ruoyi-vue-plus.version>3.1.0</ruoyi-vue-plus.version>
<spring-boot.version>2.5.3</spring-boot.version> <spring-boot.version>2.5.4</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<druid.version>1.2.6</druid.version> <druid.version>1.2.6</druid.version>
<knife4j.version>3.0.3</knife4j.version> <knife4j.version>3.0.3</knife4j.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<easyexcel.version>2.2.10</easyexcel.version> <easyexcel.version>2.2.10</easyexcel.version>
<velocity.version>1.7</velocity.version> <velocity.version>1.7</velocity.version>
<jwt.version>0.9.1</jwt.version> <jwt.version>0.9.1</jwt.version>
<mybatis-plus.version>3.4.3</mybatis-plus.version> <mybatis-plus.version>3.4.3.3</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version> <p6spy.version>3.9.1</p6spy.version>
<hutool.version>5.7.7</hutool.version> <hutool.version>5.7.11</hutool.version>
<feign.version>3.0.3</feign.version> <feign.version>3.0.3</feign.version>
<feign-okhttp.version>11.2</feign-okhttp.version> <feign-okhttp.version>11.6</feign-okhttp.version>
<okhttp.version>4.9.1</okhttp.version> <okhttp.version>4.9.1</okhttp.version>
<spring-boot-admin.version>2.5.0</spring-boot-admin.version> <spring-boot-admin.version>2.5.1</spring-boot-admin.version>
<redisson.version>3.16.1</redisson.version> <redisson.version>3.16.2</redisson.version>
<lock4j.version>2.2.1</lock4j.version> <lock4j.version>2.2.1</lock4j.version>
<dynamic-ds.version>3.4.1</dynamic-ds.version> <dynamic-ds.version>3.4.1</dynamic-ds.version>
<!-- OSS 配置 --> <!-- OSS 配置 -->
<qiniu.version>7.8.0</qiniu.version> <qiniu.version>7.8.0</qiniu.version>
<aliyun.oss.version>3.13.0</aliyun.oss.version> <aliyun.oss.version>3.13.1</aliyun.oss.version>
<qcloud.cos.version>5.6.47</qcloud.cos.version> <qcloud.cos.version>5.6.51</qcloud.cos.version>
<minio.version>8.2.0</minio.version> <minio.version>8.3.0</minio.version>
<!-- docker 配置 --> <!-- docker 配置 -->
<docker.registry.url>localhost</docker.registry.url> <docker.registry.url>localhost</docker.registry.url>

View File

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

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -1,25 +1,22 @@
package com.ruoyi.web.controller.common; package com.ruoyi.web.controller.common;
import cn.hutool.captcha.AbstractCaptcha; import cn.hutool.captcha.AbstractCaptcha;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.captcha.generator.CodeGenerator; import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.enums.CaptchaType;
import com.ruoyi.framework.captcha.UnsignedMathGenerator; import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.properties.CaptchaProperties; import com.ruoyi.framework.config.properties.CaptchaProperties;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -32,19 +29,6 @@ import java.util.concurrent.TimeUnit;
@RestController @RestController
public class CaptchaController { public class CaptchaController {
// 圆圈干扰验证码
@Resource(name = "CircleCaptcha")
private CircleCaptcha circleCaptcha;
// 线段干扰的验证码
@Resource(name = "LineCaptcha")
private LineCaptcha lineCaptcha;
// 扭曲干扰验证码
@Resource(name = "ShearCaptcha")
private ShearCaptcha shearCaptcha;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private CaptchaProperties captchaProperties; private CaptchaProperties captchaProperties;
@ -65,41 +49,16 @@ public class CaptchaController {
// 保存验证码信息 // 保存验证码信息
String uuid = IdUtil.simpleUUID(); String uuid = IdUtil.simpleUUID();
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String code = null;
// 生成验证码 // 生成验证码
CodeGenerator codeGenerator; CaptchaType captchaType = captchaProperties.getType();
AbstractCaptcha captcha; boolean isMath = CaptchaType.MATH == captchaType;
switch (captchaProperties.getType()) { Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
case "math": CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
codeGenerator = new UnsignedMathGenerator(captchaProperties.getNumberLength()); AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
break;
case "char":
codeGenerator = new RandomGenerator(captchaProperties.getCharLength());
break;
default:
throw new IllegalArgumentException("验证码类型异常");
}
switch (captchaProperties.getCategory()) {
case "line":
captcha = lineCaptcha;
break;
case "circle":
captcha = circleCaptcha;
break;
case "shear":
captcha = shearCaptcha;
break;
default:
throw new IllegalArgumentException("验证码类别异常");
}
captcha.setGenerator(codeGenerator); captcha.setGenerator(codeGenerator);
captcha.createCode(); captcha.createCode();
if ("math".equals(captchaProperties.getType())) { String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode();
code = getCodeResult(captcha.getCode()); RedisUtils.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
} else if ("char".equals(captchaProperties.getType())) {
code = captcha.getCode();
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
ajax.put("uuid", uuid); ajax.put("uuid", uuid);
ajax.put("img", captcha.getImageBase64()); ajax.put("img", captcha.getImageBase64());
return AjaxResult.success(ajax); return AjaxResult.success(ajax);
@ -112,13 +71,13 @@ public class CaptchaController {
int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim()); int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim());
switch (operator) { switch (operator) {
case '*': case '*':
return a * b + ""; return Convert.toStr(a * b);
case '+': case '+':
return a + b + ""; return Convert.toStr(a + b);
case '-': case '-':
return a - b + ""; return Convert.toStr(a - b);
default: default:
return ""; return StringUtils.EMPTY;
} }
} }

View File

@ -6,9 +6,9 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline; import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService; import com.ruoyi.system.service.ISysUserOnlineService;
@ -33,18 +33,15 @@ public class SysUserOnlineController extends BaseController
@Autowired @Autowired
private ISysUserOnlineService userOnlineService; private ISysUserOnlineService userOnlineService;
@Autowired
private RedisCache redisCache;
@PreAuthorize("@ss.hasPermi('monitor:online:list')") @PreAuthorize("@ss.hasPermi('monitor:online:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(String ipaddr, String userName) public TableDataInfo list(String ipaddr, String userName)
{ {
Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*"); Collection<String> keys = RedisUtils.keys(Constants.LOGIN_TOKEN_KEY + "*");
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>(); List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
for (String key : keys) for (String key : keys)
{ {
LoginUser user = redisCache.getCacheObject(key); LoginUser user = RedisUtils.getCacheObject(key);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
{ {
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
@ -84,7 +81,7 @@ public class SysUserOnlineController extends BaseController
@DeleteMapping("/{tokenId}") @DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId) public AjaxResult forceLogout(@PathVariable String tokenId)
{ {
redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId); RedisUtils.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
return AjaxResult.success(); return AjaxResult.success();
} }
} }

View File

@ -70,6 +70,7 @@ public class SysDeptController extends BaseController
@GetMapping(value = "/{deptId}") @GetMapping(value = "/{deptId}")
public AjaxResult getInfo(@PathVariable Long deptId) public AjaxResult getInfo(@PathVariable Long deptId)
{ {
deptService.checkDeptDataScope(deptId);
return AjaxResult.success(deptService.selectDeptById(deptId)); return AjaxResult.success(deptService.selectDeptById(deptId));
} }

View File

@ -5,12 +5,9 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody; import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.web.service.SysLoginService; import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService; import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysMenuService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -40,9 +37,6 @@ public class SysLoginController
@Autowired @Autowired
private SysPermissionService permissionService; private SysPermissionService permissionService;
@Autowired
private TokenService tokenService;
/** /**
* 登录方法 * 登录方法
* *
@ -68,8 +62,7 @@ public class SysLoginController
@GetMapping("getInfo") @GetMapping("getInfo")
public AjaxResult getInfo() public AjaxResult getInfo()
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); SysUser user = SecurityUtils.getLoginUser().getUser();
SysUser user = loginUser.getUser();
// 角色集合 // 角色集合
Set<String> roles = permissionService.getRolePermission(user); Set<String> roles = permissionService.getRolePermission(user);
// 权限集合 // 权限集合

View File

@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup; import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.bo.SysOssConfigBo; import com.ruoyi.system.domain.bo.SysOssConfigBo;
import com.ruoyi.system.domain.vo.SysOssConfigVo; import com.ruoyi.system.domain.vo.SysOssConfigVo;
@ -45,7 +46,7 @@ public class SysOssConfigController extends BaseController {
@ApiOperation("查询云存储配置列表") @ApiOperation("查询云存储配置列表")
@PreAuthorize("@ss.hasPermi('system:oss:list')") @PreAuthorize("@ss.hasPermi('system:oss:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo<SysOssConfigVo> list(@Validated SysOssConfigBo bo) { public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo) {
return iSysOssConfigService.queryPageList(bo); return iSysOssConfigService.queryPageList(bo);
} }

View File

@ -10,6 +10,7 @@ import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.JsonUtils;
@ -63,7 +64,7 @@ public class SysOssController extends BaseController {
@ApiOperation("查询OSS云存储列表") @ApiOperation("查询OSS云存储列表")
@PreAuthorize("@ss.hasPermi('system:oss:list')") @PreAuthorize("@ss.hasPermi('system:oss:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo<SysOssVo> list(@Validated SysOssBo bo) { public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo) {
return iSysOssService.queryPageList(bo); return iSysOssService.queryPageList(bo);
} }

View File

@ -8,7 +8,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.SysOss;
@ -46,7 +45,7 @@ public class SysProfileController extends BaseController
@GetMapping @GetMapping
public AjaxResult profile() public AjaxResult profile()
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = getLoginUser();
SysUser user = loginUser.getUser(); SysUser user = loginUser.getUser();
Map<String,Object> ajax = new HashMap<>(); Map<String,Object> ajax = new HashMap<>();
ajax.put("user", user); ajax.put("user", user);
@ -72,17 +71,17 @@ public class SysProfileController extends BaseController
{ {
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
} }
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = getLoginUser();
SysUser sysUser = loginUser.getUser(); SysUser sysUser = loginUser.getUser();
user.setUserId(sysUser.getUserId()); user.setUserId(sysUser.getUserId());
user.setPassword(null); user.setPassword(null);
if (userService.updateUserProfile(user) > 0) if (userService.updateUserProfile(user) > 0)
{ {
// 更新缓存用户信息 // 更新缓存用户信息
loginUser.getUser().setNickName(user.getNickName()); sysUser.setNickName(user.getNickName());
loginUser.getUser().setPhonenumber(user.getPhonenumber()); sysUser.setPhonenumber(user.getPhonenumber());
loginUser.getUser().setEmail(user.getEmail()); sysUser.setEmail(user.getEmail());
loginUser.getUser().setSex(user.getSex()); sysUser.setSex(user.getSex());
tokenService.setLoginUser(loginUser); tokenService.setLoginUser(loginUser);
return AjaxResult.success(); return AjaxResult.success();
} }
@ -96,7 +95,7 @@ public class SysProfileController extends BaseController
@PutMapping("/updatePwd") @PutMapping("/updatePwd")
public AjaxResult updatePwd(String oldPassword, String newPassword) public AjaxResult updatePwd(String oldPassword, String newPassword)
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = getLoginUser();
String userName = loginUser.getUsername(); String userName = loginUser.getUsername();
String password = loginUser.getPassword(); String password = loginUser.getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password)) if (!SecurityUtils.matchesPassword(oldPassword, password))
@ -126,7 +125,7 @@ public class SysProfileController extends BaseController
{ {
if (!file.isEmpty()) if (!file.isEmpty())
{ {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = getLoginUser();
SysOss oss = iSysOssService.upload(file); SysOss oss = iSysOssService.upload(file);
String avatar = oss.getUrl(); String avatar = oss.getUrl();
if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) if (userService.updateUserAvatar(loginUser.getUsername(), avatar))

View File

@ -9,7 +9,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService; import com.ruoyi.framework.web.service.SysPermissionService;
@ -69,6 +68,7 @@ public class SysRoleController extends BaseController
@GetMapping(value = "/{roleId}") @GetMapping(value = "/{roleId}")
public AjaxResult getInfo(@PathVariable Long roleId) public AjaxResult getInfo(@PathVariable Long roleId)
{ {
roleService.checkRoleDataScope(roleId);
return AjaxResult.success(roleService.selectRoleById(roleId)); return AjaxResult.success(roleService.selectRoleById(roleId));
} }
@ -115,7 +115,7 @@ public class SysRoleController extends BaseController
if (roleService.updateRole(role) > 0) if (roleService.updateRole(role) > 0)
{ {
// 更新缓存用户权限 // 更新缓存用户权限
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{ {
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser())); loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));

View File

@ -10,14 +10,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.vo.SysUserExportVo; import com.ruoyi.system.domain.vo.SysUserExportVo;
import com.ruoyi.system.domain.vo.SysUserImportVo; import com.ruoyi.system.domain.vo.SysUserImportVo;
import com.ruoyi.system.service.ISysPostService; import com.ruoyi.system.service.ISysPostService;
@ -54,9 +51,6 @@ public class SysUserController extends BaseController
@Autowired @Autowired
private ISysPostService postService; private ISysPostService postService;
@Autowired
private TokenService tokenService;
/** /**
* 获取用户列表 * 获取用户列表
*/ */
@ -92,8 +86,7 @@ public class SysUserController extends BaseController
{ {
List<SysUserImportVo> userListVo = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class); List<SysUserImportVo> userListVo = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class);
List<SysUser> userList = BeanUtil.copyToList(userListVo, SysUser.class); List<SysUser> userList = BeanUtil.copyToList(userListVo, SysUser.class);
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); String operName = getUsername();
String operName = loginUser.getUsername();
String message = userService.importUser(userList, updateSupport, operName); String message = userService.importUser(userList, updateSupport, operName);
return AjaxResult.success(message); return AjaxResult.success(message);
} }
@ -111,6 +104,7 @@ public class SysUserController extends BaseController
@GetMapping(value = { "/", "/{userId}" }) @GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{ {
userService.checkUserDataScope(userId);
Map<String, Object> ajax = new HashMap<>(); Map<String, Object> ajax = new HashMap<>();
List<SysRole> roles = roleService.selectRoleAll(); List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));

View File

@ -38,7 +38,7 @@ spring:
# 配置一个连接在池中最大生存的时间,单位是毫秒 # 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000 maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效 # 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL validationQuery: SELECT 1
testWhileIdle: true testWhileIdle: true
testOnBorrow: false testOnBorrow: false
testOnReturn: false testOnReturn: false

View File

@ -38,7 +38,7 @@ spring:
# 配置一个连接在池中最大生存的时间,单位是毫秒 # 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000 maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效 # 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL validationQuery: SELECT 1
testWhileIdle: true testWhileIdle: true
testOnBorrow: false testOnBorrow: false
testOnReturn: false testOnReturn: false

View File

@ -12,10 +12,11 @@ ruoyi:
addressEnabled: true addressEnabled: true
captcha: captcha:
# 页面 <参数设置> 可开启关闭 验证码校验
# 验证码类型 math 数组计算 char 字符验证 # 验证码类型 math 数组计算 char 字符验证
type: math type: MATH
# line 线段干扰 circle 圆圈干扰 shear 扭曲干扰 # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
category: circle category: CIRCLE
# 数字验证码位数 # 数字验证码位数
numberLength: 1 numberLength: 1
# 字符验证码长度 # 字符验证码长度
@ -133,8 +134,6 @@ mybatis-plus:
# REUSE该执行器类型会复用预处理语句PreparedStatement # REUSE该执行器类型会复用预处理语句PreparedStatement
# BATCH该执行器类型会批量执行所有的更新语句 # BATCH该执行器类型会批量执行所有的更新语句
executorType: SIMPLE executorType: SIMPLE
# 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
configurationProperties: null
configuration: configuration:
# 自动驼峰命名规则camel case映射 # 自动驼峰命名规则camel case映射
# 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名 # 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
@ -199,11 +198,11 @@ mybatis-plus:
# NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断) # NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
# DEFAULT 默认的,一般只用于注解里 # DEFAULT 默认的,一般只用于注解里
# NEVER 不加入 SQL # NEVER 不加入 SQL
insertStrategy: NOT_EMPTY insertStrategy: NOT_NULL
# 字段验证策略之 update,在 update 的时候的字段验证策略 # 字段验证策略之 update,在 update 的时候的字段验证策略
updateStrategy: NOT_EMPTY updateStrategy: NOT_NULL
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件 # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
selectStrategy: NOT_EMPTY where-strategy: NOT_NULL
# Swagger配置 # Swagger配置
swagger: swagger:
@ -245,11 +244,11 @@ thread-pool:
# 线程池维护线程所允许的空闲时间 # 线程池维护线程所允许的空闲时间
keepAliveSeconds: 300 keepAliveSeconds: 300
# 线程池对拒绝任务(无线程可用)的处理策略 # 线程池对拒绝任务(无线程可用)的处理策略
# CallerRunsPolicy 等待 # CALLER_RUNS_POLICY 等待
# DiscardOldestPolicy 放弃最旧的 # DISCARD_OLDEST_POLICY 放弃最旧的
# DiscardPolicy 丢弃 # DISCARD_POLICY 丢弃
# AbortPolicy 中止 # ABORT_POLICY 中止
rejectedExecutionHandler: CallerRunsPolicy rejectedExecutionHandler: CALLER_RUNS_POLICY
# feign 相关配置 # feign 相关配置
feign: feign:

View File

@ -1,26 +1,26 @@
# p6spy 性能分析插件配置文件 # p6spy 性能分析插件配置文件
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印 # 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台 #日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql # 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger #appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理 # 设置 p6spy driver 代理
#deregisterdrivers=true #deregisterdrivers=true
# 取消JDBC URL前缀 # 取消JDBC URL前缀
useprefix=true useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset. # 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset excludecategories=info,debug,result,commit,resultset
# 日期格式 # 日期格式
dateformat=yyyy-MM-dd HH:mm:ss dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个 # 实际驱动可多个
#driverlist=org.h2.Driver #driverlist=org.h2.Driver
# 是否开启慢SQL记录 # 是否开启慢SQL记录
outagedetection=true outagedetection=true
# 慢SQL记录标准 2 秒 # 慢SQL记录标准 2 秒
outagedetectioninterval=2 outagedetectioninterval=2
# 是否过滤 Log # 是否过滤 Log
filter=true filter=true
# 过滤 Log 时所排除的表名列表,以逗号分隔 # 过滤 Log 时所排除的表名列表,以逗号分隔
exclude=QRTZ_ exclude=QRTZ_

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -1,4 +1,4 @@
package com.ruoyi.framework.captcha; package com.ruoyi.common.captcha;
import cn.hutool.captcha.generator.CodeGenerator; import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.math.Calculator; import cn.hutool.core.math.Calculator;

View File

@ -139,4 +139,8 @@ public class Constants
*/ */
public static final String LOOKUP_RMI = "rmi://"; public static final String LOOKUP_RMI = "rmi://";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap://";
} }

View File

@ -0,0 +1,51 @@
package com.ruoyi.common.convert;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
/**
* 大数值转换
* Excel 数值长度位15位 大于15位的数值转换位字符串
*
* @author Lion Li
*/
@Slf4j
public class ExcelBigNumberConvert implements Converter<Long> {
@Override
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return Convert.toLong(cellData.getData());
}
@Override
public CellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (ObjectUtil.isNotNull(object)) {
String str = Convert.toStr(object);
if (str.length() > 15) {
return new CellData<>(str);
}
}
CellData<Object> cellData = new CellData<>(new BigDecimal(object));
cellData.setType(CellDataTypeEnum.NUMBER);
return cellData;
}
}

View File

@ -16,28 +16,6 @@ public class BaseController
{ {
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult<Void> toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult<Void> toAjax(boolean result)
{
return result ? success() : error();
}
/** /**
* 返回成功 * 返回成功
*/ */
@ -70,6 +48,28 @@ public class BaseController
return AjaxResult.error(message); return AjaxResult.error(message);
} }
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult<Void> toAjax(int rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
*
* @param result 结果
* @return 操作结果
*/
protected AjaxResult<Void> toAjax(boolean result)
{
return result ? success() : error();
}
/** /**
* 页面跳转 * 页面跳转
*/ */

View File

@ -78,6 +78,11 @@ public class SysUser implements Serializable {
/** /**
* 密码 * 密码
*/ */
@TableField(
insertStrategy = FieldStrategy.NOT_EMPTY,
updateStrategy = FieldStrategy.NOT_EMPTY,
whereStrategy = FieldStrategy.NOT_EMPTY
)
private String password; private String password;
@JsonIgnore @JsonIgnore

View File

@ -1,7 +1,7 @@
package com.ruoyi.common.core.mybatisplus.cache; package com.ruoyi.common.core.mybatisplus.cache;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.connection.RedisServerCommands; import org.springframework.data.redis.connection.RedisServerCommands;
@ -25,8 +25,6 @@ public class MybatisPlusRedisCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
private RedisCache redisCache;
private String id; private String id;
public MybatisPlusRedisCache(final String id) { public MybatisPlusRedisCache(final String id) {
@ -43,23 +41,16 @@ public class MybatisPlusRedisCache implements Cache {
@Override @Override
public void putObject(Object key, Object value) { public void putObject(Object key, Object value) {
if (redisCache == null) {
redisCache = SpringUtil.getBean(RedisCache.class);
}
if (value != null) { if (value != null) {
redisCache.setCacheObject(key.toString(), value); RedisUtils.setCacheObject(key.toString(), value);
} }
} }
@Override @Override
public Object getObject(Object key) { public Object getObject(Object key) {
if (redisCache == null) {
//由于启动期间注入失败只能运行期间注入这段代码可以删除
redisCache = SpringUtil.getBean(RedisCache.class);
}
try { try {
if (key != null) { if (key != null) {
return redisCache.getCacheObject(key.toString()); return RedisUtils.getCacheObject(key.toString());
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -70,11 +61,8 @@ public class MybatisPlusRedisCache implements Cache {
@Override @Override
public Object removeObject(Object key) { public Object removeObject(Object key) {
if (redisCache == null) {
redisCache = SpringUtil.getBean(RedisCache.class);
}
if (key != null) { if (key != null) {
redisCache.deleteObject(key.toString()); RedisUtils.deleteObject(key.toString());
} }
return null; return null;
} }
@ -82,12 +70,9 @@ public class MybatisPlusRedisCache implements Cache {
@Override @Override
public void clear() { public void clear() {
log.debug("清空缓存"); log.debug("清空缓存");
if (redisCache == null) { Collection<String> keys = RedisUtils.keys("*:" + this.id + "*");
redisCache = SpringUtil.getBean(RedisCache.class);
}
Collection<String> keys = redisCache.keys("*:" + this.id + "*");
if (!CollectionUtils.isEmpty(keys)) { if (!CollectionUtils.isEmpty(keys)) {
redisCache.deleteObject(keys); RedisUtils.deleteObject(keys);
} }
} }

View File

@ -14,8 +14,7 @@ import java.util.Collection;
public interface BaseMapperPlus<T> extends BaseMapper<T> { public interface BaseMapperPlus<T> extends BaseMapper<T> {
/** /**
* 单sql批量插入( 全量填充 无视数据库默认值 ) * 单sql批量插入( 全量填充 )
* 适用于无脑插入
*/ */
int insertAll(@Param("list") Collection<T> batchList); int insertAll(@Param("list") Collection<T> batchList);

View File

@ -15,45 +15,46 @@ import java.util.function.Function;
/** /**
* 自定义 Service 接口, 实现 数据库实体与 vo 对象转换返回 * 自定义 Service 接口, 实现 数据库实体与 vo 对象转换返回
* *
* @param <T> 数据实体类
* @param <V> vo类
* @author Lion Li * @author Lion Li
* @since 2021-05-13
*/ */
public interface IServicePlus<T, K> extends IService<T> { public interface IServicePlus<T, V> extends IService<T> {
/** /**
* @param id 主键id * @param id 主键id
* @param copyOptions copy条件 * @param copyOptions copy条件
* @return K对象 * @return V对象
*/ */
K getVoById(Serializable id, CopyOptions copyOptions); V getVoById(Serializable id, CopyOptions copyOptions);
default K getVoById(Serializable id) { default V getVoById(Serializable id) {
return getVoById(id, new CopyOptions()); return getVoById(id, new CopyOptions());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default K getVoById(Serializable id, Function<T, K> convertor) { default V getVoById(Serializable id, Function<T, V> convertor) {
return convertor.apply(getById(id)); return convertor.apply(getById(id));
} }
/** /**
* @param idList id列表 * @param idList id列表
* @param copyOptions copy条件 * @param copyOptions copy条件
* @return K对象 * @return V对象
*/ */
List<K> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions); List<V> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions);
default List<K> listVoByIds(Collection<? extends Serializable> idList) { default List<V> listVoByIds(Collection<? extends Serializable> idList) {
return listVoByIds(idList, new CopyOptions()); return listVoByIds(idList, new CopyOptions());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default List<K> listVoByIds(Collection<? extends Serializable> idList, default List<V> listVoByIds(Collection<? extends Serializable> idList,
Function<Collection<T>, List<K>> convertor) { Function<Collection<T>, List<V>> convertor) {
List<T> list = getBaseMapper().selectBatchIds(idList); List<T> list = getBaseMapper().selectBatchIds(idList);
if (list == null) { if (list == null) {
return null; return null;
@ -64,19 +65,19 @@ public interface IServicePlus<T, K> extends IService<T> {
/** /**
* @param columnMap 表字段 map 对象 * @param columnMap 表字段 map 对象
* @param copyOptions copy条件 * @param copyOptions copy条件
* @return K对象 * @return V对象
*/ */
List<K> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions); List<V> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions);
default List<K> listVoByMap(Map<String, Object> columnMap) { default List<V> listVoByMap(Map<String, Object> columnMap) {
return listVoByMap(columnMap, new CopyOptions()); return listVoByMap(columnMap, new CopyOptions());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default List<K> listVoByMap(Map<String, Object> columnMap, default List<V> listVoByMap(Map<String, Object> columnMap,
Function<Collection<T>, List<K>> convertor) { Function<Collection<T>, List<V>> convertor) {
List<T> list = getBaseMapper().selectByMap(columnMap); List<T> list = getBaseMapper().selectByMap(columnMap);
if (list == null) { if (list == null) {
return null; return null;
@ -87,36 +88,36 @@ public interface IServicePlus<T, K> extends IService<T> {
/** /**
* @param queryWrapper 查询条件 * @param queryWrapper 查询条件
* @param copyOptions copy条件 * @param copyOptions copy条件
* @return K对象 * @return V对象
*/ */
K getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions); V getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions);
default K getVoOne(Wrapper<T> queryWrapper) { default V getVoOne(Wrapper<T> queryWrapper) {
return getVoOne(queryWrapper, new CopyOptions()); return getVoOne(queryWrapper, new CopyOptions());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default K getVoOne(Wrapper<T> queryWrapper, Function<T, K> convertor) { default V getVoOne(Wrapper<T> queryWrapper, Function<T, V> convertor) {
return convertor.apply(getOne(queryWrapper, true)); return convertor.apply(getOne(queryWrapper, true));
} }
/** /**
* @param queryWrapper 查询条件 * @param queryWrapper 查询条件
* @param copyOptions copy条件 * @param copyOptions copy条件
* @return K对象 * @return V对象
*/ */
List<K> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions); List<V> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions);
default List<K> listVo(Wrapper<T> queryWrapper) { default List<V> listVo(Wrapper<T> queryWrapper) {
return listVo(queryWrapper, new CopyOptions()); return listVo(queryWrapper, new CopyOptions());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default List<K> listVo(Wrapper<T> queryWrapper, Function<Collection<T>, List<K>> convertor) { default List<V> listVo(Wrapper<T> queryWrapper, Function<Collection<T>, List<V>> convertor) {
List<T> list = getBaseMapper().selectList(queryWrapper); List<T> list = getBaseMapper().selectList(queryWrapper);
if (list == null) { if (list == null) {
return null; return null;
@ -124,14 +125,14 @@ public interface IServicePlus<T, K> extends IService<T> {
return convertor.apply(list); return convertor.apply(list);
} }
default List<K> listVo() { default List<V> listVo() {
return listVo(Wrappers.emptyWrapper()); return listVo(Wrappers.emptyWrapper());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default List<K> listVo(Function<Collection<T>, List<K>> convertor) { default List<V> listVo(Function<Collection<T>, List<V>> convertor) {
return listVo(Wrappers.emptyWrapper(), convertor); return listVo(Wrappers.emptyWrapper(), convertor);
} }
@ -139,34 +140,36 @@ public interface IServicePlus<T, K> extends IService<T> {
* @param page 分页对象 * @param page 分页对象
* @param queryWrapper 查询条件 * @param queryWrapper 查询条件
* @param copyOptions copy条件 * @param copyOptions copy条件
* @return K对象 * @return V对象
*/ */
PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper, CopyOptions copyOptions); PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper, CopyOptions copyOptions);
default PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper) { default PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper) {
return pageVo(page, queryWrapper, new CopyOptions()); return pageVo(page, queryWrapper, new CopyOptions());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper, default PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper,
Function<Collection<T>, List<K>> convertor) { Function<Collection<T>, List<V>> convertor) {
PagePlus<T, K> result = getBaseMapper().selectPage(page, queryWrapper); PagePlus<T, V> result = getBaseMapper().selectPage(page, queryWrapper);
return result.setRecordsVo(convertor.apply(result.getRecords())); return result.setRecordsVo(convertor.apply(result.getRecords()));
} }
default PagePlus<T, K> pageVo(PagePlus<T, K> page) { default PagePlus<T, V> pageVo(PagePlus<T, V> page) {
return pageVo(page, Wrappers.emptyWrapper()); return pageVo(page, Wrappers.emptyWrapper());
} }
/** /**
* @param convertor 自定义转换器 * @param convertor 自定义转换器
*/ */
default PagePlus<T, K> pageVo(PagePlus<T, K> page, Function<Collection<T>, List<K>> convertor) { default PagePlus<T, V> pageVo(PagePlus<T, V> page, Function<Collection<T>, List<V>> convertor) {
return pageVo(page, Wrappers.emptyWrapper(), convertor); return pageVo(page, Wrappers.emptyWrapper(), convertor);
} }
boolean saveAll(Collection<T> entityList); boolean saveAll(Collection<T> entityList);
boolean saveOrUpdateAll(Collection<T> entityList);
} }

View File

@ -1,16 +1,22 @@
package com.ruoyi.common.core.mybatisplus.core; package com.ruoyi.common.core.mybatisplus.core;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils; import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.page.PagePlus; import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.utils.BeanCopyUtils; import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ResolvableType;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -18,11 +24,14 @@ import java.util.Map;
/** /**
* IServicePlus 实现类 * IServicePlus 实现类
* *
* @param <M> Mapper类
* @param <T> 数据实体类
* @param <V> vo类
* @author Lion Li * @author Lion Li
*/ */
@Slf4j @Slf4j
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceImpl<M, T> implements IServicePlus<T, K> { public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, V> extends ServiceImpl<M, T> implements IServicePlus<T, V> {
@Autowired @Autowired
protected M baseMapper; protected M baseMapper;
@ -40,31 +49,26 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
return entityClass; return entityClass;
} }
protected Class<T> mapperClass = currentMapperClass(); protected Class<M> mapperClass = currentMapperClass();
protected Class<K> voClass = currentVoClass(); protected Class<V> voClass = currentVoClass();
public Class<K> getVoClass() { public Class<V> getVoClass() {
return voClass; return voClass;
} }
@Override @Override
protected Class<T> currentMapperClass() { protected Class<M> currentMapperClass() {
return (Class<T>) this.getResolvableType().as(ServicePlusImpl.class).getGeneric(0).getType(); return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServicePlusImpl.class, 0);
} }
@Override @Override
protected Class<T> currentModelClass() { protected Class<T> currentModelClass() {
return (Class<T>) this.getResolvableType().as(ServicePlusImpl.class).getGeneric(1).getType(); return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServicePlusImpl.class, 1);
} }
protected Class<K> currentVoClass() { protected Class<V> currentVoClass() {
return (Class<K>) this.getResolvableType().as(ServicePlusImpl.class).getGeneric(2).getType(); return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServicePlusImpl.class, 2);
}
@Override
protected ResolvableType getResolvableType() {
return ResolvableType.forClass(ClassUtils.getUserClass(getClass()));
} }
/** /**
@ -113,21 +117,55 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
} }
/** /**
* 单sql批量插入( 全量填充 无视数据库默认值 ) * 单sql批量插入( 全量填充 )
* 适用于无脑插入
*/ */
@Override @Override
public boolean saveAll(Collection<T> entityList) { public boolean saveAll(Collection<T> entityList) {
if (CollUtil.isEmpty(entityList)) {
return false;
}
return baseMapper.insertAll(entityList) == entityList.size(); return baseMapper.insertAll(entityList) == entityList.size();
} }
/**
* 全量保存或更新 ( 按主键区分 )
*/
@Override
public boolean saveOrUpdateAll(Collection<T> entityList) {
if (CollUtil.isEmpty(entityList)) {
return false;
}
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
List<T> addList = new ArrayList<>();
List<T> updateList = new ArrayList<>();
int row = 0;
for (T entity : entityList) {
Object id = ReflectUtils.invokeGetter(entity, keyProperty);
if (ObjectUtil.isNull(id)) {
addList.add(entity);
} else {
updateList.add(entity);
}
}
if (CollUtil.isNotEmpty(updateList) && updateBatchById(updateList)) {
row += updateList.size();
}
if (CollUtil.isNotEmpty(addList)) {
row += baseMapper.insertAll(addList);
}
return row == entityList.size();
}
/** /**
* 根据 ID 查询 * 根据 ID 查询
* *
* @param id 主键ID * @param id 主键ID
*/ */
@Override @Override
public K getVoById(Serializable id, CopyOptions copyOptions) { public V getVoById(Serializable id, CopyOptions copyOptions) {
T t = getBaseMapper().selectById(id); T t = getBaseMapper().selectById(id);
return BeanCopyUtils.oneCopy(t, copyOptions, voClass); return BeanCopyUtils.oneCopy(t, copyOptions, voClass);
} }
@ -138,7 +176,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
* @param idList 主键ID列表 * @param idList 主键ID列表
*/ */
@Override @Override
public List<K> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions) { public List<V> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions) {
List<T> list = getBaseMapper().selectBatchIds(idList); List<T> list = getBaseMapper().selectBatchIds(idList);
if (list == null) { if (list == null) {
return null; return null;
@ -152,7 +190,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
* @param columnMap 表字段 map 对象 * @param columnMap 表字段 map 对象
*/ */
@Override @Override
public List<K> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions) { public List<V> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions) {
List<T> list = getBaseMapper().selectByMap(columnMap); List<T> list = getBaseMapper().selectByMap(columnMap);
if (list == null) { if (list == null) {
return null; return null;
@ -167,7 +205,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/ */
@Override @Override
public K getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions) { public V getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
T t = getOne(queryWrapper, true); T t = getOne(queryWrapper, true);
return BeanCopyUtils.oneCopy(t, copyOptions, voClass); return BeanCopyUtils.oneCopy(t, copyOptions, voClass);
} }
@ -178,7 +216,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/ */
@Override @Override
public List<K> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions) { public List<V> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
List<T> list = getBaseMapper().selectList(queryWrapper); List<T> list = getBaseMapper().selectList(queryWrapper);
if (list == null) { if (list == null) {
return null; return null;
@ -193,9 +231,9 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
* @param queryWrapper 实体对象封装操作类 * @param queryWrapper 实体对象封装操作类
*/ */
@Override @Override
public PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper, CopyOptions copyOptions) { public PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper, CopyOptions copyOptions) {
PagePlus<T, K> result = getBaseMapper().selectPage(page, queryWrapper); PagePlus<T, V> result = getBaseMapper().selectPage(page, queryWrapper);
List<K> volist = BeanCopyUtils.listCopy(result.getRecords(), copyOptions, voClass); List<V> volist = BeanCopyUtils.listCopy(result.getRecords(), copyOptions, voClass);
result.setRecordsVo(volist); result.setRecordsVo(volist);
return result; return result;
} }

View File

@ -2,6 +2,7 @@ package com.ruoyi.common.core.mybatisplus.methods;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
@ -11,13 +12,17 @@ import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource; import org.apache.ibatis.mapping.SqlSource;
import java.util.List;
/** /**
* 单sql批量插入( 全量填充 无视数据库默认值 ) * 单sql批量插入( 全量填充 )
* *
* @author Lion Li * @author Lion Li
*/ */
public class InsertAll extends AbstractMethod { public class InsertAll extends AbstractMethod {
private final static String[] FILL_PROPERTY = {"createTime", "createBy", "updateTime", "updateBy"};
@Override @Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
final String sql = "<script>insert into %s %s values %s</script>"; final String sql = "<script>insert into %s %s values %s</script>";
@ -63,10 +68,32 @@ public class InsertAll extends AbstractMethod {
final StringBuilder valueSql = new StringBuilder(); final StringBuilder valueSql = new StringBuilder();
valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">"); valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
if (StringUtils.isNotBlank(tableInfo.getKeyColumn())) { if (StringUtils.isNotBlank(tableInfo.getKeyColumn())) {
valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},"); valueSql.append("\n#{item.").append(tableInfo.getKeyProperty()).append("},\n");
}
List<TableFieldInfo> fieldList = tableInfo.getFieldList();
int last = fieldList.size() - 1;
for (int i = 0; i < fieldList.size(); i++) {
String property = fieldList.get(i).getProperty();
if (!StringUtils.equalsAny(property, FILL_PROPERTY)) {
valueSql.append("<if test=\"item.").append(property).append(" != null\">");
valueSql.append("#{item.").append(property).append("}");
if (i != last) {
valueSql.append(",");
}
valueSql.append("</if>");
valueSql.append("<if test=\"item.").append(property).append(" == null\">");
valueSql.append("DEFAULT");
if (i != last) {
valueSql.append(",");
}
valueSql.append("</if>");
} else {
valueSql.append("#{item.").append(property).append("}");
if (i != last) {
valueSql.append(",");
}
}
} }
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
valueSql.delete(valueSql.length() - 1, valueSql.length());
valueSql.append("</foreach>"); valueSql.append("</foreach>");
return valueSql.toString(); return valueSql.toString();
} }

View File

@ -5,21 +5,58 @@ import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.*; import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/** /**
* spring redis 工具类 * spring redis 工具类
* *
* @author shenxinquan * @author shenxinquan
* @see com.ruoyi.common.utils.RedisUtils
* @deprecated 3.2.0 删除此类
**/ **/
@SuppressWarnings(value = {"unchecked", "rawtypes"}) @SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component @Component
@Deprecated
public class RedisCache { public class RedisCache {
@Autowired @Autowired
private RedissonClient redissonClient; private RedissonClient redissonClient;
/**
* 发布通道消息
*
* @param channelKey 通道key
* @param msg 发送数据
* @param consumer 自定义处理
*/
public <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
RTopic topic = redissonClient.getTopic(channelKey);
topic.publish(msg);
consumer.accept(msg);
}
public <T> void publish(String channelKey, T msg) {
RTopic topic = redissonClient.getTopic(channelKey);
topic.publish(msg);
}
/**
* 订阅通道接收消息
*
* @param channelKey 通道key
* @param clazz 消息类型
* @param consumer 自定义处理
*/
public <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
RTopic topic = redissonClient.getTopic(channelKey);
topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
}
/** /**
* 缓存基本的对象IntegerString实体类等 * 缓存基本的对象IntegerString实体类等
* *

View File

@ -0,0 +1,9 @@
package com.ruoyi.common.core.validate;
/**
* 校验分组 query
*
* @author Lion Li
*/
public interface QueryGroup {
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.common.enums;
import cn.hutool.captcha.AbstractCaptcha;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 验证码类别
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum CaptchaCategory {
/**
* 线段干扰
*/
LINE(LineCaptcha.class),
/**
* 圆圈干扰
*/
CIRCLE(CircleCaptcha.class),
/**
* 扭曲干扰
*/
SHEAR(ShearCaptcha.class);
private final Class<? extends AbstractCaptcha> clazz;
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.common.enums;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.captcha.generator.RandomGenerator;
import com.ruoyi.common.captcha.UnsignedMathGenerator;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 验证码类型
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum CaptchaType {
/**
* 数字
*/
MATH(UnsignedMathGenerator.class),
/**
* 字符
*/
CHAR(RandomGenerator.class);
private final Class<? extends CodeGenerator> clazz;
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池 拒绝策略 泛型
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum ThreadPoolRejectedPolicy {
CALLER_RUNS_POLICY("等待", ThreadPoolExecutor.CallerRunsPolicy.class),
DISCARD_OLDEST_POLICY("放弃最旧的", ThreadPoolExecutor.DiscardOldestPolicy.class),
DISCARD_POLICY("丢弃", ThreadPoolExecutor.DiscardPolicy.class),
ABORT_POLICY("中止", ThreadPoolExecutor.AbortPolicy.class);
private final String name;
private final Class<? extends RejectedExecutionHandler> clazz;
}

View File

@ -65,8 +65,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
// xss过滤 // xss过滤
json = HtmlUtil.cleanHtmlTag(json).trim(); json = HtmlUtil.cleanHtmlTag(json).trim();
byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
final ByteArrayInputStream bis = IoUtil.toStream(json, StandardCharsets.UTF_8); final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes);
return new ServletInputStream() return new ServletInputStream()
{ {
@Override @Override
@ -81,6 +81,12 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
return true; return true;
} }
@Override
public int available() throws IOException
{
return jsonBytes.length;
}
@Override @Override
public void setReadListener(ReadListener readListener) public void setReadListener(ReadListener readListener)
{ {

View File

@ -2,6 +2,8 @@ package com.ruoyi.common.utils;
import cn.hutool.core.bean.copier.BeanCopier; import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import java.util.List; import java.util.List;
@ -36,6 +38,9 @@ public class BeanCopyUtils {
* @return desc * @return desc
*/ */
public static <T, V> V oneCopy(T source, CopyOptions copyOptions, V desc) { public static <T, V> V oneCopy(T source, CopyOptions copyOptions, V desc) {
if (ObjectUtil.isNull(source)) {
return null;
}
return BeanCopier.create(source, desc, copyOptions).copy(); return BeanCopier.create(source, desc, copyOptions).copy();
} }
@ -48,6 +53,12 @@ public class BeanCopyUtils {
* @return desc * @return desc
*/ */
public static <T, V> List<V> listCopy(List<T> sourceList, CopyOptions copyOptions, Class<V> desc) { public static <T, V> List<V> listCopy(List<T> sourceList, CopyOptions copyOptions, Class<V> desc) {
if (ObjectUtil.isNull(sourceList)) {
return null;
}
if (CollUtil.isEmpty(sourceList)) {
return CollUtil.newArrayList();
}
return sourceList.stream() return sourceList.stream()
.map(source -> oneCopy(source, copyOptions, desc)) .map(source -> oneCopy(source, copyOptions, desc))
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -3,8 +3,6 @@ package com.ruoyi.common.utils;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.spring.SpringUtils;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -29,7 +27,7 @@ public class DictUtils
*/ */
public static void setDictCache(String key, List<SysDictData> dictDatas) public static void setDictCache(String key, List<SysDictData> dictDatas)
{ {
SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); RedisUtils.setCacheObject(getCacheKey(key), dictDatas);
} }
/** /**
@ -40,7 +38,7 @@ public class DictUtils
*/ */
public static List<SysDictData> getDictCache(String key) public static List<SysDictData> getDictCache(String key)
{ {
Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); Object cacheObj = RedisUtils.getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj)) if (StringUtils.isNotNull(cacheObj))
{ {
List<SysDictData> dictDatas = (List<SysDictData>)cacheObj; List<SysDictData> dictDatas = (List<SysDictData>)cacheObj;
@ -160,7 +158,7 @@ public class DictUtils
*/ */
public static void removeDictCache(String key) public static void removeDictCache(String key)
{ {
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key)); RedisUtils.deleteObject(getCacheKey(key));
} }
/** /**
@ -168,8 +166,8 @@ public class DictUtils
*/ */
public static void clearDictCache() public static void clearDictCache()
{ {
Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(Constants.SYS_DICT_KEY + "*"); Collection<String> keys = RedisUtils.keys(Constants.SYS_DICT_KEY + "*");
SpringUtils.getBean(RedisCache.class).deleteObject(keys); RedisUtils.deleteObject(keys);
} }
/** /**

View File

@ -4,6 +4,9 @@ import cn.hutool.core.util.ArrayUtil;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -15,20 +18,10 @@ import java.util.Map;
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class JsonUtils { public class JsonUtils {
private static ObjectMapper objectMapper = new ObjectMapper(); private static ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class);
/**
* 初始化 objectMapper 属性
* <p>
* 通过这样的方式使用 Spring 创建的 ObjectMapper Bean
*
* @param objectMapper ObjectMapper 对象
*/
public static void init(ObjectMapper objectMapper) {
JsonUtils.objectMapper = objectMapper;
}
public static String toJsonString(Object object) { public static String toJsonString(Object object) {
if (StringUtils.isNull(object)) { if (StringUtils.isNull(object)) {

View File

@ -57,15 +57,12 @@ public class PageUtils {
Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE); Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE);
String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN); String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN);
String isAsc = ServletUtils.getParameter(IS_ASC); String isAsc = ServletUtils.getParameter(IS_ASC);
PagePlus<T, K> page = new PagePlus<>(pageNum, pageSize); if (pageNum <= 0) {
if (StringUtils.isNotBlank(orderByColumn)) { pageNum = DEFAULT_PAGE_NUM;
String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
if ("asc".equals(isAsc)) {
page.addOrder(OrderItem.asc(orderBy));
} else if ("desc".equals(isAsc)) {
page.addOrder(OrderItem.desc(orderBy));
}
} }
PagePlus<T, K> page = new PagePlus<>(pageNum, pageSize);
OrderItem orderItem = buildOrderItem(orderByColumn, isAsc);
page.addOrder(orderItem);
return page; return page;
} }
@ -83,23 +80,32 @@ public class PageUtils {
Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE); Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE);
String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN, defaultOrderByColumn); String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN, defaultOrderByColumn);
String isAsc = ServletUtils.getParameter(IS_ASC, defaultIsAsc); String isAsc = ServletUtils.getParameter(IS_ASC, defaultIsAsc);
// 兼容前端排序类型 if (pageNum <= 0) {
if ("ascending".equals(isAsc)) { pageNum = DEFAULT_PAGE_NUM;
isAsc = "asc"; }
} else if ("descending".equals(isAsc)) {
isAsc = "desc";
}
Page<T> page = new Page<>(pageNum, pageSize); Page<T> page = new Page<>(pageNum, pageSize);
OrderItem orderItem = buildOrderItem(orderByColumn, isAsc);
page.addOrder(orderItem);
return page;
}
private static OrderItem buildOrderItem(String orderByColumn, String isAsc) {
// 兼容前端排序类型
if ("ascending".equals(isAsc)) {
isAsc = "asc";
} else if ("descending".equals(isAsc)) {
isAsc = "desc";
}
if (StringUtils.isNotBlank(orderByColumn)) { if (StringUtils.isNotBlank(orderByColumn)) {
String orderBy = SqlUtil.escapeOrderBySql(orderByColumn); String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
orderBy = StringUtils.toUnderScoreCase(orderBy); orderBy = StringUtils.toUnderScoreCase(orderBy);
if ("asc".equals(isAsc)) { if ("asc".equals(isAsc)) {
page.addOrder(OrderItem.asc(orderBy)); return OrderItem.asc(orderBy);
} else if ("desc".equals(isAsc)) { } else if ("desc".equals(isAsc)) {
page.addOrder(OrderItem.desc(orderBy)); return OrderItem.desc(orderBy);
} }
} }
return page; return null;
} }
public static <T, K> TableDataInfo<K> buildDataInfo(PagePlus<T, K> page) { public static <T, K> TableDataInfo<K> buildDataInfo(PagePlus<T, K> page) {
@ -129,4 +135,11 @@ public class PageUtils {
return rspData; return rspData;
} }
public static <T> TableDataInfo<T> buildDataInfo() {
TableDataInfo<T> rspData = new TableDataInfo<>();
rspData.setCode(HttpStatus.HTTP_OK);
rspData.setMsg("查询成功");
return rspData;
}
} }

View File

@ -0,0 +1,258 @@
package com.ruoyi.common.utils;
import com.google.common.collect.Lists;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* redis 工具类
*
* @author Lion Li
* @version 3.1.0 新增
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisUtils {
private static RedissonClient client = SpringUtils.getBean(RedissonClient.class);
/**
* 发布通道消息
*
* @param channelKey 通道key
* @param msg 发送数据
* @param consumer 自定义处理
*/
public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
RTopic topic = client.getTopic(channelKey);
topic.publish(msg);
consumer.accept(msg);
}
public static <T> void publish(String channelKey, T msg) {
RTopic topic = client.getTopic(channelKey);
topic.publish(msg);
}
/**
* 订阅通道接收消息
*
* @param channelKey 通道key
* @param clazz 消息类型
* @param consumer 自定义处理
*/
public static <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
RTopic topic = client.getTopic(channelKey);
topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
}
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public static <T> void setCacheObject(final String key, final T value) {
client.getBucket(key).set(value);
}
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public static <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
RBucket<T> result = client.getBucket(key);
result.set(value);
result.expire(timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功false=设置失败
*/
public static boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功false=设置失败
*/
public static boolean expire(final String key, final long timeout, final TimeUnit unit) {
RBucket rBucket = client.getBucket(key);
return rBucket.expire(timeout, unit);
}
/**
* 获得缓存的基本对象
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public static <T> T getCacheObject(final String key) {
RBucket<T> rBucket = client.getBucket(key);
return rBucket.get();
}
/**
* 删除单个对象
*
* @param key
*/
public static boolean deleteObject(final String key) {
return client.getBucket(key).delete();
}
/* */
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public static void deleteObject(final Collection collection) {
RBatch batch = client.createBatch();
collection.forEach(t -> {
batch.getBucket(t.toString()).deleteAsync();
});
batch.execute();
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public static <T> boolean setCacheList(final String key, final List<T> dataList) {
RList<T> rList = client.getList(key);
return rList.addAll(dataList);
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public static <T> List<T> getCacheList(final String key) {
RList<T> rList = client.getList(key);
return rList.readAll();
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public static <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
RSet<T> rSet = client.getSet(key);
return rSet.addAll(dataSet);
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public static <T> Set<T> getCacheSet(final String key) {
RSet<T> rSet = client.getSet(key);
return rSet.readAll();
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public static <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
RMap<String, T> rMap = client.getMap(key);
rMap.putAll(dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public static <T> Map<String, T> getCacheMap(final String key) {
RMap<String, T> rMap = client.getMap(key);
return rMap.getAll(rMap.keySet());
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value
*/
public static <T> void setCacheMapValue(final String key, final String hKey, final T value) {
RMap<String, T> rMap = client.getMap(key);
rMap.put(hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public static <T> T getCacheMapValue(final String key, final String hKey) {
RMap<String, T> rMap = client.getMap(key);
return rMap.get(hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public static <K, V> Map<K, V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
RMap<K, V> rMap = client.getMap(key);
return rMap.getAll(hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public static Collection<String> keys(final String pattern) {
Iterable<String> iterable = client.getKeys().getKeysByPattern(pattern);
return Lists.newArrayList(iterable);
}
}

View File

@ -48,12 +48,26 @@ public class ServletUtils extends ServletUtil {
return Convert.toInt(getRequest().getParameter(name), defaultValue); return Convert.toInt(getRequest().getParameter(name), defaultValue);
} }
/** /**
* 获取request * 获取Boolean参数
*/ */
public static HttpServletRequest getRequest() { public static Boolean getParameterToBool(String name) {
return getRequestAttributes().getRequest(); return Convert.toBool(getRequest().getParameter(name));
} }
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue) {
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/**
* 获取request
*/
public static HttpServletRequest getRequest() {
return getRequestAttributes().getRequest();
}
/** /**
* 获取response * 获取response

View File

@ -3,6 +3,7 @@ package com.ruoyi.common.utils.poi;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.ruoyi.common.convert.ExcelBigNumberConvert;
import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.file.FileUtils;
@ -52,6 +53,8 @@ public class ExcelUtil {
.autoCloseStream(false) .autoCloseStream(false)
// 自动适配 // 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.sheet(sheetName).doWrite(list); .sheet(sheetName).doWrite(list);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("导出Excel异常"); throw new RuntimeException("导出Excel异常");

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -2,6 +2,8 @@ package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.demo.feign.FeignTestService; import com.ruoyi.demo.feign.FeignTestService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
* *
* @author Lion Li * @author Lion Li
*/ */
@Api(value = "feign测试", tags = {"feign测试"})
@RequiredArgsConstructor(onConstructor_ = @Autowired) @RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController @RestController
@RequestMapping("/feign/test") @RequestMapping("/feign/test")
@ -21,6 +24,10 @@ public class FeignTestController {
private final FeignTestService feignTestService; private final FeignTestService feignTestService;
/**
* 搜索数据
*/
@ApiOperation("测试使用feign请求数据")
@GetMapping("/search/{wd}") @GetMapping("/search/{wd}")
public AjaxResult search(@PathVariable String wd) { public AjaxResult search(@PathVariable String wd) {
String search = feignTestService.search(wd); String search = feignTestService.search(wd);

View File

@ -1,6 +1,8 @@
package com.ruoyi.demo.controller; package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
*/ */
// 类级别 缓存统一配置 // 类级别 缓存统一配置
//@CacheConfig(cacheNames = "redissonCacheMap") //@CacheConfig(cacheNames = "redissonCacheMap")
@Api(value = "spring-cache 演示案例", tags = {"spring-cache 演示案例"})
@RequiredArgsConstructor(onConstructor_ = @Autowired) @RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController @RestController
@RequestMapping("/demo/cache") @RequestMapping("/demo/cache")
@ -33,6 +36,7 @@ public class RedisCacheController {
* *
* cacheNames 为配置文件内 groupId * cacheNames 为配置文件内 groupId
*/ */
@ApiOperation("测试 @Cacheable")
@Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") @Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test1") @GetMapping("/test1")
public AjaxResult<String> test1(String key, String value){ public AjaxResult<String> test1(String key, String value){
@ -47,6 +51,7 @@ public class RedisCacheController {
* *
* cacheNames 配置文件内 groupId * cacheNames 配置文件内 groupId
*/ */
@ApiOperation("测试 @CachePut")
@CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") @CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test2") @GetMapping("/test2")
public AjaxResult<String> test2(String key, String value){ public AjaxResult<String> test2(String key, String value){
@ -61,6 +66,7 @@ public class RedisCacheController {
* *
* cacheNames 配置文件内 groupId * cacheNames 配置文件内 groupId
*/ */
@ApiOperation("测试 @CacheEvict")
@CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") @CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
@GetMapping("/test3") @GetMapping("/test3")
public AjaxResult<String> test3(String key, String value){ public AjaxResult<String> test3(String key, String value){

View File

@ -5,6 +5,8 @@ import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.lock.executor.RedissonLockExecutor; import com.baomidou.lock.executor.RedissonLockExecutor;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
@ -20,6 +22,7 @@ import java.time.LocalTime;
* *
* @author shenxinquan * @author shenxinquan
*/ */
@Api(value = "测试分布式锁的样例", tags = {"测试分布式锁的样例"})
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/demo/redisLock") @RequestMapping("/demo/redisLock")
@ -31,6 +34,7 @@ public class RedisLockController {
/** /**
* 测试lock4j 注解 * 测试lock4j 注解
*/ */
@ApiOperation("测试lock4j 注解")
@Lock4j(keys = {"#key"}) @Lock4j(keys = {"#key"})
@GetMapping("/testLock4j") @GetMapping("/testLock4j")
public AjaxResult<String> testLock4j(String key,String value){ public AjaxResult<String> testLock4j(String key,String value){
@ -47,6 +51,7 @@ public class RedisLockController {
/** /**
* 测试lock4j 工具 * 测试lock4j 工具
*/ */
@ApiOperation("测试lock4j 工具")
@GetMapping("/testLock4jLockTemaplate") @GetMapping("/testLock4jLockTemaplate")
public AjaxResult<String> testLock4jLockTemaplate(String key,String value){ public AjaxResult<String> testLock4jLockTemaplate(String key,String value){
final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class); final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
@ -72,6 +77,7 @@ public class RedisLockController {
/** /**
* 测试spring-cache注解 * 测试spring-cache注解
*/ */
@ApiOperation("测试spring-cache注解")
@Cacheable(value = "test", key = "#key") @Cacheable(value = "test", key = "#key")
@GetMapping("/testCache") @GetMapping("/testCache")
public AjaxResult<String> testCache(String key) { public AjaxResult<String> testCache(String key) {

View File

@ -0,0 +1,42 @@
package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.RedisUtils;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Redis 发布订阅 演示案例
*
* @author Lion Li
*/
@Api(value = "Redis发布订阅 演示案例", tags = {"Redis发布订阅"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@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("/sub")
public AjaxResult<Void> sub(String key){
RedisUtils.subscribe(key, String.class, msg -> {
System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
});
return AjaxResult.success("操作成功");
}
}

View File

@ -32,10 +32,10 @@ public class TestBatchController extends BaseController {
private final ITestDemoService iTestDemoService; private final ITestDemoService iTestDemoService;
/** /**
* 新增批量方法 ( 全量覆盖填充 ) * 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大)
*/ */
@ApiOperation(value = "新增批量方法") @ApiOperation(value = "新增批量方法")
@PostMapping() @PostMapping("/add")
// @DataSource(DataSourceType.SLAVE) // @DataSource(DataSourceType.SLAVE)
public AjaxResult<Void> add() { public AjaxResult<Void> add() {
List<TestDemo> list = new ArrayList<>(); List<TestDemo> list = new ArrayList<>();
@ -45,6 +45,28 @@ public class TestBatchController extends BaseController {
return toAjax(iTestDemoService.saveAll(list) ? 1 : 0); return toAjax(iTestDemoService.saveAll(list) ? 1 : 0);
} }
/**
* 新增或更新 可完美替代 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);
}
/** /**
* 删除批量方法 * 删除批量方法
*/ */

View File

@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup; import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.domain.bo.TestDemoBo; import com.ruoyi.demo.domain.bo.TestDemoBo;
@ -48,7 +49,7 @@ public class TestDemoController extends BaseController {
@ApiOperation("查询测试单表列表") @ApiOperation("查询测试单表列表")
@PreAuthorize("@ss.hasPermi('demo:demo:list')") @PreAuthorize("@ss.hasPermi('demo:demo:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo<TestDemoVo> list(@Validated TestDemoBo bo) { public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo) {
return iTestDemoService.queryPageList(bo); return iTestDemoService.queryPageList(bo);
} }
@ -71,6 +72,10 @@ public class TestDemoController extends BaseController {
@GetMapping("/export") @GetMapping("/export")
public void export(@Validated TestDemoBo bo, HttpServletResponse response) { public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
List<TestDemoVo> list = iTestDemoService.queryList(bo); List<TestDemoVo> list = iTestDemoService.queryList(bo);
// 测试雪花id导出
// for (TestDemoVo vo : list) {
// vo.setId(1234567891234567893L);
// }
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response); ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
} }

View File

@ -2,6 +2,8 @@ package com.ruoyi.demo.controller;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -12,6 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
* *
* @author Lion Li * @author Lion Li
*/ */
@Api(value = "测试国际化控制器", tags = {"测试国际化管理"})
@RestController @RestController
@RequestMapping("/demo/i18n") @RequestMapping("/demo/i18n")
public class TestI18nController { public class TestI18nController {
@ -22,6 +25,7 @@ public class TestI18nController {
* *
* 测试使用 user.register.success * 测试使用 user.register.success
*/ */
@ApiOperation("通过code获取国际化内容")
@GetMapping() @GetMapping()
public AjaxResult<Void> get(String code) { public AjaxResult<Void> get(String code) {
return AjaxResult.success(MessageUtils.message(code)); return AjaxResult.success(MessageUtils.message(code));

View File

@ -6,6 +6,7 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup; import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.domain.bo.TestTreeBo; import com.ruoyi.demo.domain.bo.TestTreeBo;
@ -46,7 +47,7 @@ public class TestTreeController extends BaseController {
@ApiOperation("查询测试树表列表") @ApiOperation("查询测试树表列表")
@PreAuthorize("@ss.hasPermi('demo:tree:list')") @PreAuthorize("@ss.hasPermi('demo:tree:list')")
@GetMapping("/list") @GetMapping("/list")
public AjaxResult<List<TestTreeVo>> list(@Validated TestTreeBo bo) { public AjaxResult<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) {
List<TestTreeVo> list = iTestTreeService.queryList(bo); List<TestTreeVo> list = iTestTreeService.queryList(bo);
return AjaxResult.success(list); return AjaxResult.success(list);
} }

View File

@ -1,8 +1,6 @@
package com.ruoyi.demo.domain; package com.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -29,7 +27,6 @@ public class TestDemo implements Serializable {
* 主键 * 主键
*/ */
@TableId(value = "id") @TableId(value = "id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id; private Long id;
/** /**

View File

@ -26,6 +26,7 @@ public class TestDemoVo {
/** /**
* 主键 * 主键
*/ */
@ExcelProperty(value = "主键")
@ApiModelProperty("主键") @ApiModelProperty("主键")
private Long id; private Long id;

View File

@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.RequestParam;
* feign测试service * feign测试service
* 规范接口 Service 无感调用 * 规范接口 Service 无感调用
* 常量管理请求路径 更加规范 * 常量管理请求路径 更加规范
* 自定义容错处理 安全可靠 * 自定义容错处理 安全可靠 (需自行配置熔断器)
* 增加 feign 的目的为使 http 请求接口化
*
* @author Lion Li * @author Lion Li
*/ */
@FeignClient( @FeignClient(

View File

@ -10,6 +10,8 @@ import org.springframework.stereotype.Component;
* 自定义封装结构体熔断 * 自定义封装结构体熔断
* 需重写解码器 根据自定义实体 自行解析熔断 * 需重写解码器 根据自定义实体 自行解析熔断
* *
* 熔断器需要自行添加配置
*
* @see {com.ruoyi.framework.config.FeignConfig#errorDecoder()} * @see {com.ruoyi.framework.config.FeignConfig#errorDecoder()}
* @author Lion Li * @author Lion Li
*/ */

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-extend</artifactId> <artifactId>ruoyi-extend</artifactId>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-extend</artifactId> <artifactId>ruoyi-extend</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,11 +5,9 @@ import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils; import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.TokenService;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature; import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
@ -78,7 +76,7 @@ public class DataScopeAspect {
return; return;
} }
// 获取当前的用户 // 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNotNull(loginUser)) { if (StringUtils.isNotNull(loginUser)) {
SysUser currentUser = loginUser.getUser(); SysUser currentUser = loginUser.getUser();
// 如果是超级管理员则不过滤数据 // 如果是超级管理员则不过滤数据

View File

@ -5,11 +5,11 @@ import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessStatus; import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.enums.HttpMethod; import com.ruoyi.common.enums.HttpMethod;
import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.AsyncService; import com.ruoyi.framework.web.service.AsyncService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysOperLog; import com.ruoyi.system.domain.SysOperLog;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature; import org.aspectj.lang.Signature;
@ -83,7 +83,7 @@ public class LogAspect
} }
// 获取当前的用户 // 获取当前的用户
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SecurityUtils.getLoginUser();
// *========数据库日志=========*// // *========数据库日志=========*//
SysOperLog operLog = new SysOperLog(); SysOperLog operLog = new SysOperLog();

View File

@ -1,10 +1,14 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import java.awt.*; import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.*; import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import java.awt.*;
/** /**
* 验证码配置 * 验证码配置
@ -22,8 +26,9 @@ public class CaptchaConfig {
/** /**
* 圆圈干扰验证码 * 圆圈干扰验证码
*/ */
@Bean(name = "CircleCaptcha") @Lazy
public CircleCaptcha getCircleCaptcha() { @Bean
public CircleCaptcha circleCaptcha() {
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height); CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height);
captcha.setBackground(background); captcha.setBackground(background);
captcha.setFont(font); captcha.setFont(font);
@ -33,8 +38,9 @@ public class CaptchaConfig {
/** /**
* 线段干扰的验证码 * 线段干扰的验证码
*/ */
@Bean(name = "LineCaptcha") @Lazy
public LineCaptcha getLineCaptcha() { @Bean
public LineCaptcha lineCaptcha() {
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(width, height); LineCaptcha captcha = CaptchaUtil.createLineCaptcha(width, height);
captcha.setBackground(background); captcha.setBackground(background);
captcha.setFont(font); captcha.setFont(font);
@ -44,8 +50,9 @@ public class CaptchaConfig {
/** /**
* 扭曲干扰验证码 * 扭曲干扰验证码
*/ */
@Bean(name = "ShearCaptcha") @Lazy
public ShearCaptcha getShearCaptcha() { @Bean
public ShearCaptcha shearCaptcha() {
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(width, height); ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(width, height);
captcha.setBackground(background); captcha.setBackground(background);
captcha.setFont(font); captcha.setFont(font);

View File

@ -5,17 +5,18 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.framework.jackson.BigNumberSerializer; import com.ruoyi.framework.jackson.BigNumberSerializer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException; import org.springframework.boot.autoconfigure.jackson.JacksonProperties;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone; import java.util.TimeZone;
/** /**
@ -27,30 +28,23 @@ import java.util.TimeZone;
@Configuration @Configuration
public class JacksonConfig { public class JacksonConfig {
@Primary
@Bean @Bean
public BeanPostProcessor objectMapperBeanPostProcessor() { public ObjectMapper getObjectMapper(Jackson2ObjectMapperBuilder builder, JacksonProperties jacksonProperties) {
return new BeanPostProcessor() { ObjectMapper objectMapper = builder.createXmlMapper(false).build();
@Override // 全局配置序列化返回 JSON 处理
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { SimpleModule simpleModule = new SimpleModule();
if (!(bean instanceof ObjectMapper)) { simpleModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
return bean; simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
} simpleModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
ObjectMapper objectMapper = (ObjectMapper) bean; simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
// 全局配置序列化返回 JSON 处理 DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat());
SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
simpleModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE); simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE); objectMapper.registerModule(simpleModule);
simpleModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE); objectMapper.setTimeZone(TimeZone.getDefault());
simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); log.info("初始化 jackson 配置");
simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE); return objectMapper;
simpleModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
objectMapper.registerModule(simpleModule);
objectMapper.setTimeZone(TimeZone.getDefault());
JsonUtils.init(objectMapper);
log.info("初始化 jackson 配置");
return bean;
}
};
} }
} }

View File

@ -1,10 +1,10 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
@ -46,10 +46,10 @@ public class MybatisPlusConfig {
*/ */
public PaginationInnerInterceptor paginationInnerInterceptor() { public PaginationInnerInterceptor paginationInnerInterceptor() {
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
// 设置数据库类型为mysql
paginationInnerInterceptor.setDbType(DbType.MYSQL);
// 设置最大单页限制数量默认 500 -1 不受限制 // 设置最大单页限制数量默认 500 -1 不受限制
paginationInnerInterceptor.setMaxLimit(-1L); paginationInnerInterceptor.setMaxLimit(-1L);
// 分页合理化
paginationInnerInterceptor.setOverflow(true);
return paginationInnerInterceptor; return paginationInnerInterceptor;
} }
@ -104,8 +104,8 @@ public class MybatisPlusConfig {
public ISqlInjector sqlInjector() { public ISqlInjector sqlInjector() {
return new DefaultSqlInjector() { return new DefaultSqlInjector() {
@Override @Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) { public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass); List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertAll()); methodList.add(new InsertAll());
return methodList; return methodList;
} }

View File

@ -3,6 +3,7 @@ package com.ruoyi.framework.config;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.RedissonProperties; import com.ruoyi.framework.config.properties.RedissonProperties;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson; import org.redisson.Redisson;
import org.redisson.api.RedissonClient; import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec; import org.redisson.codec.JsonJacksonCodec;
@ -29,6 +30,7 @@ import java.util.Map;
* *
* @author Lion Li * @author Lion Li
*/ */
@Slf4j
@Configuration @Configuration
@EnableCaching @EnableCaching
public class RedisConfig extends CachingConfigurerSupport { public class RedisConfig extends CachingConfigurerSupport {
@ -73,7 +75,9 @@ public class RedisConfig extends CachingConfigurerSupport {
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize()) .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize()) .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval()); .setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
return Redisson.create(config); RedissonClient redissonClient = Redisson.create(config);
log.info("初始化 redis 配置");
return redissonClient;
} }
/** /**

View File

@ -1,6 +1,7 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import com.ruoyi.common.utils.Threads; import com.ruoyi.common.utils.Threads;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.framework.config.properties.ThreadPoolProperties; import com.ruoyi.framework.config.properties.ThreadPoolProperties;
import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -12,7 +13,6 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/** /**
* 线程池配置 * 线程池配置
@ -33,21 +33,7 @@ public class ThreadPoolConfig {
executor.setCorePoolSize(threadPoolProperties.getCorePoolSize()); executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
executor.setQueueCapacity(threadPoolProperties.getQueueCapacity()); executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds()); executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
RejectedExecutionHandler handler; RejectedExecutionHandler handler = ReflectUtils.newInstance(threadPoolProperties.getRejectedExecutionHandler().getClazz());
switch (threadPoolProperties.getRejectedExecutionHandler()) {
case "CallerRunsPolicy":
handler = new ThreadPoolExecutor.CallerRunsPolicy();
break;
case "DiscardOldestPolicy":
handler = new ThreadPoolExecutor.DiscardOldestPolicy();
break;
case "DiscardPolicy":
handler = new ThreadPoolExecutor.DiscardPolicy();
break;
default:
handler = new ThreadPoolExecutor.AbortPolicy();
break;
}
executor.setRejectedExecutionHandler(handler); executor.setRejectedExecutionHandler(handler);
return executor; return executor;
} }

View File

@ -1,5 +1,7 @@
package com.ruoyi.framework.config.properties; package com.ruoyi.framework.config.properties;
import com.ruoyi.common.enums.CaptchaCategory;
import com.ruoyi.common.enums.CaptchaType;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -17,12 +19,12 @@ public class CaptchaProperties {
/** /**
* 验证码类型 * 验证码类型
*/ */
private String type; private CaptchaType type;
/** /**
* 验证码类别 * 验证码类别
*/ */
private String category; private CaptchaCategory category;
/** /**
* 数字验证码位数 * 数字验证码位数

View File

@ -1,5 +1,6 @@
package com.ruoyi.framework.config.properties; package com.ruoyi.framework.config.properties;
import com.ruoyi.common.enums.ThreadPoolRejectedPolicy;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -42,6 +43,6 @@ public class ThreadPoolProperties {
/** /**
* 线程池对拒绝任务(无线程可用)的处理策略 * 线程池对拒绝任务(无线程可用)的处理策略
*/ */
private String rejectedExecutionHandler; private ThreadPoolRejectedPolicy rejectedExecutionHandler;
} }

View File

@ -4,9 +4,9 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper; import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.RepeatSubmitProperties; import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
import com.ruoyi.framework.config.properties.TokenProperties; import com.ruoyi.framework.config.properties.TokenProperties;
@ -38,7 +38,6 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
private final TokenProperties tokenProperties; private final TokenProperties tokenProperties;
private final RepeatSubmitProperties repeatSubmitProperties; private final RepeatSubmitProperties repeatSubmitProperties;
private final RedisCache redisCache;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -79,7 +78,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
// 唯一标识指定key + 消息头 // 唯一标识指定key + 消息头
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey; String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); Object sessionObj = RedisUtils.getCacheObject(cacheRepeatKey);
if (sessionObj != null) { if (sessionObj != null) {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
if (sessionMap.containsKey(url)) { if (sessionMap.containsKey(url)) {
@ -91,7 +90,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
} }
Map<String, Object> cacheMap = new HashMap<String, Object>(); Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap); cacheMap.put(url, nowDataMap);
redisCache.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS); RedisUtils.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS);
return false; return false;
} }

View File

@ -1,10 +1,9 @@
package com.ruoyi.framework.web.service; package com.ruoyi.framework.web.service;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired; import com.ruoyi.common.utils.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -28,9 +27,6 @@ public class PermissionService
private static final String PERMISSION_DELIMETER = ","; private static final String PERMISSION_DELIMETER = ",";
@Autowired
private TokenService tokenService;
/** /**
* 验证用户是否具备某权限 * 验证用户是否具备某权限
* *
@ -43,7 +39,7 @@ public class PermissionService
{ {
return false; return false;
} }
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{ {
return false; return false;
@ -74,7 +70,7 @@ public class PermissionService
{ {
return false; return false;
} }
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{ {
return false; return false;
@ -102,7 +98,7 @@ public class PermissionService
{ {
return false; return false;
} }
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{ {
return false; return false;
@ -141,7 +137,7 @@ public class PermissionService
{ {
return false; return false;
} }
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{ {
return false; return false;

View File

@ -3,13 +3,13 @@ package com.ruoyi.framework.web.service;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@ -37,9 +37,6 @@ public class SysLoginService
@Resource @Resource
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private ISysUserService userService; private ISysUserService userService;
@ -105,8 +102,8 @@ public class SysLoginService
*/ */
public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) { public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey); String captcha = RedisUtils.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey); RedisUtils.deleteObject(verifyKey);
if (captcha == null) { if (captcha == null) {
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request); asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
throw new CaptchaExpireException(); throw new CaptchaExpireException();

View File

@ -4,13 +4,9 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody; import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -30,9 +26,6 @@ public class SysRegisterService
@Autowired @Autowired
private ISysConfigService configService; private ISysConfigService configService;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private AsyncService asyncService; private AsyncService asyncService;
@ -103,8 +96,8 @@ public class SysRegisterService
public void validateCaptcha(String username, String code, String uuid) public void validateCaptcha(String username, String code, String uuid)
{ {
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String captcha = redisCache.getCacheObject(verifyKey); String captcha = RedisUtils.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey); RedisUtils.deleteObject(verifyKey);
if (captcha == null) if (captcha == null)
{ {
throw new CaptchaExpireException(); throw new CaptchaExpireException();

View File

@ -5,7 +5,7 @@ import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.http.useragent.UserAgentUtil;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.AddressUtils;
@ -35,9 +35,6 @@ public class TokenService {
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private TokenProperties tokenProperties; private TokenProperties tokenProperties;
@ -55,7 +52,7 @@ public class TokenService {
// 解析对应的权限以及用户信息 // 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid); String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey); LoginUser user = RedisUtils.getCacheObject(userKey);
return user; return user;
} catch (Exception e) { } catch (Exception e) {
@ -79,7 +76,7 @@ public class TokenService {
public void delLoginUser(String token) { public void delLoginUser(String token) {
if (StringUtils.isNotEmpty(token)) { if (StringUtils.isNotEmpty(token)) {
String userKey = getTokenKey(token); String userKey = getTokenKey(token);
redisCache.deleteObject(userKey); RedisUtils.deleteObject(userKey);
} }
} }
@ -124,7 +121,7 @@ public class TokenService {
loginUser.setExpireTime(loginUser.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE); loginUser.setExpireTime(loginUser.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE);
// 根据uuid将loginUser缓存 // 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken()); String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, tokenProperties.getExpireTime(), TimeUnit.MINUTES); RedisUtils.setCacheObject(userKey, loginUser, tokenProperties.getExpireTime(), TimeUnit.MINUTES);
} }
/** /**

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -44,6 +44,7 @@ public class GenTableColumn implements Serializable {
/** /**
* 列描述 * 列描述
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String columnComment; private String columnComment;
/** /**
@ -65,36 +66,43 @@ public class GenTableColumn implements Serializable {
/** /**
* 是否主键1是 * 是否主键1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isPk; private String isPk;
/** /**
* 是否自增1是 * 是否自增1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isIncrement; private String isIncrement;
/** /**
* 是否必填1是 * 是否必填1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isRequired; private String isRequired;
/** /**
* 是否为插入字段1是 * 是否为插入字段1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isInsert; private String isInsert;
/** /**
* 是否编辑字段1是 * 是否编辑字段1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isEdit; private String isEdit;
/** /**
* 是否列表字段1是 * 是否列表字段1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isList; private String isList;
/** /**
* 是否查询字段1是 * 是否查询字段1是
*/ */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String isQuery; private String isQuery;
/** /**

View File

@ -2,9 +2,7 @@ package com.ruoyi.generator.service;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.Constants;
import com.ruoyi.common.constant.GenConstants; import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
@ -13,6 +11,7 @@ import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.generator.domain.GenTable; import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn; import com.ruoyi.generator.domain.GenTableColumn;
@ -34,10 +33,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Arrays; import java.util.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@ -134,18 +130,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
int row = baseMapper.updateById(genTable); int row = baseMapper.updateById(genTable);
if (row > 0) { if (row > 0) {
for (GenTableColumn cenTableColumn : genTable.getColumns()) { for (GenTableColumn cenTableColumn : genTable.getColumns()) {
genTableColumnMapper.update(cenTableColumn, genTableColumnMapper.updateById(cenTableColumn);
new LambdaUpdateWrapper<GenTableColumn>()
.set(StringUtils.isBlank(cenTableColumn.getColumnComment()), GenTableColumn::getColumnComment, null)
.set(StringUtils.isBlank(cenTableColumn.getIsPk()), GenTableColumn::getIsPk, null)
.set(StringUtils.isBlank(cenTableColumn.getIsIncrement()), GenTableColumn::getIsIncrement, null)
.set(StringUtils.isBlank(cenTableColumn.getIsInsert()), GenTableColumn::getIsInsert, null)
.set(StringUtils.isBlank(cenTableColumn.getIsEdit()), GenTableColumn::getIsEdit, null)
.set(StringUtils.isBlank(cenTableColumn.getIsList()), GenTableColumn::getIsList, null)
.set(StringUtils.isBlank(cenTableColumn.getIsQuery()), GenTableColumn::getIsQuery, null)
.set(StringUtils.isBlank(cenTableColumn.getIsRequired()), GenTableColumn::getIsRequired, null)
.set(StringUtils.isBlank(cenTableColumn.getDictType()), GenTableColumn::getDictType, "")
.eq(GenTableColumn::getColumnId,cenTableColumn.getColumnId()));
} }
} }
} }
@ -178,13 +163,17 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
String tableName = table.getTableName(); String tableName = table.getTableName();
GenUtils.initTable(table, operName); GenUtils.initTable(table, operName);
int row = baseMapper.insert(table); int row = baseMapper.insert(table);
if (row > 0) { if (row > 0) {
// 保存列信息 // 保存列信息
List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
for (GenTableColumn column : genTableColumns) { List<GenTableColumn> saveColumns = new ArrayList<>();
GenUtils.initColumnField(column, table); for (GenTableColumn column : genTableColumns) {
genTableColumnMapper.insert(column); GenUtils.initColumnField(column, table);
} saveColumns.add(column);
}
if (CollUtil.isNotEmpty(saveColumns)) {
genTableColumnMapper.insertAll(saveColumns);
}
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -292,12 +281,16 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
} }
List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
dbTableColumns.forEach(column -> { List<GenTableColumn> saveColumns = new ArrayList<>();
if (!tableColumnNames.contains(column.getColumnName())) { dbTableColumns.forEach(column -> {
GenUtils.initColumnField(column, table); if (!tableColumnNames.contains(column.getColumnName())) {
genTableColumnMapper.insert(column); GenUtils.initColumnField(column, table);
saveColumns.add(column);
} }
}); });
if (CollUtil.isNotEmpty(saveColumns)) {
genTableColumnMapper.insertAll(saveColumns);
}
List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(delColumns)) { if (CollUtil.isNotEmpty(delColumns)) {

View File

@ -164,9 +164,10 @@ public class GenUtils
*/ */
public static String getBusinessName(String tableName) public static String getBusinessName(String tableName)
{ {
int lastIndex = tableName.lastIndexOf("_"); int firstIndex = tableName.indexOf("_");
int nameLength = tableName.length(); int nameLength = tableName.length();
String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength); String businessName = StringUtils.substring(tableName, firstIndex + 1, nameLength);
businessName = StringUtils.toCamelCase(businessName);
return businessName; return businessName;
} }

View File

@ -92,6 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="genTable.params.endTime != null and genTable.params.endTime != ''"><!-- 结束时间检索 --> <if test="genTable.params.endTime != null and genTable.params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{genTable.params.endTime},'%y%m%d') AND date_format(create_time,'%y%m%d') &lt;= date_format(#{genTable.params.endTime},'%y%m%d')
</if> </if>
order by create_time desc
</select> </select>
@ -130,6 +131,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d') AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if> </if>
order by create_time desc
</select> </select>
<select id="selectDbTableListByNames" resultMap="GenTableResult"> <select id="selectDbTableListByNames" resultMap="GenTableResult">

View File

@ -17,6 +17,7 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup; import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import ${packageName}.domain.vo.${ClassName}Vo; import ${packageName}.domain.vo.${ClassName}Vo;
@ -51,11 +52,11 @@ public class ${ClassName}Controller extends BaseController {
@PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')") @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
@GetMapping("/list") @GetMapping("/list")
#if($table.crud || $table.sub) #if($table.crud || $table.sub)
public TableDataInfo<${ClassName}Vo> list(@Validated ${ClassName}Bo bo) { public TableDataInfo<${ClassName}Vo> list(@Validated(QueryGroup.class) ${ClassName}Bo bo) {
return i${ClassName}Service.queryPageList(bo); return i${ClassName}Service.queryPageList(bo);
} }
#elseif($table.tree) #elseif($table.tree)
public AjaxResult<List<${ClassName}Vo>> list(@Validated ${ClassName}Bo bo) { public AjaxResult<List<${ClassName}Vo>> list(@Validated(QueryGroup.class) ${ClassName}Bo bo) {
List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo); List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
return AjaxResult.success(list); return AjaxResult.success(list);
} }

View File

@ -106,7 +106,11 @@
</template> </template>
</el-table-column> </el-table-column>
#elseif($column.list && $column.dictType && "" != $column.dictType) #elseif($column.list && $column.dictType && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" /> <el-table-column label="${comment}" align="center" prop="${javaField}">
<template slot-scope="scope">
<dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
</template>
</el-table-column>
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
#if(${foreach.index} == 1) #if(${foreach.index} == 1)
<el-table-column label="${comment}" prop="${javaField}" /> <el-table-column label="${comment}" prop="${javaField}" />
@ -378,20 +382,6 @@ export default {
this.${businessName}Options.push(data); this.${businessName}Options.push(data);
}); });
}, },
#foreach ($column in $columns)
#if(${column.dictType} && ${column.dictType} != '')
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
// $comment字典翻译
${column.javaField}Format(row, column) {
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
},
#end
#end
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false; this.open = false;

View File

@ -135,7 +135,11 @@
</template> </template>
</el-table-column> </el-table-column>
#elseif($column.list && $column.dictType && "" != $column.dictType) #elseif($column.list && $column.dictType && "" != $column.dictType)
<el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" /> <el-table-column label="${comment}" align="center" prop="${javaField}">
<template slot-scope="scope">
<dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
</template>
</el-table-column>
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
<el-table-column label="${comment}" align="center" prop="${javaField}" /> <el-table-column label="${comment}" align="center" prop="${javaField}" />
#end #end
@ -308,7 +312,6 @@
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
import { downLoadExcel } from "@/utils/download";
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@ -427,20 +430,6 @@ export default {
this.loading = false; this.loading = false;
}); });
}, },
#foreach ($column in $columns)
#if(${column.dictType} && ${column.dictType} != '')
#set($parentheseIndex=$column.columnComment.indexOf(""))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
// $comment字典翻译
${column.javaField}Format(row, column) {
return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
},
#end
#end
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false; this.open = false;
@ -601,7 +590,7 @@ export default {
#end #end
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
downLoadExcel('/${moduleName}/${businessName}/export', this.queryParams); this.downLoadExcel('/${moduleName}/${businessName}/export', this.queryParams);
} }
} }
}; };

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -1,19 +1,18 @@
package com.ruoyi.oss.factory; package com.ruoyi.oss.factory;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils; import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.oss.constant.CloudConstant; import com.ruoyi.oss.constant.CloudConstant;
import com.ruoyi.oss.enumd.CloudServiceEnumd; import com.ruoyi.oss.enumd.CloudServiceEnumd;
import com.ruoyi.oss.exception.OssException; import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.CloudStorageProperties; import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.ICloudStorageStrategy; import com.ruoyi.oss.service.ICloudStorageStrategy;
import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy; import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -22,12 +21,14 @@ import java.util.concurrent.ConcurrentHashMap;
* *
* @author Lion Li * @author Lion Li
*/ */
@Slf4j
public class OssFactory { public class OssFactory {
private static RedisCache redisCache;
static { static {
OssFactory.redisCache = SpringUtils.getBean(RedisCache.class); RedisUtils.subscribe(CloudConstant.CACHE_CONFIG_KEY, String.class, msg -> {
refreshService(msg);
log.info("订阅刷新OSS配置 => " + msg);
});
} }
/** /**
@ -35,17 +36,12 @@ public class OssFactory {
*/ */
private static final Map<String, ICloudStorageStrategy> SERVICES = new ConcurrentHashMap<>(); private static final Map<String, ICloudStorageStrategy> SERVICES = new ConcurrentHashMap<>();
/**
* 服务配置更新时间缓存
*/
private static final Map<String, Date> SERVICES_UPDATE_TIME = new ConcurrentHashMap<>();
/** /**
* 获取默认实例 * 获取默认实例
*/ */
public static ICloudStorageStrategy instance() { public static ICloudStorageStrategy instance() {
// 获取redis 默认类型 // 获取redis 默认类型
String type = Convert.toStr(redisCache.getCacheObject(CloudConstant.CACHE_CONFIG_KEY)); String type = Convert.toStr(RedisUtils.getCacheObject(CloudConstant.CACHE_CONFIG_KEY));
if (StringUtils.isEmpty(type)) { if (StringUtils.isEmpty(type)) {
throw new OssException("文件存储服务类型无法找到!"); throw new OssException("文件存储服务类型无法找到!");
} }
@ -57,23 +53,23 @@ public class OssFactory {
*/ */
public static ICloudStorageStrategy instance(String type) { public static ICloudStorageStrategy instance(String type) {
ICloudStorageStrategy service = SERVICES.get(type); ICloudStorageStrategy service = SERVICES.get(type);
Date oldDate = SERVICES_UPDATE_TIME.get(type); if (service == null) {
Object json = redisCache.getCacheObject(CloudConstant.SYS_OSS_KEY + type); refreshService(type);
service = SERVICES.get(type);
}
return service;
}
private static void refreshService(String type) {
Object json = RedisUtils.getCacheObject(CloudConstant.SYS_OSS_KEY + type);
CloudStorageProperties properties = JsonUtils.parseObject(json.toString(), CloudStorageProperties.class); CloudStorageProperties properties = JsonUtils.parseObject(json.toString(), CloudStorageProperties.class);
if (properties == null) { if (properties == null) {
throw new OssException("系统异常, '" + type + "'配置信息不存在!"); throw new OssException("系统异常, '" + type + "'配置信息不存在!");
} }
Date nowDate = properties.getUpdateTime();
// 服务存在并更新时间相同则返回(使用更新时间确保配置最终一致性)
if (service != null && oldDate.equals(nowDate)) {
return service;
}
// 获取redis配置信息 创建对象 并缓存 // 获取redis配置信息 创建对象 并缓存
service = (ICloudStorageStrategy) ReflectUtils.newInstance(CloudServiceEnumd.getServiceClass(type)); ICloudStorageStrategy service = (ICloudStorageStrategy) ReflectUtils.newInstance(CloudServiceEnumd.getServiceClass(type));
((AbstractCloudStorageStrategy)service).init(properties); ((AbstractCloudStorageStrategy)service).init(properties);
SERVICES.put(type, service); SERVICES.put(type, service);
SERVICES_UPDATE_TIME.put(type, nowDate);
return service;
} }
} }

View File

@ -1,15 +1,14 @@
package com.ruoyi.oss.service.abstractd; package com.ruoyi.oss.service.abstractd;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oss.entity.UploadResult; import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.properties.CloudStorageProperties; import com.ruoyi.oss.properties.CloudStorageProperties;
import com.ruoyi.oss.service.ICloudStorageStrategy; import com.ruoyi.oss.service.ICloudStorageStrategy;
import java.io.InputStream; import java.io.InputStream;
import java.util.Date;
/** /**
* 云存储策略(支持七牛阿里云腾讯云minio) * 云存储策略(支持七牛阿里云腾讯云minio)
@ -33,7 +32,7 @@ public abstract class AbstractCloudStorageStrategy implements ICloudStorageStrat
// 生成uuid // 生成uuid
String uuid = IdUtil.fastSimpleUUID(); String uuid = IdUtil.fastSimpleUUID();
// 文件路径 // 文件路径
String path = DateUtil.format(new Date(), "yyyyMMdd") + "/" + uuid; String path = DateUtils.datePath() + "/" + uuid;
if (StringUtils.isNotBlank(prefix)) { if (StringUtils.isNotBlank(prefix)) {
path = prefix + "/" + path; path = prefix + "/" + path;
} }

View File

@ -36,7 +36,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration); client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
createBucket(); createBucket();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("阿里云存储配置错误! 请检查系统配置!"); throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
} }
} }
@ -51,7 +51,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
client.createBucket(createBucketRequest); client.createBucket(createBucketRequest);
} catch (Exception e) { } catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对阿里云配置信息"); throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]");
} }
} }
@ -72,7 +72,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
metadata.setContentType(contentType); metadata.setContentType(contentType);
client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata)); client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请检查阿里云配置信息"); throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
} }
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path); return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
} }
@ -83,7 +83,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
try { try {
client.deleteObject(properties.getBucketName(), path); client.deleteObject(properties.getBucketName(), path);
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请检查阿里云配置信息"); throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
} }
} }

View File

@ -32,7 +32,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
.build(); .build();
createBucket(); createBucket();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("Minio存储配置错误! 请检查系统配置!"); throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
} }
} }
@ -51,7 +51,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
.config(getPolicy(bucketName, PolicyType.READ)) .config(getPolicy(bucketName, PolicyType.READ))
.build()); .build());
} catch (Exception e) { } catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对Minio配置信息"); throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]");
} }
} }
@ -75,7 +75,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
.stream(inputStream, inputStream.available(), -1) .stream(inputStream, inputStream.available(), -1)
.build()); .build());
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败请核对Minio配置信息"); throw new OssException("上传文件失败请核对Minio配置信息:[" + e.getMessage() + "]");
} }
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path); return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
} }
@ -95,7 +95,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
@Override @Override
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
return upload(data, getPath("", suffix), contentType); return upload(data, getPath(properties.getPrefix(), suffix), contentType);
} }
@Override @Override

View File

@ -44,7 +44,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
client = new COSClient(credentials, clientConfig); client = new COSClient(credentials, clientConfig);
createBucket(); createBucket();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("腾讯云存储配置错误! 请检查系统配置!"); throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
} }
} }
@ -59,7 +59,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead); createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
client.createBucket(createBucketRequest); client.createBucket(createBucketRequest);
} catch (Exception e) { } catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对腾讯云配置信息"); throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]");
} }
} }
@ -80,7 +80,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
metadata.setContentType(contentType); metadata.setContentType(contentType);
client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata)); client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请检查腾讯云配置信息"); throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]");
} }
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path); return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
} }
@ -91,7 +91,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
try { try {
client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path)); client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path));
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请检腾讯云查配置信息"); throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]");
} }
} }

View File

@ -44,7 +44,7 @@ public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
bucketManager.createBucket(bucketName, properties.getRegion()); bucketManager.createBucket(bucketName, properties.getRegion());
} }
} catch (Exception e) { } catch (Exception e) {
throw new OssException("七牛云存储配置错误! 请检查系统配置!"); throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
} }
} }
@ -57,7 +57,7 @@ public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
} }
bucketManager.createBucket(bucketName, properties.getRegion()); bucketManager.createBucket(bucketName, properties.getRegion());
} catch (Exception e) { } catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对七牛云配置信息"); throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]");
} }
} }
@ -74,7 +74,7 @@ public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
throw new RuntimeException("上传七牛出错:" + res.toString()); throw new RuntimeException("上传七牛出错:" + res.toString());
} }
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请核对七牛配置信息"); throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]");
} }
return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path); return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -80,6 +80,10 @@ public class SysJobController extends BaseController
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
} }
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
{
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{ {
return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用"); return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
@ -104,6 +108,10 @@ public class SysJobController extends BaseController
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
} }
else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
{
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
}
else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
{ {
return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用"); return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");

View File

@ -87,7 +87,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 * @param job 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public int pauseJob(SysJob job) throws SchedulerException { public int pauseJob(SysJob job) throws SchedulerException {
Long jobId = job.getJobId(); Long jobId = job.getJobId();
String jobGroup = job.getJobGroup(); String jobGroup = job.getJobGroup();
@ -105,7 +105,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 * @param job 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public int resumeJob(SysJob job) throws SchedulerException { public int resumeJob(SysJob job) throws SchedulerException {
Long jobId = job.getJobId(); Long jobId = job.getJobId();
String jobGroup = job.getJobGroup(); String jobGroup = job.getJobGroup();
@ -123,7 +123,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 * @param job 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public int deleteJob(SysJob job) throws SchedulerException { public int deleteJob(SysJob job) throws SchedulerException {
Long jobId = job.getJobId(); Long jobId = job.getJobId();
String jobGroup = job.getJobGroup(); String jobGroup = job.getJobGroup();
@ -141,7 +141,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @return 结果 * @return 结果
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public void deleteJobByIds(Long[] jobIds) throws SchedulerException { public void deleteJobByIds(Long[] jobIds) throws SchedulerException {
for (Long jobId : jobIds) { for (Long jobId : jobIds) {
SysJob job = getById(jobId); SysJob job = getById(jobId);
@ -155,7 +155,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 * @param job 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public int changeStatus(SysJob job) throws SchedulerException { public int changeStatus(SysJob job) throws SchedulerException {
int rows = 0; int rows = 0;
String status = job.getStatus(); String status = job.getStatus();
@ -173,7 +173,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 * @param job 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public void run(SysJob job) throws SchedulerException { public void run(SysJob job) throws SchedulerException {
Long jobId = job.getJobId(); Long jobId = job.getJobId();
String jobGroup = job.getJobGroup(); String jobGroup = job.getJobGroup();
@ -190,7 +190,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 调度信息 * @param job 调度信息 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public int insertJob(SysJob job) throws SchedulerException, TaskException { public int insertJob(SysJob job) throws SchedulerException, TaskException {
job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
int rows = baseMapper.insert(job); int rows = baseMapper.insert(job);
@ -206,7 +206,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
* @param job 调度信息 * @param job 调度信息
*/ */
@Override @Override
@Transactional @Transactional(rollbackFor = Exception.class)
public int updateJob(SysJob job) throws SchedulerException, TaskException { public int updateJob(SysJob job) throws SchedulerException, TaskException {
SysJob properties = selectJobById(job.getJobId()); SysJob properties = selectJobById(job.getJobId());
int rows = baseMapper.updateById(job); int rows = baseMapper.updateById(job);

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>ruoyi-vue-plus</artifactId> <artifactId>ruoyi-vue-plus</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.0.0</version> <version>3.1.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -58,7 +58,7 @@ public interface ISysDeptService extends IService<SysDept> {
* @param deptId 部门ID * @param deptId 部门ID
* @return 子部门数 * @return 子部门数
*/ */
public int selectNormalChildrenDeptById(Long deptId); public long selectNormalChildrenDeptById(Long deptId);
/** /**
* 是否存在部门子节点 * 是否存在部门子节点
@ -84,6 +84,13 @@ public interface ISysDeptService extends IService<SysDept> {
*/ */
public String checkDeptNameUnique(SysDept dept); public String checkDeptNameUnique(SysDept dept);
/**
* 校验部门是否有数据权限
*
* @param deptId 部门id
*/
public void checkDeptDataScope(Long deptId);
/** /**
* 新增保存部门信息 * 新增保存部门信息
* *

View File

@ -69,7 +69,7 @@ public interface ISysPostService extends IService<SysPost> {
* @param postId 岗位ID * @param postId 岗位ID
* @return 结果 * @return 结果
*/ */
public int countUserPostById(Long postId); public long countUserPostById(Long postId);
/** /**
* 删除岗位信息 * 删除岗位信息

View File

@ -88,13 +88,20 @@ public interface ISysRoleService extends IService<SysRole> {
*/ */
public void checkRoleAllowed(SysRole role); public void checkRoleAllowed(SysRole role);
/**
* 校验角色是否有数据权限
*
* @param roleId 角色id
*/
public void checkRoleDataScope(Long roleId);
/** /**
* 通过角色ID查询角色使用数量 * 通过角色ID查询角色使用数量
* *
* @param roleId 角色ID * @param roleId 角色ID
* @return 结果 * @return 结果
*/ */
public int countUserRoleByRoleId(Long roleId); public long countUserRoleByRoleId(Long roleId);
/** /**
* 新增保存角色信息 * 新增保存角色信息

View File

@ -103,6 +103,13 @@ public interface ISysUserService extends IService<SysUser> {
*/ */
public void checkUserAllowed(SysUser user); public void checkUserAllowed(SysUser user);
/**
* 校验用户是否有数据权限
*
* @param userId 用户id
*/
public void checkUserDataScope(Long userId);
/** /**
* 新增用户信息 * 新增用户信息
* *

View File

@ -1,21 +1,20 @@
package com.ruoyi.system.service.impl; package com.ruoyi.system.service.impl;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -32,9 +31,6 @@ import java.util.Map;
@Service @Service
public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysConfig, SysConfig> implements ISysConfigService { public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysConfig, SysConfig> implements ISysConfigService {
@Autowired
private RedisCache redisCache;
/** /**
* 项目启动时初始化参数到缓存 * 项目启动时初始化参数到缓存
*/ */
@ -79,14 +75,14 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
*/ */
@Override @Override
public String selectConfigByKey(String configKey) { public String selectConfigByKey(String configKey) {
String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey))); String configValue = Convert.toStr(RedisUtils.getCacheObject(getCacheKey(configKey)));
if (StringUtils.isNotEmpty(configValue)) { if (StringUtils.isNotEmpty(configValue)) {
return configValue; return configValue;
} }
SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>() SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
.eq(SysConfig::getConfigKey, configKey)); .eq(SysConfig::getConfigKey, configKey));
if (StringUtils.isNotNull(retConfig)) { if (StringUtils.isNotNull(retConfig)) {
redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); RedisUtils.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
return retConfig.getConfigValue(); return retConfig.getConfigValue();
} }
return StringUtils.EMPTY; return StringUtils.EMPTY;
@ -138,7 +134,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
public int insertConfig(SysConfig config) { public int insertConfig(SysConfig config) {
int row = baseMapper.insert(config); int row = baseMapper.insert(config);
if (row > 0) { if (row > 0) {
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
} }
return row; return row;
} }
@ -153,7 +149,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
public int updateConfig(SysConfig config) { public int updateConfig(SysConfig config) {
int row = baseMapper.updateById(config); int row = baseMapper.updateById(config);
if (row > 0) { if (row > 0) {
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
} }
return row; return row;
} }
@ -171,7 +167,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
} }
redisCache.deleteObject(getCacheKey(config.getConfigKey())); RedisUtils.deleteObject(getCacheKey(config.getConfigKey()));
} }
baseMapper.deleteBatchIds(Arrays.asList(configIds)); baseMapper.deleteBatchIds(Arrays.asList(configIds));
} }
@ -183,7 +179,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
public void loadingConfigCache() { public void loadingConfigCache() {
List<SysConfig> configsList = selectConfigList(new SysConfig()); List<SysConfig> configsList = selectConfigList(new SysConfig());
for (SysConfig config : configsList) { for (SysConfig config : configsList) {
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
} }
} }
@ -192,8 +188,8 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
*/ */
@Override @Override
public void clearConfigCache() { public void clearConfigCache() {
Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*"); Collection<String> keys = RedisUtils.keys(Constants.SYS_CONFIG_KEY + "*");
redisCache.deleteObject(keys); RedisUtils.deleteObject(keys);
} }
/** /**

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