Merge remote-tracking branch 'origin/dev' into satoken
# Conflicts: # pom.xml # ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java # ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java # ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java # ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
This commit is contained in:
commit
6f6a3566ac
@ -14,6 +14,8 @@ RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼
|
|||||||
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 当前框架 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
|
| 当前框架 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
|
||||||
|
| satoken分支 | RuoYi-Vue-Plus-satoken | [satoken分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/) | 使用satoken重构权限鉴权(仅供学习不推荐上生产) |
|
||||||
|
| 单体分支 | RuoYi-Vue-Plus-fast | [fast分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/) | 单体应用结构 |
|
||||||
| 原框架 | RuoYi-Vue | [RuoYi-Vue官网](http://ruoyi.vip/) | 定期同步需要的功能 |
|
| 原框架 | RuoYi-Vue | [RuoYi-Vue官网](http://ruoyi.vip/) | 定期同步需要的功能 |
|
||||||
| 前端开发框架 | Vue、Element UI | [Element UI官网](https://element.eleme.cn/#/zh-CN) | |
|
| 前端开发框架 | Vue、Element UI | [Element UI官网](https://element.eleme.cn/#/zh-CN) | |
|
||||||
| 后端开发框架 | SpringBoot | [SpringBoot官网](https://spring.io/projects/spring-boot/#learn) | |
|
| 后端开发框架 | SpringBoot | [SpringBoot官网](https://spring.io/projects/spring-boot/#learn) | |
|
||||||
@ -69,6 +71,7 @@ RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼
|
|||||||
* 同步升级 RuoYi-Vue
|
* 同步升级 RuoYi-Vue
|
||||||
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
|
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
|
||||||
* 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
|
* 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
|
||||||
|
* satoken 分支 [RuoYi-Vue-Plus-satoken](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/)
|
||||||
* 用户扩展项目 [扩展项目列表](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
|
* 用户扩展项目 [扩展项目列表](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
|
||||||
|
|
||||||
## 加群与捐献
|
## 加群与捐献
|
||||||
|
8
pom.xml
8
pom.xml
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi-vue-plus.version>3.1.0</ruoyi-vue-plus.version>
|
<ruoyi-vue-plus.version>3.1.0</ruoyi-vue-plus.version>
|
||||||
<spring-boot.version>2.5.4</spring-boot.version>
|
<spring-boot.version>2.5.5</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>
|
||||||
@ -26,14 +26,14 @@
|
|||||||
<easyexcel.version>2.2.11</easyexcel.version>
|
<easyexcel.version>2.2.11</easyexcel.version>
|
||||||
<velocity.version>1.7</velocity.version>
|
<velocity.version>1.7</velocity.version>
|
||||||
<satoken.version>1.26.0</satoken.version>
|
<satoken.version>1.26.0</satoken.version>
|
||||||
<mybatis-plus.version>3.4.3.3</mybatis-plus.version>
|
<mybatis-plus.version>3.4.3.4</mybatis-plus.version>
|
||||||
<p6spy.version>3.9.1</p6spy.version>
|
<p6spy.version>3.9.1</p6spy.version>
|
||||||
<hutool.version>5.7.13</hutool.version>
|
<hutool.version>5.7.13</hutool.version>
|
||||||
<feign.version>3.0.3</feign.version>
|
<feign.version>3.0.3</feign.version>
|
||||||
<feign-okhttp.version>11.6</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.1</spring-boot-admin.version>
|
<spring-boot-admin.version>2.5.1</spring-boot-admin.version>
|
||||||
<redisson.version>3.16.2</redisson.version>
|
<redisson.version>3.16.3</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>
|
||||||
|
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<!-- OSS 配置 -->
|
<!-- OSS 配置 -->
|
||||||
<qiniu.version>7.8.0</qiniu.version>
|
<qiniu.version>7.8.0</qiniu.version>
|
||||||
<aliyun.oss.version>3.13.1</aliyun.oss.version>
|
<aliyun.oss.version>3.13.1</aliyun.oss.version>
|
||||||
<qcloud.cos.version>5.6.51</qcloud.cos.version>
|
<qcloud.cos.version>5.6.55</qcloud.cos.version>
|
||||||
<minio.version>8.3.0</minio.version>
|
<minio.version>8.3.0</minio.version>
|
||||||
|
|
||||||
<!-- docker 配置 -->
|
<!-- docker 配置 -->
|
||||||
|
@ -122,6 +122,28 @@ sa-token:
|
|||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
|
||||||
|
# security配置
|
||||||
|
security:
|
||||||
|
# 登出路径
|
||||||
|
logout-url: /logout
|
||||||
|
# 匿名路径
|
||||||
|
anonymous:
|
||||||
|
- /login
|
||||||
|
- /register
|
||||||
|
- /captchaImage
|
||||||
|
# swagger 文档配置
|
||||||
|
- /doc.html
|
||||||
|
- /swagger-resources/**
|
||||||
|
- /webjars/**
|
||||||
|
- /*/api-docs
|
||||||
|
# druid 监控配置
|
||||||
|
- /druid/**
|
||||||
|
# actuator 监控配置
|
||||||
|
- /actuator
|
||||||
|
- /actuator/**
|
||||||
|
# 用户放行
|
||||||
|
permit-all:
|
||||||
|
|
||||||
# 重复提交
|
# 重复提交
|
||||||
repeat-submit:
|
repeat-submit:
|
||||||
# 全局间隔时间(毫秒)
|
# 全局间隔时间(毫秒)
|
||||||
@ -237,6 +259,11 @@ swagger:
|
|||||||
name: Lion Li
|
name: Lion Li
|
||||||
email: crazylionli@163.com
|
email: crazylionli@163.com
|
||||||
url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
|
url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
|
||||||
|
groups:
|
||||||
|
- name: 演示案例
|
||||||
|
basePackage: com.ruoyi.demo
|
||||||
|
- name: 系统模块
|
||||||
|
basePackage: com.ruoyi.admin
|
||||||
|
|
||||||
# 防止XSS攻击
|
# 防止XSS攻击
|
||||||
xss:
|
xss:
|
||||||
|
@ -1,260 +0,0 @@
|
|||||||
package com.ruoyi.common.core.redis;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.redisson.api.*;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* spring redis 工具类
|
|
||||||
*
|
|
||||||
* @author shenxinquan
|
|
||||||
* @see com.ruoyi.common.utils.RedisUtils
|
|
||||||
* @deprecated 3.2.0 删除此类
|
|
||||||
**/
|
|
||||||
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
|
||||||
@Component
|
|
||||||
@Deprecated
|
|
||||||
public class RedisCache {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存基本的对象,Integer、String、实体类等
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @param value 缓存的值
|
|
||||||
*/
|
|
||||||
public <T> void setCacheObject(final String key, final T value) {
|
|
||||||
redissonClient.getBucket(key).set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存基本的对象,Integer、String、实体类等
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @param value 缓存的值
|
|
||||||
* @param timeout 时间
|
|
||||||
* @param timeUnit 时间颗粒度
|
|
||||||
*/
|
|
||||||
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
|
|
||||||
RBucket<T> result = redissonClient.getBucket(key);
|
|
||||||
result.set(value);
|
|
||||||
result.expire(timeout, timeUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置有效时间
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param timeout 超时时间
|
|
||||||
* @return true=设置成功;false=设置失败
|
|
||||||
*/
|
|
||||||
public 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 boolean expire(final String key, final long timeout, final TimeUnit unit) {
|
|
||||||
RBucket rBucket = redissonClient.getBucket(key);
|
|
||||||
return rBucket.expire(timeout, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的基本对象。
|
|
||||||
*
|
|
||||||
* @param key 缓存键值
|
|
||||||
* @return 缓存键值对应的数据
|
|
||||||
*/
|
|
||||||
public <T> T getCacheObject(final String key) {
|
|
||||||
RBucket<T> rBucket = redissonClient.getBucket(key);
|
|
||||||
return rBucket.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除单个对象
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
public boolean deleteObject(final String key) {
|
|
||||||
return redissonClient.getBucket(key).delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除集合对象
|
|
||||||
*
|
|
||||||
* @param collection 多个对象
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public void deleteObject(final Collection collection) {
|
|
||||||
RBatch batch = redissonClient.createBatch();
|
|
||||||
collection.forEach(t->{
|
|
||||||
batch.getBucket(t.toString()).deleteAsync();
|
|
||||||
});
|
|
||||||
batch.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存List数据
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @param dataList 待缓存的List数据
|
|
||||||
* @return 缓存的对象
|
|
||||||
*/
|
|
||||||
public <T> boolean setCacheList(final String key, final List<T> dataList) {
|
|
||||||
RList<T> rList = redissonClient.getList(key);
|
|
||||||
return rList.addAll(dataList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的list对象
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @return 缓存键值对应的数据
|
|
||||||
*/
|
|
||||||
public <T> List<T> getCacheList(final String key) {
|
|
||||||
RList<T> rList = redissonClient.getList(key);
|
|
||||||
return rList.readAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存Set
|
|
||||||
*
|
|
||||||
* @param key 缓存键值
|
|
||||||
* @param dataSet 缓存的数据
|
|
||||||
* @return 缓存数据的对象
|
|
||||||
*/
|
|
||||||
public <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
|
|
||||||
RSet<T> rSet = redissonClient.getSet(key);
|
|
||||||
return rSet.addAll(dataSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的set
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public <T> Set<T> getCacheSet(final String key) {
|
|
||||||
RSet<T> rSet = redissonClient.getSet(key);
|
|
||||||
return rSet.readAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存Map
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @param dataMap
|
|
||||||
*/
|
|
||||||
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
|
|
||||||
if (dataMap != null) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
rMap.putAll(dataMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的Map
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public <T> Map<String, T> getCacheMap(final String key) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
return rMap.getAll(rMap.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 往Hash中存入数据
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param hKey Hash键
|
|
||||||
* @param value 值
|
|
||||||
*/
|
|
||||||
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
rMap.put(hKey, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取Hash中的数据
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param hKey Hash键
|
|
||||||
* @return Hash中的对象
|
|
||||||
*/
|
|
||||||
public <T> T getCacheMapValue(final String key, final String hKey) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
return rMap.get(hKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取多个Hash中的数据
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param hKeys Hash键集合
|
|
||||||
* @return Hash对象集合
|
|
||||||
*/
|
|
||||||
public <K,V> Map<K,V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
|
|
||||||
RMap<K,V> rMap = redissonClient.getMap(key);
|
|
||||||
return rMap.getAll(hKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的基本对象列表
|
|
||||||
*
|
|
||||||
* @param pattern 字符串前缀
|
|
||||||
* @return 对象列表
|
|
||||||
*/
|
|
||||||
public Collection<String> keys(final String pattern) {
|
|
||||||
Iterable<String> iterable = redissonClient.getKeys().getKeysByPattern(pattern);
|
|
||||||
return Lists.newArrayList(iterable);
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,6 +27,9 @@ public class AddressUtils {
|
|||||||
|
|
||||||
public static String getRealAddressByIP(String ip) {
|
public static String getRealAddressByIP(String ip) {
|
||||||
String address = UNKNOWN;
|
String address = UNKNOWN;
|
||||||
|
if (StringUtils.isBlank(ip)){
|
||||||
|
return address;
|
||||||
|
}
|
||||||
// 内网不查询
|
// 内网不查询
|
||||||
ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
|
ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
|
||||||
if (NetUtil.isInnerIP(ip)) {
|
if (NetUtil.isInnerIP(ip)) {
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package com.ruoyi.framework.config;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务相关配置
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class ServerConfig
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
|
|
||||||
*
|
|
||||||
* @return 服务地址
|
|
||||||
*/
|
|
||||||
public String getUrl()
|
|
||||||
{
|
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
|
||||||
return getDomain(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDomain(HttpServletRequest request)
|
|
||||||
{
|
|
||||||
StringBuffer url = request.getRequestURL();
|
|
||||||
String contextPath = request.getServletContext().getContextPath();
|
|
||||||
return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,12 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||||
|
import com.ruoyi.common.properties.TokenProperties;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.framework.config.properties.SwaggerProperties;
|
import com.ruoyi.framework.config.properties.SwaggerProperties;
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import io.swagger.models.auth.In;
|
import io.swagger.models.auth.In;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import springfox.documentation.builders.PathSelectors;
|
||||||
@ -15,6 +16,7 @@ import springfox.documentation.spi.DocumentationType;
|
|||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -30,28 +32,37 @@ public class SwaggerConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SwaggerProperties swaggerProperties;
|
private SwaggerProperties swaggerProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TokenProperties tokenProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建API
|
* 创建API
|
||||||
*/
|
*/
|
||||||
@Bean
|
@PostConstruct
|
||||||
public Docket createRestApi() {
|
public void createRestApi() {
|
||||||
return new Docket(DocumentationType.OAS_30)
|
for (SwaggerProperties.Groups group : swaggerProperties.getGroups()) {
|
||||||
|
String basePackage = group.getBasePackage();
|
||||||
|
Docket docket = new Docket(DocumentationType.OAS_30)
|
||||||
.enable(swaggerProperties.getEnabled())
|
.enable(swaggerProperties.getEnabled())
|
||||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||||
.apiInfo(apiInfo())
|
.apiInfo(apiInfo())
|
||||||
// 设置哪些接口暴露给Swagger展示
|
// 设置哪些接口暴露给Swagger展示
|
||||||
.select()
|
.select()
|
||||||
// 扫描所有有注解的api,用这种方式更灵活
|
// 扫描所有有注解的api,用这种方式更灵活
|
||||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
//.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||||
// 扫描指定包中的swagger注解
|
// 扫描指定包中的swagger注解
|
||||||
// .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
.apis(RequestHandlerSelectors.basePackage(basePackage))
|
||||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||||
.paths(PathSelectors.any())
|
.paths(PathSelectors.any())
|
||||||
.build()
|
.build()
|
||||||
/* 设置安全模式,swagger可以设置访问token */
|
.groupName(group.getName())
|
||||||
|
// 设置安全模式,swagger可以设置访问token
|
||||||
.securitySchemes(securitySchemes())
|
.securitySchemes(securitySchemes())
|
||||||
.securityContexts(securityContexts())
|
.securityContexts(securityContexts())
|
||||||
.pathMapping(swaggerProperties.getPathMapping());
|
.pathMapping(swaggerProperties.getPathMapping());
|
||||||
|
String beanName = StringUtils.substringAfterLast(basePackage, ".") + "Docket";
|
||||||
|
SpringUtils.registerBean(beanName, docket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,7 +70,8 @@ public class SwaggerConfig {
|
|||||||
*/
|
*/
|
||||||
private List<SecurityScheme> securitySchemes() {
|
private List<SecurityScheme> securitySchemes() {
|
||||||
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
||||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
|
String header = tokenProperties.getHeader();
|
||||||
|
apiKeyList.add(new ApiKey(header, header, In.HEADER.toValue()));
|
||||||
return apiKeyList;
|
return apiKeyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +96,7 @@ public class SwaggerConfig {
|
|||||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||||
authorizationScopes[0] = authorizationScope;
|
authorizationScopes[0] = authorizationScope;
|
||||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||||
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
|
securityReferences.add(new SecurityReference(tokenProperties.getHeader(), authorizationScopes));
|
||||||
return securityReferences;
|
return securityReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.ruoyi.framework.config.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security 配置属性
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "security")
|
||||||
|
public class SecurityProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录url
|
||||||
|
*/
|
||||||
|
private String logoutUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匿名放行路径
|
||||||
|
*/
|
||||||
|
private String[] anonymous;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户任意访问放行路径
|
||||||
|
*/
|
||||||
|
private String[] permitAll;
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,8 @@ import lombok.NoArgsConstructor;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* swagger 配置属性
|
* swagger 配置属性
|
||||||
*
|
*
|
||||||
@ -41,23 +43,46 @@ public class SwaggerProperties {
|
|||||||
*/
|
*/
|
||||||
private Contact contact;
|
private Contact contact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配置
|
||||||
|
*/
|
||||||
|
private List<Groups> groups;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class Contact {
|
public static class Contact {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人
|
* 联系人
|
||||||
**/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人url
|
* 联系人url
|
||||||
**/
|
*/
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人email
|
* 联系人email
|
||||||
**/
|
*/
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class Groups {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础包路径
|
||||||
|
*/
|
||||||
|
private String basePackage;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -557,7 +557,7 @@ export default {
|
|||||||
/** ${subTable.functionName}删除按钮操作 */
|
/** ${subTable.functionName}删除按钮操作 */
|
||||||
handleDelete${subClassName}() {
|
handleDelete${subClassName}() {
|
||||||
if (this.checked${subClassName}.length == 0) {
|
if (this.checked${subClassName}.length == 0) {
|
||||||
this.msgError("请先选择要删除的${subTable.functionName}数据");
|
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
|
||||||
} else {
|
} else {
|
||||||
const ${subclassName}List = this.${subclassName}List;
|
const ${subclassName}List = this.${subclassName}List;
|
||||||
const checked${subClassName} = this.checked${subClassName};
|
const checked${subClassName} = this.checked${subClassName};
|
||||||
|
@ -77,9 +77,14 @@ public class SysLoginService
|
|||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
|
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
|
||||||
throw new UserPasswordNotMatchException();
|
throw new UserPasswordNotMatchException();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
|
||||||
|
throw new ServiceException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
||||||
recordLoginInfo(user);
|
recordLoginInfo(user.getUserId());
|
||||||
// 生成token
|
// 生成token
|
||||||
StpUtil.login(user.getUserId(), "PC");
|
StpUtil.login(user.getUserId(), "PC");
|
||||||
return StpUtil.getTokenValue();
|
return StpUtil.getTokenValue();
|
||||||
@ -109,12 +114,15 @@ public class SysLoginService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录登录信息
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
public void recordLoginInfo(SysUser user)
|
public void recordLoginInfo(Long userId)
|
||||||
{
|
{
|
||||||
user.setLoginIp(ServletUtils.getClientIP());
|
SysUser sysUser = new SysUser();
|
||||||
user.setLoginDate(DateUtils.getNowDate());
|
sysUser.setUserId(userId);
|
||||||
user.setUpdateBy(user.getUserName());
|
sysUser.setLoginIp(ServletUtils.getClientIP());
|
||||||
userService.updateUserProfile(user);
|
sysUser.setLoginDate(DateUtils.getNowDate());
|
||||||
|
userService.updateUserProfile(sysUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
<el-tab-pane label="基本信息" name="basic">
|
<el-tab-pane label="基本信息" name="basic">
|
||||||
<basic-info-form ref="basicInfo" :info="info" />
|
<basic-info-form ref="basicInfo" :info="info" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="字段信息" name="cloum">
|
<el-tab-pane label="字段信息" name="columnInfo">
|
||||||
<el-table ref="dragTable" :data="cloumns" row-key="columnId" :max-height="tableHeight">
|
<el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
|
||||||
<el-table-column label="序号" type="index" min-width="5%" class-name="allowDrag" />
|
<el-table-column label="序号" type="index" min-width="5%" class-name="allowDrag" />
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="字段列名"
|
label="字段列名"
|
||||||
@ -141,13 +141,13 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 选中选项卡的 name
|
// 选中选项卡的 name
|
||||||
activeName: "cloum",
|
activeName: "columnInfo",
|
||||||
// 表格的高度
|
// 表格的高度
|
||||||
tableHeight: document.documentElement.scrollHeight - 245 + "px",
|
tableHeight: document.documentElement.scrollHeight - 245 + "px",
|
||||||
// 表信息
|
// 表信息
|
||||||
tables: [],
|
tables: [],
|
||||||
// 表列信息
|
// 表列信息
|
||||||
cloumns: [],
|
columns: [],
|
||||||
// 字典信息
|
// 字典信息
|
||||||
dictOptions: [],
|
dictOptions: [],
|
||||||
// 菜单信息
|
// 菜单信息
|
||||||
@ -161,7 +161,7 @@ export default {
|
|||||||
if (tableId) {
|
if (tableId) {
|
||||||
// 获取表详细信息
|
// 获取表详细信息
|
||||||
getGenTable(tableId).then(res => {
|
getGenTable(tableId).then(res => {
|
||||||
this.cloumns = res.data.rows;
|
this.columns = res.data.rows;
|
||||||
this.info = res.data.info;
|
this.info = res.data.info;
|
||||||
this.tables = res.data.tables;
|
this.tables = res.data.tables;
|
||||||
});
|
});
|
||||||
@ -184,7 +184,7 @@ export default {
|
|||||||
const validateResult = res.every(item => !!item);
|
const validateResult = res.every(item => !!item);
|
||||||
if (validateResult) {
|
if (validateResult) {
|
||||||
const genTable = Object.assign({}, basicForm.model, genForm.model);
|
const genTable = Object.assign({}, basicForm.model, genForm.model);
|
||||||
genTable.columns = this.cloumns;
|
genTable.columns = this.columns;
|
||||||
genTable.params = {
|
genTable.params = {
|
||||||
treeCode: genTable.treeCode,
|
treeCode: genTable.treeCode,
|
||||||
treeName: genTable.treeName,
|
treeName: genTable.treeName,
|
||||||
@ -220,10 +220,10 @@ export default {
|
|||||||
const sortable = Sortable.create(el, {
|
const sortable = Sortable.create(el, {
|
||||||
handle: ".allowDrag",
|
handle: ".allowDrag",
|
||||||
onEnd: evt => {
|
onEnd: evt => {
|
||||||
const targetRow = this.cloumns.splice(evt.oldIndex, 1)[0];
|
const targetRow = this.columns.splice(evt.oldIndex, 1)[0];
|
||||||
this.cloumns.splice(evt.newIndex, 0, targetRow);
|
this.columns.splice(evt.newIndex, 0, targetRow);
|
||||||
for (let index in this.cloumns) {
|
for (let index in this.columns) {
|
||||||
this.cloumns[index].sort = parseInt(index) + 1;
|
this.columns[index].sort = parseInt(index) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user