mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-18 17:05:55 +08:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8216db72b4 | ||
|
|
8501632079 | ||
|
|
1a3c6fd460 | ||
|
|
2cf44dc4ef | ||
|
|
7b361e6eae | ||
|
|
07392576f3 | ||
|
|
79d2a82e2d | ||
|
|
d357a68e35 | ||
|
|
ce0abdfbb1 | ||
|
|
bc93c2d2eb | ||
|
|
5f33234e8b | ||
|
|
73f66f8d78 | ||
|
|
3c7a64327d | ||
|
|
fa25f771a2 | ||
|
|
3e4d271be8 | ||
|
|
63d2258911 | ||
|
|
f48e7a1579 | ||
|
|
44f3182ec3 | ||
|
|
0306e5c6cb | ||
|
|
4dc62fdecd | ||
|
|
61a9c0a846 | ||
|
|
b3cb59e151 | ||
|
|
9dad5ec04c | ||
|
|
6cf181ee8d | ||
|
|
d7b5ce1c16 | ||
|
|
c5a9d0d567 | ||
|
|
f5af688500 | ||
|
|
908c4e58a7 | ||
|
|
1e7bd72bfa | ||
|
|
5058e2edc7 | ||
|
|
d56c600643 | ||
|
|
c5ddae9565 | ||
|
|
edf2dc0b88 | ||
|
|
21f0a90a2d | ||
|
|
fe28413ab2 | ||
|
|
25bcaae210 | ||
|
|
a082c61f6b | ||
|
|
2ad5d6ff28 | ||
|
|
7f58d3e12b | ||
|
|
7079610ee4 | ||
|
|
5bb2794e8c | ||
|
|
4ec2f3eeaa | ||
|
|
bc5b492d26 | ||
|
|
a3625cd254 | ||
|
|
3500faf044 | ||
|
|
5b6ec185c4 | ||
|
|
f545198645 | ||
|
|
32cc5e794e | ||
|
|
461ab2a37e | ||
|
|
44bd079c06 | ||
|
|
70f466e471 | ||
|
|
8d60474904 | ||
|
|
2df210fe6b | ||
|
|
00f5c882e2 | ||
|
|
25239c32cb | ||
|
|
bfd2977ff4 | ||
|
|
8c9031acef | ||
|
|
f5598f1663 | ||
|
|
d681d4b22b | ||
|
|
0215feb4b0 | ||
|
|
905e36243c | ||
|
|
201bbfeefb | ||
|
|
39aba490c6 | ||
|
|
54f2487330 | ||
|
|
ff51ea78af | ||
|
|
e404cd26d4 | ||
|
|
b86acd933b | ||
|
|
5fc141719a | ||
|
|
8939c78e37 | ||
|
|
19fedbe841 | ||
|
|
1805c99f4f | ||
|
|
56577f4262 | ||
|
|
12dc1e869e | ||
|
|
7f5d432f5a | ||
|
|
d979c9025a | ||
|
|
f71cbff3d7 | ||
|
|
645fca0119 | ||
|
|
4065392ccc | ||
|
|
bc8b5796d2 | ||
|
|
18568aa663 | ||
|
|
38e236a8ff | ||
|
|
8099d7bdcc | ||
|
|
a5a88ae379 | ||
|
|
462da2a6ce | ||
|
|
f7e9e403b0 | ||
|
|
2772c49df1 | ||
|
|
1afceda43c | ||
|
|
4920d84516 | ||
|
|
14ad72b6fa | ||
|
|
59f4185d2b | ||
|
|
59c83b1601 | ||
|
|
e8c192dbd4 | ||
|
|
1424423769 | ||
|
|
0615f005b7 | ||
|
|
c2a7aafcd4 | ||
|
|
d8e07328c7 | ||
|
|
5abe95f617 | ||
|
|
c12352ffea | ||
|
|
5715a15d46 | ||
|
|
92b504d78a | ||
|
|
c8a9fd0a99 | ||
|
|
4af4f250eb | ||
|
|
6d50802b60 | ||
|
|
87cb9f2ba1 | ||
|
|
2f481c1b13 | ||
|
|
cfebb8753f | ||
|
|
a7f60c902a | ||
|
|
aab9710423 | ||
|
|
a56ab82a94 |
163
README.md
163
README.md
@@ -1,110 +1,95 @@
|
||||

|
||||
[](https://gitee.com/activity/2025opensource?ident=IKKZS9)
|
||||
|
||||
|
||||
FastBee 是一款面向中小企业与个人开发者的**轻量**、**易用**、**全栈**开源物联网平台。
|
||||
|
||||
---
|
||||
|
||||
### 一、项目介绍
|
||||
|
||||
1. FastBee开源物联网平台,简单易用,更适合中小企业和个人学习使用。适用于智能家居、智慧办公、智慧社区、农业监测、水利监测、工业控制等。
|
||||
|
||||
2. 系统后端采用Spring boot;前端采用Vue;Mqtt服务端使用netty搭建;移动端支持微信小程序、安卓、苹果和H5采用Uniapp;数据库采用Mysql、TDengine和Redis;设备端支持ESP32、ESP8266、树莓派、合宙等;
|
||||
FastBee 集设备管理、数据监控、多端应用于一体,支持[一键容器化部署](https://fastbee.cn/doc/install/docker.html),适用于智能家居、智慧办公、智慧社区、农业监测、水利监测、工业控制等多种场景。平台基于 Spring Boot 开发,<b>内置高性能 MQTT 服务端,无需额外部署 EMQX 或其他 MQTT 服务端</b>,前端采用 Vue 与 ElementUI,移动端支持微信小程序、Android、iOS 及 H5,设备端兼容 ESP32、ESP8266、树莓派、合宙等常见硬件。
|
||||
|
||||
---
|
||||
|
||||
### 二、系统功能
|
||||
|
||||
| 系统功能 | 功能说明 | 开源版本 | 商业版本 |
|
||||
|:------------------------:|:-----------------------------------------------:|------|--------------|
|
||||
| 产品管理 | 产品详情、产品物模型、产品分类、设备授权、产品固件 | 支持 | 支持 |
|
||||
| 设备管理 | 设备详情、设备分组、设备日志、设备分享、设备实时控制、实时状态、数据监测 | 支持 | 支持 |
|
||||
| 物模型管理 | 属性(设备状态和监测数据),功能(执行特定任务),事件(设备主动上报给云端) | 支持 | 支持 |
|
||||
| MQTT接入 | emqx开源版、netty版本MqttBroker | 支持 | 支持 |
|
||||
| 硬件 SDK | ESP-IDF、Arduino、RaspberryPi、合宙等平台设备接入 | 支持 | 支持 |
|
||||
| 视频监控接入 | 基于GB/T28181协议支持主流厂商监控设备接入,直播、设备录制回放、 云端录像和云台控制 | 支持设备接入和直播 | 支持 |
|
||||
| 多协议管理 | 硬件设备多种协议支持管理 | 支持JSON | 支持多种 |
|
||||
| TCP接入 | 基于Netty搭建的TCP服务器 | 不支持 | 支持 |
|
||||
| Modbus接入 | 透传Modbus/边缘网关接入Modbus设备 | 不支持 | 支持 |
|
||||
| 采集点管理 | 网关设备管理子设备接入 | 不支持 | 支持 |
|
||||
| 设备模拟器调试 | Modbus设备在线调试 | 不支持 | 支持 |
|
||||
| 数据大屏 | 数据大屏可视化,将图表或页面元素封装为基础组件,0代码即可完成业务需求。 | 不支持 | 支持 |
|
||||
| 规则引擎-规则脚本 | 可视化规则引擎编写,支持js,java等脚本修改消息结构,处理设备上行/下行/上线/下线/数据解析/数据转换 | 不支持 | 支持 |
|
||||
| 场景联动 | 基于规则引擎生成场景联动 | 不支持 | 支持 |
|
||||
| 告警功能 | 告警: 设备告警/平台告警判定 告警配置: 基于规则引擎开发的平台告警判定 告警记录:设备告警记录入库 | 不支持 | 支持 |
|
||||
| 消息通知功能 | 阿里云短信/腾讯云短信阿里云语言/腾讯云语音/QQ邮箱/163邮箱/微信小程序/企业微信群机器人/企业微信应用信息/钉钉消息通知/钉钉群机器人 | 不支持 | 支持 |
|
||||
| 多租户 | 系统内租户的管理,独占一套系统配置,数据相互隔离。如:租户权限、过期时间、用户数量、企业信息等 | 不支持 | 支持 |
|
||||
| 移动端app | 移动端(安卓 / 苹果 / 微信小程序) | 不支持 | 支持 |
|
||||
| 智能音响对接 | 云云对接:智能音响(小度、天猫精灵、小爱同学) | 不支持 | 额外付费模块 |
|
||||
| web组态 | 自定义数据大屏/2D/3D | 不支持 | 额外付费模块 |
|
||||
| 第三方OpenAPT接入 | 萤石云,海康sdk接入、AI SDK接入 | 不支持 | 额外付费模块 |
|
||||
| 数据存储 | 设备数据处理 | redis存储最后一条数据,不支持实时更新 | redis存储最新数据,实时更新/mysql存储系统数据/TDengine时序数据库存储设备数据 |
|
||||
| 设备接入数/上行数据并发支持 | 设备接入数,以及设备数据并发量 | 支持小规模设备接入,同步处理数据 | 支持规模量大设备。消息队列削峰,线程池异步处理高并发数据 |
|
||||
| 技术支持 | | 不支持 | 提供一定的技术支持/技术方案 |
|
||||
| 系统功能 | 功能说明 |
|
||||
|----------------|--------------------------------------------------------------------------|
|
||||
| 产品管理 | 创建产品、定义物模型、设置设备认证方式、管理产品分类及固件版本 |
|
||||
| 设备管理 | 设备注册、分组、实时状态监测、远程控制、操作日志追溯及设备分享功能 |
|
||||
| 物模型管理 | 提供标准化的属性、功能和事件定义,实现设备与平台的数据语义统一 |
|
||||
| 规则脚本 | 对设备上报和平台下发的原始数据进行处理,转发后匹配设备交互格式 |
|
||||
| MQTT 接入 | 内置基于 Netty 开发的高性能 MQTT Broker,无需额外部署第三方服务 |
|
||||
| 视频监控接入 | 支持 GB/T 28181 国家标准协议,实现视频直播与设备管理 |
|
||||
| 权限管理 | 基于成熟的若依权限框架,实现用户、角色、部门、岗位及操作日志的精细化管控 |
|
||||
| 多数据源 | 支持 MySQL、PostgreSQL、MSSQL 等关系型数据库 |
|
||||
| 硬件 SDK | 提供 ESP-IDF、Arduino、树莓派、合宙等常见硬件平台的接入示例与 SDK |
|
||||
| 多端应用支持 | 提供 Web 控制台(Vue + ElementUI)、微信小程序、Android/iOS App 及 H5 界面 |
|
||||
| 一键部署 | 推荐使用 Docker 容器化部署,支持[快速搭建](https://fastbee.cn/doc/install/docker.html)完整环境 |
|
||||
|
||||
|
||||
[](https://gitee.com/beecue/FastBee-Arduino)
|
||||
|
||||

|
||||
---
|
||||
|
||||
|[空气检测仪](https://fastbee.cn/doc/pages/hardware/) | [物联网开发板](https://fastbee.cn/doc/pages/hardware/) | [Air724开发板](https://fastbee.cn/doc/pages/hardware/) | [智能开关](https://fastbee.cn/doc/pages/hardware/) | [查看更多>>](https://fastbee.cn/doc/pages/hardware/) |
|
||||
### 三、快速开始
|
||||
|
||||
1. **环境准备**:确保服务器已安装 `Docker` 和 `Docker Compose`。
|
||||
2. **执行命令**:
|
||||
```bash
|
||||
sudo wget -c https://hub.fastbee.cn/resource/install.sh && bash ./install.sh
|
||||
```
|
||||
根据提示选择“开源版本”,脚本将自动完成所有服务的拉取与启动。
|
||||
3. **访问系统**:部署完成后,通过浏览器访问 `http://你的服务器IP:端口`,默认账号为 `admin`,密码为 `admin123`。
|
||||
4. **详细步骤**:请查阅 [官方安装文档](https://fastbee.cn/doc/install/docker.html)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
### 四、技术栈
|
||||
##### 服务端
|
||||
- 相关技术:Spring boot、MyBatis、Spring Security、Jwt、Mysql、Redis、TDengine、Netty等
|
||||
- 开发工具:IDEA
|
||||
- 源码目录:spring-boot文件夹下
|
||||
|
||||
##### Web端
|
||||
- 相关技术:ES6、Vue、Vuex、Vue-router、Vue-cli、Axios、Element-ui、Echart等
|
||||
- 开发工具:Visual Studio Code
|
||||
- 源码目录:vue文件夹下
|
||||
|
||||
##### 移动端(微信小程序 / Android / Ios / H5)
|
||||
- 相关技术:uniapp、[uView](https://www.uviewui.com/)、[uChart](https://www.ucharts.cn/)
|
||||
- 开发工具:HBuilder
|
||||
- 源码地址:[https://gitee.com/beecue/fastbee-app](https://gitee.com/beecue/fastbee-app)
|
||||
|
||||
##### 硬件端
|
||||
- 相关技术: ESP-IDF、Arduino、FreeRTOS、Python、Lua等
|
||||
- 开发工具:Visual Studio Code 和 Arduino等
|
||||
- 源码地址:[https://gitee.com/beecue/fastbee-sdk](https://gitee.com/beecue/fastbee-sdk)
|
||||
|
||||
##### 部署与运维
|
||||
- 相关技术:docker、docker-compose、shell
|
||||
- [快速部署](https://fastbee.cn/doc/install/docker.html):安装好docker和docker-compose后执行命令 ` sudo wget -c https://hub.fastbee.cn/resource/install.sh && bash ./install.sh ` 然后选择开源版本,等待完成部署
|
||||
|
||||
|空气检测仪| 物联网开发板 | Air724开发板 | 智能开关| [查看更多>>](https://fastbee.cn/doc/device/) |
|
||||
| :----: | :----------: |:----------: |:----------: |:----------: |
|
||||
|  |  |  | |  |
|
||||
|
||||
---
|
||||
|
||||
### 三、技术栈
|
||||
* 服务端
|
||||
- 相关技术:Spring boot、MyBatis、Spring Security、Jwt、Mysql、Redis、TDengine、EMQX、Netty等
|
||||
- 开发工具:IDEA
|
||||
* Web端
|
||||
- 相关技术:ES6、Vue、Vuex、Vue-router、Vue-cli、Axios、Element-ui、Echart等
|
||||
- 开发工具:Visual Studio Code
|
||||
* 移动端(微信小程序 / Android / Ios / H5)
|
||||
- 相关技术:uniapp、[uView](https://www.uviewui.com/)、[uChart](https://www.ucharts.cn/)
|
||||
- 开发工具:HBuilder
|
||||
* 硬件端
|
||||
- 相关技术: ESP-IDF、Arduino、FreeRTOS、Python、Lua等
|
||||
- 开发工具:Visual Studio Code 和 Arduino等
|
||||
### 五、其他
|
||||
|
||||
1. **商用授权**:开源版本采用 AGPL3 协议,可用于个人学习和使用,商业用途推荐购买[商业版本授权](https://fastbee.cn/doc/pages/sponsor/)。
|
||||
2. **在线演示**:[商业版本演示地址](https://iot.fastbee.cn/)(开源版本暂仅支持 MQTT 协议)。
|
||||
3. **系统文档**:[https://fastbee.cn/doc/](https://fastbee.cn/doc/)
|
||||
4. **QQ 交流群**:720136372、946029159、1073236354
|
||||
|
||||
### 四、项目目录
|
||||
app -------------------- 移动端(微信小程序 / Android / Ios / H5) 商业版开源<br/>
|
||||
docker ---------------- docker部署文件<br />
|
||||
spring-boot ---------- 后端<br/>
|
||||
vue -------------------- 前端<br />
|
||||
---
|
||||
|
||||
### 六、部分图片
|
||||
|
||||
### 五、商用授权
|
||||
项目采用AGPL3协议,可用于个人学习和使用,商业用途需要赞助项目,获得授权,并提供商业版本源码、可视化平台和移动端源码。赞助过的用户请下载商业版本源码。
|
||||
- [授权详情>>](https://fastbee.cn/doc/pages/sponsor/) [商业版本源码>>](https://fastbee.cn/doc/pages/sponsor/)
|
||||
- [移动端源码>>](https://gitee.com/beecue/fastbee-app) [可视化平台源码>>](https://fastbee.cn/doc/pages/sponsor/)
|
||||
- [硬件SDK源码>>](https://gitee.com/beecue/fastbee-sdk)
|
||||
- 二开项目同样遵守AGPL3.0协议进行开源,可以向原作者申请授权
|
||||
- 如果商业项目想转闭源,可以向原作者申请或者购买闭源授权
|
||||
|
||||
### 六、贡献代码
|
||||
- [贡献者指南>>](./doc/贡献者指南.md)
|
||||
- [Git提交规范>>](./doc/Git提交规范.md)
|
||||
- [功能规划>>](./RoadMap.md)
|
||||
|
||||
### 七、其他
|
||||
1. QQ交流群:🚀946029159 🚀1073236354(已满)
|
||||
|
||||
2. 权限管理基于ruoyi-vue系统开发,Mqtt消息服务器使用EMQX5.0开源版
|
||||
|
||||
* [开源版本在线演示](http://101.33.237.12/)
|
||||
* [商业版本在线演示](https://iot.fastbee.cn/)
|
||||
* [项目使用文档](https://fastbee.cn/doc/)
|
||||
* [若依权限管理系统文档](http://doc.ruoyi.vip/ruoyi-vue/)
|
||||
* [EMQX5.0消息服务器文档](https://www.emqx.io/docs/zh/v5.0/)
|
||||
* [uCharts高性能跨平台图表库](https://www.ucharts.cn)
|
||||
|
||||
3. 项目贡献者(如有遗漏请联系作者):
|
||||
- [小驿物联](https://gitee.com/iot-xiaoyi)、[CrazyDull](https://gitee.com/crazyDull)、[YBZX](https://github.com/YBZX)、 [CQAdu](https://gitee.com/iot.adu)、[孙阿龙](https://gitee.com/sunalong)、[xxmfl](https://gitee.com/xxmfl)、[董晓龙-3715687@qq.com](https://fastbee.cn/)
|
||||
- [SXH](https://gitee.com/sixiaohu)、 [Redamancy_zxp](https://gitee.com/redamancy-zxp)、 [LEE](https://gitee.com/yueming188)、 [LemonTree](https://gitee.com/fishhunterplus)、 [Tang](https://gitee.com/mexiaotang)、 [Tang](https://gitee.com/mexiaotang)、[KUN](https://gitee.com/L_KUN_KUN)
|
||||
|
||||
4. 主要参与用户:
|
||||
- [Guanshubiao](https://gitee.com/guanshubiao):熟悉物联网开发,完善和优化系统的网关架构和部分功能等
|
||||
- [帐篷](https://gitee.com/zhuangpengli):熟悉物联网开发,完善视频监控模块和部分协议等
|
||||
- [JaminDeng](https://gitee.com/jamin-deng):熟悉物联网开发,完善平台前端设计可视化等
|
||||
|
||||
### 八、部分图片
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -129,4 +114,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
|
||||
FastBee 项目代码完全开源,覆盖设备 SDK、后端服务、前端应用和移动端,兼顾成熟度、性能与开发效率,适合中小企业快速构建物联网业务,也便于开发者进行二次开发与学习研究。
|
||||
@@ -1,47 +0,0 @@
|
||||
<br />
|
||||
|
||||
* 项目可用于个人学习;商业使用请赞助该项目,获得授权;
|
||||
* 赞助后还提供了小程序、APP源码。[详情](https://wumei.live/doc/pages/sponsor/)
|
||||
|
||||
|
||||
#### 移动端介绍
|
||||
|
||||
|安卓/Android|苹果/IOS|微信小程序| 网页/H5|Vue2.0
|
||||
| :---: | :---: | :---: | :---: |:---: |
|
||||
| √ | √| √ | √ | √ |
|
||||
|
||||
|
||||
1. 项目使用uniapp开发,适配小程序、安卓、苹果和H5,其他平台未测试。
|
||||
2. UI框架使用uView2.0
|
||||
3. 组件使用easycom模式,只要组件安装在项目的components目录下或uni_modules目录下,并符合components/组件名称/组件名称.vue目录结构。就可以不用引用、注册,直接在页面中使用。
|
||||
4. 开发工具为Hbuilder3.3版本,版本不易过低。
|
||||
|
||||
|
||||
###### 项目结构
|
||||
|
||||
```
|
||||
├─apis // 接口管理
|
||||
│ ├─modules // api模块化目录
|
||||
│ │ └─device.js // 设备接口地址
|
||||
│ ├─http.api.js // 接口定义文件
|
||||
│ └─http.interceptor // 拦截器
|
||||
├─common // 公共文件
|
||||
│ ├─config // 环境配置 (设置baseurl等)
|
||||
│ ├─extend // 扩展原型方法
|
||||
│ ├─filters // 全局过滤器
|
||||
│ └─tools // 全局公共方法
|
||||
├─components // 项目组件库,组件放置这里,其他页面可直接使用
|
||||
│ ├─cl-test // easycom测试组件
|
||||
│ └─cl-icon // iconfont图标组件
|
||||
├─pages // 页面目录
|
||||
│ ├─public // 公共页面
|
||||
│ └─tarbar // 底部导航栏页面
|
||||
├─static // 图片目录
|
||||
├─store // vuex
|
||||
│ ├─$u.mixin // store全局混入方法
|
||||
│ └─index // vuex 组件全局状态管理
|
||||
├─uni_modules // 插件市场插件目录
|
||||
│ └─uview-ui // uview-ui
|
||||
```
|
||||
|
||||
<br /><br />
|
||||
BIN
app/fastbee.apk
BIN
app/fastbee.apk
Binary file not shown.
BIN
app/fastbee.ipa
BIN
app/fastbee.ipa
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
images/banner.jpg
Normal file
BIN
images/banner.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
BIN
images/banner1.png
Normal file
BIN
images/banner1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>fastbee</artifactId>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<version>3.8.5</version>
|
||||
<version>${fastbee.version}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
@@ -34,7 +34,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<version>${io.swagger.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
@@ -84,7 +84,7 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<version>2.5.15</version>
|
||||
<configuration>
|
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||
</configuration>
|
||||
|
||||
@@ -2,14 +2,13 @@ package com.fastbee;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||
@SpringBootApplication
|
||||
public class FastBeeApplication
|
||||
{
|
||||
public static void main(String[] args)
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -26,7 +27,7 @@ import com.fastbee.system.domain.SysCache;
|
||||
|
||||
/**
|
||||
* 缓存监控
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "缓存监控")
|
||||
@@ -87,7 +88,7 @@ public class CacheController
|
||||
public AjaxResult getCacheKeys(@PathVariable String cacheName)
|
||||
{
|
||||
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
|
||||
return AjaxResult.success(cacheKeys);
|
||||
return AjaxResult.success(new TreeSet<>(cacheKeys));
|
||||
}
|
||||
|
||||
@ApiOperation("缓存内容")
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.fastbee.system.service.ISysUserOnlineService;
|
||||
|
||||
/**
|
||||
* 在线用户监控
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "在线用户监控")
|
||||
@@ -54,24 +54,15 @@ public class SysUserOnlineController extends BaseController
|
||||
LoginUser user = redisCache.getCacheObject(key);
|
||||
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
|
||||
{
|
||||
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
|
||||
{
|
||||
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
|
||||
}
|
||||
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(ipaddr))
|
||||
{
|
||||
if (StringUtils.equals(ipaddr, user.getIpaddr()))
|
||||
{
|
||||
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
|
||||
}
|
||||
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
|
||||
{
|
||||
if (StringUtils.equals(userName, user.getUsername()))
|
||||
{
|
||||
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
|
||||
}
|
||||
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.fastbee.system.service.ISysConfigService;
|
||||
|
||||
/**
|
||||
* 参数配置 信息操作处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "参数设置")
|
||||
@@ -93,7 +93,7 @@ public class SysConfigController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysConfig config)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
|
||||
if (!configService.checkConfigKeyUnique(config))
|
||||
{
|
||||
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public class SysConfigController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody SysConfig config)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
|
||||
if (!configService.checkConfigKeyUnique(config))
|
||||
{
|
||||
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.fastbee.system.service.ISysDeptService;
|
||||
|
||||
/**
|
||||
* 部门信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "部门管理")
|
||||
@@ -84,7 +84,7 @@ public class SysDeptController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysDept dept)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
|
||||
if (!deptService.checkDeptNameUnique(dept))
|
||||
{
|
||||
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class SysDeptController extends BaseController
|
||||
{
|
||||
Long deptId = dept.getDeptId();
|
||||
deptService.checkDeptDataScope(deptId);
|
||||
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
|
||||
if (!deptService.checkDeptNameUnique(dept))
|
||||
{
|
||||
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.fastbee.system.service.ISysDictTypeService;
|
||||
|
||||
/**
|
||||
* 数据字典信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "字典管理")
|
||||
@@ -80,7 +80,7 @@ public class SysDictTypeController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysDictType dict)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
|
||||
if (!dictTypeService.checkDictTypeUnique(dict))
|
||||
{
|
||||
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class SysDictTypeController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody SysDictType dict)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
|
||||
if (!dictTypeService.checkDictTypeUnique(dict))
|
||||
{
|
||||
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||
}
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
package com.fastbee.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.core.domain.AjaxResult;
|
||||
import com.fastbee.common.core.domain.entity.SysMenu;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
import com.fastbee.common.core.domain.model.LoginBody;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.utils.SecurityUtils;
|
||||
import com.fastbee.framework.web.service.SysLoginService;
|
||||
import com.fastbee.framework.web.service.SysPermissionService;
|
||||
import com.fastbee.framework.web.service.TokenService;
|
||||
import com.fastbee.system.service.ISysMenuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "登录验证")
|
||||
@RestController
|
||||
public class SysLoginController
|
||||
{
|
||||
@@ -38,16 +36,16 @@ public class SysLoginController
|
||||
|
||||
@Autowired
|
||||
private SysPermissionService permissionService;
|
||||
@Value("${server.broker.enabled}")
|
||||
private Boolean enabled;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*
|
||||
*
|
||||
* @param loginBody 登录信息
|
||||
* @return 结果
|
||||
*/
|
||||
@ApiOperation("用户登录")
|
||||
@PostMapping("/login")
|
||||
public AjaxResult login(@RequestBody LoginBody loginBody)
|
||||
{
|
||||
@@ -61,32 +59,35 @@ public class SysLoginController
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
*
|
||||
* @return 用户信息
|
||||
*/
|
||||
@ApiOperation("获取用户信息")
|
||||
@GetMapping("getInfo")
|
||||
public AjaxResult getInfo()
|
||||
{
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
SysUser user = loginUser.getUser();
|
||||
// 角色集合
|
||||
Set<String> roles = permissionService.getRolePermission(user);
|
||||
// 权限集合
|
||||
Set<String> permissions = permissionService.getMenuPermission(user);
|
||||
if (!loginUser.getPermissions().equals(permissions))
|
||||
{
|
||||
loginUser.setPermissions(permissions);
|
||||
tokenService.refreshToken(loginUser);
|
||||
}
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("user", user);
|
||||
ajax.put("roles", roles);
|
||||
ajax.put("permissions", permissions);
|
||||
ajax.put("mqtt",enabled);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由信息
|
||||
*
|
||||
*
|
||||
* @return 路由信息
|
||||
*/
|
||||
@ApiOperation("获取路由信息")
|
||||
@GetMapping("getRouters")
|
||||
public AjaxResult getRouters()
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.fastbee.system.service.ISysMenuService;
|
||||
|
||||
/**
|
||||
* 菜单信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "菜单管理")
|
||||
@@ -94,7 +94,7 @@ public class SysMenuController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysMenu menu)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
|
||||
if (!menuService.checkMenuNameUnique(menu))
|
||||
{
|
||||
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public class SysMenuController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
|
||||
if (!menuService.checkMenuNameUnique(menu))
|
||||
{
|
||||
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
@@ -150,4 +150,4 @@ public class SysMenuController extends BaseController
|
||||
}
|
||||
return toAjax(menuService.deleteMenuById(menuId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.fastbee.system.service.ISysPostService;
|
||||
|
||||
/**
|
||||
* 岗位信息操作处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "岗位管理")
|
||||
@@ -83,11 +83,11 @@ public class SysPostController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysPost post)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
|
||||
if (!postService.checkPostNameUnique(post))
|
||||
{
|
||||
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
|
||||
else if (!postService.checkPostCodeUnique(post))
|
||||
{
|
||||
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||
}
|
||||
@@ -104,11 +104,11 @@ public class SysPostController extends BaseController
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody SysPost post)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
|
||||
if (!postService.checkPostNameUnique(post))
|
||||
{
|
||||
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
|
||||
else if (!postService.checkPostCodeUnique(post))
|
||||
{
|
||||
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 个人信息 业务处理
|
||||
@@ -78,29 +79,22 @@ public class SysProfileController extends BaseController
|
||||
public AjaxResult updateProfile(@RequestBody SysUser user)
|
||||
{
|
||||
LoginUser loginUser = getLoginUser();
|
||||
SysUser sysUser = loginUser.getUser();
|
||||
user.setUserName(sysUser.getUserName());
|
||||
if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
currentUser.setNickName(user.getNickName());
|
||||
currentUser.setEmail(user.getEmail());
|
||||
currentUser.setPhonenumber(user.getPhonenumber());
|
||||
currentUser.setSex(user.getSex());
|
||||
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
|
||||
{
|
||||
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
|
||||
{
|
||||
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
user.setUserId(sysUser.getUserId());
|
||||
user.setPassword(null);
|
||||
user.setAvatar(null);
|
||||
user.setDeptId(null);
|
||||
if (userService.updateUserProfile(user) > 0)
|
||||
if (userService.updateUserProfile(currentUser) > 0)
|
||||
{
|
||||
// 更新缓存用户信息
|
||||
sysUser.setNickName(user.getNickName());
|
||||
sysUser.setPhonenumber(user.getPhonenumber());
|
||||
sysUser.setEmail(user.getEmail());
|
||||
sysUser.setSex(user.getSex());
|
||||
tokenService.setLoginUser(loginUser);
|
||||
return success();
|
||||
}
|
||||
@@ -113,8 +107,10 @@ public class SysProfileController extends BaseController
|
||||
@ApiOperation("重置密码")
|
||||
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/updatePwd")
|
||||
public AjaxResult updatePwd(String oldPassword, String newPassword)
|
||||
public AjaxResult updatePwd(@RequestBody Map<String, String> params)
|
||||
{
|
||||
String oldPassword = params.get("oldPassword");
|
||||
String newPassword = params.get("newPassword");
|
||||
LoginUser loginUser = getLoginUser();
|
||||
String userName = loginUser.getUsername();
|
||||
String password = loginUser.getPassword();
|
||||
@@ -126,10 +122,11 @@ public class SysProfileController extends BaseController
|
||||
{
|
||||
return error("新密码不能与旧密码相同");
|
||||
}
|
||||
if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
|
||||
newPassword = SecurityUtils.encryptPassword(newPassword);
|
||||
if (userService.resetUserPwd(userName, newPassword) > 0)
|
||||
{
|
||||
// 更新缓存用户密码
|
||||
loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
|
||||
loginUser.getUser().setPassword(newPassword);
|
||||
tokenService.setLoginUser(loginUser);
|
||||
return success();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import com.fastbee.system.service.ISysUserService;
|
||||
|
||||
/**
|
||||
* 角色信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "角色管理")
|
||||
@@ -102,11 +102,11 @@ public class SysRoleController extends BaseController
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysRole role)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
||||
if (!roleService.checkRoleNameUnique(role))
|
||||
{
|
||||
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
|
||||
else if (!roleService.checkRoleKeyUnique(role))
|
||||
{
|
||||
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||
}
|
||||
@@ -126,24 +126,24 @@ public class SysRoleController extends BaseController
|
||||
{
|
||||
roleService.checkRoleAllowed(role);
|
||||
roleService.checkRoleDataScope(role.getRoleId());
|
||||
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
||||
if (!roleService.checkRoleNameUnique(role))
|
||||
{
|
||||
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
|
||||
else if (!roleService.checkRoleKeyUnique(role))
|
||||
{
|
||||
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||
}
|
||||
role.setUpdateBy(getUsername());
|
||||
|
||||
|
||||
if (roleService.updateRole(role) > 0)
|
||||
{
|
||||
// 更新缓存用户权限
|
||||
LoginUser loginUser = getLoginUser();
|
||||
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
|
||||
{
|
||||
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
|
||||
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
|
||||
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
|
||||
tokenService.setLoginUser(loginUser);
|
||||
}
|
||||
return success();
|
||||
|
||||
@@ -1,26 +1,6 @@
|
||||
package com.fastbee.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.fastbee.common.annotation.Log;
|
||||
import com.fastbee.common.constant.UserConstants;
|
||||
import com.fastbee.common.core.controller.BaseController;
|
||||
import com.fastbee.common.core.domain.AjaxResult;
|
||||
import com.fastbee.common.core.domain.entity.SysDept;
|
||||
@@ -35,13 +15,22 @@ import com.fastbee.system.service.ISysDeptService;
|
||||
import com.fastbee.system.service.ISysPostService;
|
||||
import com.fastbee.system.service.ISysRoleService;
|
||||
import com.fastbee.system.service.ISysUserService;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "用户管理")
|
||||
@RestController
|
||||
@RequestMapping("/system/user")
|
||||
public class SysUserController extends BaseController
|
||||
@@ -61,7 +50,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 获取用户列表
|
||||
*/
|
||||
@ApiOperation("获取用户分页列表")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(SysUser user)
|
||||
@@ -71,7 +59,6 @@ public class SysUserController extends BaseController
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@ApiOperation("导出用户列表")
|
||||
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
|
||||
@PreAuthorize("@ss.hasPermi('system:user:export')")
|
||||
@PostMapping("/export")
|
||||
@@ -82,7 +69,6 @@ public class SysUserController extends BaseController
|
||||
util.exportExcel(response, list, "用户数据");
|
||||
}
|
||||
|
||||
@ApiOperation("批量导入用户")
|
||||
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
|
||||
@PreAuthorize("@ss.hasPermi('system:user:import')")
|
||||
@PostMapping("/importData")
|
||||
@@ -95,8 +81,6 @@ public class SysUserController extends BaseController
|
||||
return success(message);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("下载用户导入模板")
|
||||
@PostMapping("/importTemplate")
|
||||
public void importTemplate(HttpServletResponse response)
|
||||
{
|
||||
@@ -107,46 +91,44 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 根据用户编号获取详细信息
|
||||
*/
|
||||
@ApiOperation("根据用户编号获取详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:query')")
|
||||
@GetMapping(value = { "/", "/{userId}" })
|
||||
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
|
||||
{
|
||||
userService.checkUserDataScope(userId);
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
List<SysRole> roles = roleService.selectRoleAll();
|
||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||
ajax.put("posts", postService.selectPostAll());
|
||||
if (StringUtils.isNotNull(userId))
|
||||
{
|
||||
userService.checkUserDataScope(userId);
|
||||
SysUser sysUser = userService.selectUserById(userId);
|
||||
ajax.put(AjaxResult.DATA_TAG, sysUser);
|
||||
ajax.put("postIds", postService.selectPostListByUserId(userId));
|
||||
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
|
||||
}
|
||||
List<SysRole> roles = roleService.selectRoleAll();
|
||||
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||
ajax.put("posts", postService.selectPostAll());
|
||||
return ajax;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户
|
||||
*/
|
||||
@ApiOperation("新增用户")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:add')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysUser user)
|
||||
{
|
||||
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user)))
|
||||
deptService.checkDeptDataScope(user.getDeptId());
|
||||
roleService.checkRoleDataScope(user.getRoleIds());
|
||||
if (!userService.checkUserNameUnique(user))
|
||||
{
|
||||
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||
{
|
||||
return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||
{
|
||||
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
@@ -158,7 +140,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 修改用户
|
||||
*/
|
||||
@ApiOperation("修改用户")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@@ -166,17 +147,17 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
userService.checkUserAllowed(user);
|
||||
userService.checkUserDataScope(user.getUserId());
|
||||
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user)))
|
||||
deptService.checkDeptDataScope(user.getDeptId());
|
||||
roleService.checkRoleDataScope(user.getRoleIds());
|
||||
if (!userService.checkUserNameUnique(user))
|
||||
{
|
||||
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||
{
|
||||
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||
{
|
||||
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
@@ -187,7 +168,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
@ApiOperation("删除用户")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:remove')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{userIds}")
|
||||
@@ -203,7 +183,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
@ApiOperation("重置用户密码")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/resetPwd")
|
||||
@@ -219,7 +198,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 状态修改
|
||||
*/
|
||||
@ApiOperation("修改用户状态")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/changeStatus")
|
||||
@@ -234,7 +212,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 根据用户编号获取授权角色
|
||||
*/
|
||||
@ApiOperation("根据用户编号获取授权角色")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:query')")
|
||||
@GetMapping("/authRole/{userId}")
|
||||
public AjaxResult authRole(@PathVariable("userId") Long userId)
|
||||
@@ -250,13 +227,13 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 用户授权角色
|
||||
*/
|
||||
@ApiOperation("为用户授权角色")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.GRANT)
|
||||
@PutMapping("/authRole")
|
||||
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
||||
{
|
||||
userService.checkUserDataScope(userId);
|
||||
roleService.checkRoleDataScope(roleIds);
|
||||
userService.insertUserAuth(userId, roleIds);
|
||||
return success();
|
||||
}
|
||||
@@ -264,7 +241,6 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 获取部门树列表
|
||||
*/
|
||||
@ApiOperation("获取部门树列表")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:list')")
|
||||
@GetMapping("/deptTree")
|
||||
public AjaxResult deptTree(SysDept dept)
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.fastbee.common.annotation.Anonymous;
|
||||
import com.fastbee.iot.mapper.DeviceMapper;
|
||||
import com.fastbee.iot.model.DeviceRelateAlertLogVO;
|
||||
import com.fastbee.iot.service.IDeviceService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -22,6 +23,7 @@ import java.util.stream.Collectors;
|
||||
* @date 2023-09-13 11:42
|
||||
*/
|
||||
@Anonymous
|
||||
@Api("测试方法")
|
||||
@RestController
|
||||
@RequestMapping("/test2")
|
||||
public class TestController2 {
|
||||
|
||||
@@ -1,57 +1,50 @@
|
||||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://localhost/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: 123456
|
||||
# 从库数据源
|
||||
slave:
|
||||
enabled: false # 从数据源开关/默认关闭
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
initialSize: 5 # 初始连接数
|
||||
minIdle: 10 # 最小连接池数量
|
||||
maxActive: 20 # 最大连接池数量
|
||||
maxWait: 60000 # 配置获取连接等待超时的时间
|
||||
timeBetweenEvictionRunsMillis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000 # 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
validationQuery: SELECT 1 FROM DUAL # 配置检测连接是否有效
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: fastbee
|
||||
login-password: fastbee
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
dynamic:
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 10
|
||||
max-wait: 60000
|
||||
max-active: 20
|
||||
timeBetweenEvictionRunsMillis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000 # 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
validation-query: 'SELECT 1'
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
datasource:
|
||||
master:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: fastbee
|
||||
druid:
|
||||
filters: stat,wall
|
||||
stat:
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
none-base-statement-allow: true
|
||||
# slave:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/fastbee1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# username: root
|
||||
# password: fastbee
|
||||
|
||||
|
||||
|
||||
# redis 配置
|
||||
redis:
|
||||
host: localhost # 地址
|
||||
port: 6379 # 端口,默认为6379
|
||||
database: 1 # 数据库索引
|
||||
password: 123456 # 密码
|
||||
database: 15 # 数据库索引
|
||||
password: fastbee # 密码
|
||||
timeout: 10s # 连接超时时间
|
||||
lettuce:
|
||||
pool:
|
||||
@@ -59,20 +52,10 @@ spring:
|
||||
max-idle: 8 # 连接池中的最大空闲连接
|
||||
max-active: 8 # 连接池的最大数据库连接数
|
||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
# mqtt 配置
|
||||
mqtt:
|
||||
username: fastbee # 账号
|
||||
password: fastbee # 密码
|
||||
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
||||
client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||
default-topic: test # 默认主题
|
||||
timeout: 30 # 超时时间
|
||||
keepalive: 30 # 保持连接
|
||||
clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
||||
|
||||
# sip 配置
|
||||
sip:
|
||||
enabled: true # 是否启用视频监控SIP,true为启用
|
||||
enabled: false # 是否启用视频监控SIP,true为启用
|
||||
## 本地调试时,绑定网卡局域网IP,设备在同一局域网,设备接入IP填写绑定IP
|
||||
## 部署服务端时,默认绑定容器IP,设备接入IP填写服务器公网IP
|
||||
#ip: 177.7.0.13
|
||||
|
||||
@@ -1,52 +1,42 @@
|
||||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://177.7.0.11/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: fastbee
|
||||
# 从库数据源
|
||||
slave:
|
||||
enabled: false # 从数据源开关/默认关闭
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
dynamic:
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 10
|
||||
max-wait: 60000
|
||||
max-active: 20
|
||||
timeBetweenEvictionRunsMillis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000 # 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
validation-query: 'SELECT 1'
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
datasource:
|
||||
master:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://177.7.0.11/fastbee?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: fastbee
|
||||
druid:
|
||||
filters: stat,wall
|
||||
stat:
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
none-base-statement-allow: true
|
||||
# slave:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/fastbee1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# username: root
|
||||
# password: fastbee
|
||||
|
||||
initialSize: 5 # 初始连接数
|
||||
minIdle: 10 # 最小连接池数量
|
||||
maxActive: 20 # 最大连接池数量
|
||||
maxWait: 60000 # 配置获取连接等待超时的时间
|
||||
timeBetweenEvictionRunsMillis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000 # 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
validationQuery: SELECT 1 FROM DUAL # 配置检测连接是否有效
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: fastbee
|
||||
login-password: fastbee
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
# redis 配置
|
||||
redis:
|
||||
host: 177.7.0.10 # 地址
|
||||
@@ -60,16 +50,6 @@ spring:
|
||||
max-idle: 8 # 连接池中的最大空闲连接
|
||||
max-active: 8 # 连接池的最大数据库连接数
|
||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
# mqtt 配置
|
||||
mqtt:
|
||||
username: fastbee # 账号(仅用于后端自认证)
|
||||
password: fastbee # 密码(仅用于后端自认证)
|
||||
host-url: tcp://177.7.0.12:1883 # 连接消息服务器地址
|
||||
client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||
default-topic: test # 默认主题
|
||||
timeout: 30 # 超时时间
|
||||
keepalive: 30 # 保持连接
|
||||
clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
|
||||
|
||||
# sip 配置
|
||||
sip:
|
||||
|
||||
131
springboot/fastbee-admin/src/main/resources/application-sql.yml
Normal file
131
springboot/fastbee-admin/src/main/resources/application-sql.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
dynamic:
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 10
|
||||
max-wait: 60000
|
||||
max-active: 20
|
||||
timeBetweenEvictionRunsMillis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000 # 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
validation-query: 'SELECT 1'
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
datasource:
|
||||
master:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: dm.jdbc.driver.DmDriver
|
||||
url: jdbc:dm://192.168.5.12:5236/OPENSOURCE&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
|
||||
username: OPENSOURCE
|
||||
password: fastbee@123
|
||||
druid:
|
||||
filters: stat
|
||||
stat:
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
none-base-statement-allow: true
|
||||
# sqlServer: # 配置 SQLServer 数据源
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
# url: jdbc:sqlserver://localhost:1433;databaseName=fastbee
|
||||
# username: sa
|
||||
# password: fastbee@123
|
||||
# postgres: # 配置 postgres 数据源
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://101.33.237.12:5432/fastbee?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||
# username: root
|
||||
# password: fastbee@123
|
||||
# dameng: # 配置达梦数据源
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: dm.jdbc.driver.DmDriver
|
||||
# url: jdbc:dm://192.168.5.28:5236/fastbee&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
|
||||
# username: root
|
||||
# password: fastbee@123
|
||||
# druid:
|
||||
# filters: stat
|
||||
# slave:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/fastbee1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# username: root
|
||||
# password: fastbee
|
||||
# slave:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/fastbee1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# username: root
|
||||
# password: fastbee
|
||||
|
||||
|
||||
|
||||
# redis 配置
|
||||
redis:
|
||||
host: 81.71.97.58 # 地址
|
||||
port: 6379 # 端口,默认为6379
|
||||
database: 11 # 数据库索引
|
||||
password: fastbee # 密码
|
||||
timeout: 10s # 连接超时时间
|
||||
lettuce:
|
||||
pool:
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
max-idle: 8 # 连接池中的最大空闲连接
|
||||
max-active: 8 # 连接池的最大数据库连接数
|
||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
|
||||
# sip 配置
|
||||
sip:
|
||||
enabled: false # 是否启用视频监控SIP,true为启用
|
||||
## 本地调试时,绑定网卡局域网IP,设备在同一局域网,设备接入IP填写绑定IP
|
||||
## 部署服务端时,默认绑定容器IP,设备接入IP填写服务器公网IP
|
||||
#ip: 177.7.0.13
|
||||
ip: 192.168.5.27
|
||||
port: 5061 # SIP端口(保持默认)
|
||||
domain: 3402000000 # 由省级、市级、区级、基层编号组成
|
||||
id: 34020000002000000001 # 同上,另外增加编号,(可保持默认)
|
||||
password: 12345678 # 监控设备接入的密码
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
com.fastbee: debug
|
||||
org.springframework: warn
|
||||
|
||||
# Swagger配置
|
||||
swagger:
|
||||
enabled: true # 是否开启swagger
|
||||
pathMapping: /dev-api # 请求前缀
|
||||
|
||||
liteflow:
|
||||
rule-source-ext-data-map:
|
||||
# 应用名称,规则链和脚本组件名称需要一致,不要修改
|
||||
applicationName: fastbee
|
||||
#是否开启SQL日志
|
||||
sqlLogEnabled: true
|
||||
# 规则多时,启用快速加载模式
|
||||
fast-load: false
|
||||
#是否开启SQL数据轮询自动刷新机制 默认不开启
|
||||
pollingEnabled: false
|
||||
pollingIntervalSeconds: 60
|
||||
pollingStartSeconds: 60
|
||||
#以下是chain表的配置
|
||||
chainTableName: iot_scene
|
||||
chainApplicationNameField: application_name
|
||||
chainNameField: chain_name
|
||||
elDataField: el_data
|
||||
chainEnableField: enable
|
||||
#以下是script表的配置
|
||||
scriptTableName: iot_script
|
||||
scriptApplicationNameField: application_name
|
||||
scriptIdField: script_id
|
||||
scriptNameField: script_name
|
||||
scriptDataField: script_data
|
||||
scriptTypeField: script_type
|
||||
scriptLanguageField: script_language
|
||||
scriptEnableField: enable
|
||||
@@ -1,11 +1,11 @@
|
||||
# 项目相关配置
|
||||
fastbee:
|
||||
name: fastbee # 名称
|
||||
version: 3.8.5 # 版本
|
||||
copyrightYear: 2023 # 版权年份
|
||||
version: 2.1.0 # 版本
|
||||
copyrightYear: 2024 # 版权年份
|
||||
demoEnabled: true # 实例演示开关
|
||||
# 文件路径,以uploadPath结尾 示例( Windows配置 D:/uploadPath,Linux配置 /uploadPath)
|
||||
profile: /uploadPath
|
||||
profile: D:/uploadPath
|
||||
addressEnabled: true # 获取ip地址开关
|
||||
captchaType: math # 验证码类型 math 数组计算 char 字符验证
|
||||
|
||||
@@ -22,19 +22,17 @@ server:
|
||||
min-spare: 100 # Tomcat启动初始化的线程数,默认值10
|
||||
# 基于netty的服务器
|
||||
broker:
|
||||
must-pass: false # 客户端连接是否需要密码
|
||||
enabled: true # mqttBroker类型选择, true: 基于netty的mqttBroker和webSocket false: emq的mqttBroker
|
||||
broker-node: node1
|
||||
port: 1883
|
||||
websocket-port: 8083
|
||||
websocket-path: /mqtt
|
||||
keep-alive: 70 # 默认的全部客户端心跳上传时间
|
||||
keep-alive: 70 # 默认的全部客户端心跳上传时间
|
||||
|
||||
# Spring配置
|
||||
spring:
|
||||
# 环境配置,dev=开发环境,prod=生产环境
|
||||
profiles:
|
||||
active: prod # 环境配置,dev=开发环境,prod=生产环境
|
||||
active: dev # 环境配置,dev=开发环境,prod=生产环境
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
@@ -55,12 +53,20 @@ spring:
|
||||
max-size: 200 # 最大连接数
|
||||
queue-capacity: 3000 # 最大容量
|
||||
keep-alive: 60
|
||||
|
||||
#集群配置
|
||||
cluster:
|
||||
enable: true
|
||||
type: redis
|
||||
|
||||
datasource:
|
||||
druid:
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
loginUsername: fastbee
|
||||
loginPassword: fastbee
|
||||
dynamic:
|
||||
primary: master
|
||||
strict: false
|
||||
lazy: true
|
||||
|
||||
# 用户配置
|
||||
user:
|
||||
|
||||
@@ -9,13 +9,14 @@ user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分
|
||||
user.password.delete=对不起,您的账号已被删除
|
||||
user.blocked=用户已封禁,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
login.blocked=很遗憾,访问IP已被列入系统黑名单
|
||||
user.logout.success=退出成功
|
||||
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
|
||||
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
|
||||
user.password.not.valid=* 5-50个字符
|
||||
|
||||
|
||||
user.email.not.valid=邮箱格式错误
|
||||
user.mobile.phone.number.not.valid=手机号格式错误
|
||||
user.login.success=登录成功
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="/logs" />
|
||||
<property name="log.path" scope="context" value="D:/logs" />
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||
|
||||
@@ -95,6 +95,24 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 规则引擎日志输出 -->
|
||||
<appender name="script" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/rule/script.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 按天回滚 daily -->
|
||||
<fileNamePattern>${log.path}/rule/script.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 3天 -->
|
||||
<maxHistory>3</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%method,%line] - %msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.fastbee" level="debug" />
|
||||
<!-- Spring日志级别控制 -->
|
||||
@@ -115,4 +133,10 @@
|
||||
<logger name="sys-user" level="info">
|
||||
<appender-ref ref="sys-user"/>
|
||||
</logger>
|
||||
</configuration>
|
||||
|
||||
<!--规则引擎日志-->
|
||||
<logger name="script" level="info">
|
||||
<appender-ref ref="script"/>
|
||||
</logger>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -14,7 +14,9 @@ PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
|
||||
<!-- 指定 MyBatis 所用日志的具体实现 -->
|
||||
<setting name="logImpl" value="SLF4J" />
|
||||
<!-- 使用驼峰命名法转换字段 -->
|
||||
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
|
||||
<setting name="mapUnderscoreToCamelCase" value="true"/>
|
||||
<setting name="autoMappingBehavior" value="FULL"/>
|
||||
<setting name="autoMappingUnknownColumnBehavior" value="NONE"/>
|
||||
</settings>
|
||||
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>fastbee</artifactId>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<version>3.8.5</version>
|
||||
<version>${fastbee.version}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId>
|
||||
@@ -74,7 +75,6 @@
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>3.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
@@ -150,20 +150,11 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.2.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.2.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package com.fastbee.common.annotation;
|
||||
|
||||
import com.fastbee.common.utils.poi.ExcelHandlerAdapter;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.math.BigDecimal;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import com.fastbee.common.utils.poi.ExcelHandlerAdapter;
|
||||
|
||||
/**
|
||||
* 自定义导出Excel数据注解
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -59,12 +60,12 @@ public @interface Excel
|
||||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||
|
||||
/**
|
||||
* 导出时在excel中每个列的高度 单位为字符
|
||||
* 导出时在excel中每个列的高度
|
||||
*/
|
||||
public double height() default 14;
|
||||
|
||||
/**
|
||||
* 导出时在excel中每个列的宽 单位为字符
|
||||
* 导出时在excel中每个列的宽度
|
||||
*/
|
||||
public double width() default 16;
|
||||
|
||||
@@ -83,11 +84,21 @@ public @interface Excel
|
||||
*/
|
||||
public String prompt() default "";
|
||||
|
||||
/**
|
||||
* 是否允许内容换行
|
||||
*/
|
||||
public boolean wrapText() default false;
|
||||
|
||||
/**
|
||||
* 设置只能选择不能输入的列内容.
|
||||
*/
|
||||
public String[] combo() default {};
|
||||
|
||||
/**
|
||||
* 是否从字典读数据到combo,默认不读取,如读取需要设置dictType注解.
|
||||
*/
|
||||
public boolean comboReadDict() default false;
|
||||
|
||||
/**
|
||||
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
|
||||
*/
|
||||
@@ -114,7 +125,7 @@ public @interface Excel
|
||||
public ColumnType cellType() default ColumnType.STRING;
|
||||
|
||||
/**
|
||||
* 导出列头背景色
|
||||
* 导出列头背景颜色
|
||||
*/
|
||||
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
|
||||
|
||||
@@ -124,7 +135,7 @@ public @interface Excel
|
||||
public IndexedColors headerColor() default IndexedColors.WHITE;
|
||||
|
||||
/**
|
||||
* 导出单元格背景色
|
||||
* 导出单元格背景颜色
|
||||
*/
|
||||
public IndexedColors backgroundColor() default IndexedColors.WHITE;
|
||||
|
||||
@@ -171,7 +182,7 @@ public @interface Excel
|
||||
|
||||
public enum ColumnType
|
||||
{
|
||||
NUMERIC(0), STRING(1), IMAGE(2);
|
||||
NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
|
||||
private final int value;
|
||||
|
||||
ColumnType(int value)
|
||||
@@ -184,4 +195,4 @@ public @interface Excel
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package com.fastbee.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import com.fastbee.common.enums.BusinessType;
|
||||
import com.fastbee.common.enums.OperatorType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义操作日志记录注解
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@@ -20,7 +17,7 @@ import com.fastbee.common.enums.OperatorType;
|
||||
public @interface Log
|
||||
{
|
||||
/**
|
||||
* 模块
|
||||
* 模块
|
||||
*/
|
||||
public String title() default "";
|
||||
|
||||
@@ -43,4 +40,9 @@ public @interface Log
|
||||
* 是否保存响应的参数
|
||||
*/
|
||||
public boolean isSaveResponseData() default true;
|
||||
|
||||
/**
|
||||
* 排除指定的请求参数
|
||||
*/
|
||||
public String[] excludeParamNames() default {};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.fastbee.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fastbee.common.config.serializer.SensitiveJsonSerializer;
|
||||
import com.fastbee.common.enums.DesensitizedType;
|
||||
|
||||
/**
|
||||
* 数据脱敏注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@JacksonAnnotationsInside
|
||||
@JsonSerialize(using = SensitiveJsonSerializer.class)
|
||||
public @interface Sensitive
|
||||
{
|
||||
DesensitizedType desensitizedType();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.fastbee.common.config.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
import com.fastbee.common.annotation.Sensitive;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.enums.DesensitizedType;
|
||||
import com.fastbee.common.utils.SecurityUtils;
|
||||
|
||||
/**
|
||||
* 数据脱敏序列化过滤
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
|
||||
{
|
||||
private DesensitizedType desensitizedType;
|
||||
|
||||
@Override
|
||||
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
|
||||
{
|
||||
if (desensitization())
|
||||
{
|
||||
gen.writeString(desensitizedType.desensitizer().apply(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
gen.writeString(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
|
||||
throws JsonMappingException
|
||||
{
|
||||
Sensitive annotation = property.getAnnotation(Sensitive.class);
|
||||
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
|
||||
{
|
||||
this.desensitizedType = annotation.desensitizedType();
|
||||
return this;
|
||||
}
|
||||
return prov.findValueSerializer(property.getType(), property);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否需要脱敏处理
|
||||
*/
|
||||
private boolean desensitization()
|
||||
{
|
||||
try
|
||||
{
|
||||
LoginUser securityUser = SecurityUtils.getLoginUser();
|
||||
// 管理员不脱敏
|
||||
return !securityUser.getUser().isAdmin();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@ package com.fastbee.common.constant;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 通用常量信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Constants
|
||||
@@ -19,6 +21,11 @@ public class Constants
|
||||
*/
|
||||
public static final String GBK = "GBK";
|
||||
|
||||
/**
|
||||
* 系统语言
|
||||
*/
|
||||
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
|
||||
|
||||
/**
|
||||
* www主域
|
||||
*/
|
||||
@@ -63,7 +70,27 @@ public class Constants
|
||||
* 登录失败
|
||||
*/
|
||||
public static final String LOGIN_FAIL = "Error";
|
||||
|
||||
|
||||
/**
|
||||
* 所有权限标识
|
||||
*/
|
||||
public static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/**
|
||||
* 管理员角色权限标识
|
||||
*/
|
||||
public static final String SUPER_ADMIN = "admin";
|
||||
|
||||
/**
|
||||
* 角色权限分隔符
|
||||
*/
|
||||
public static final String ROLE_DELIMETER = ",";
|
||||
|
||||
/**
|
||||
* 权限标识分隔符
|
||||
*/
|
||||
public static final String PERMISSION_DELIMETER = ",";
|
||||
|
||||
/**
|
||||
* 验证码有效期(分钟)
|
||||
*/
|
||||
@@ -129,14 +156,19 @@ public class Constants
|
||||
*/
|
||||
public static final String LOOKUP_LDAPS = "ldaps:";
|
||||
|
||||
/**
|
||||
* 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||
*/
|
||||
public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
|
||||
|
||||
/**
|
||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||
*/
|
||||
public static final String[] JOB_WHITELIST_STR = { "com.fastbee" };
|
||||
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
|
||||
|
||||
/**
|
||||
* 定时任务违规的字符
|
||||
*/
|
||||
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||
"org.springframework", "org.apache", "com.fastbee.common.utils.file", "com.fastbee.common.config" };
|
||||
"org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.fastbee.common.constant;
|
||||
|
||||
/**
|
||||
* 用户常量信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UserConstants
|
||||
@@ -21,6 +21,9 @@ public class UserConstants
|
||||
/** 用户封禁状态 */
|
||||
public static final String USER_DISABLE = "1";
|
||||
|
||||
/** 角色正常状态 */
|
||||
public static final String ROLE_NORMAL = "0";
|
||||
|
||||
/** 角色封禁状态 */
|
||||
public static final String ROLE_DISABLE = "1";
|
||||
|
||||
@@ -53,16 +56,16 @@ public class UserConstants
|
||||
|
||||
/** Layout组件标识 */
|
||||
public final static String LAYOUT = "Layout";
|
||||
|
||||
|
||||
/** ParentView组件标识 */
|
||||
public final static String PARENT_VIEW = "ParentView";
|
||||
|
||||
/** InnerLink组件标识 */
|
||||
public final static String INNER_LINK = "InnerLink";
|
||||
|
||||
/** 校验返回结果码 */
|
||||
public final static String UNIQUE = "0";
|
||||
public final static String NOT_UNIQUE = "1";
|
||||
/** 校验是否唯一的返回标识 */
|
||||
public final static boolean UNIQUE = true;
|
||||
public final static boolean NOT_UNIQUE = false;
|
||||
|
||||
/**
|
||||
* 用户名长度限制
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.fastbee.common.core.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import com.fastbee.common.constant.HttpStatus;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 操作消息提醒
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AjaxResult extends HashMap<String, Object>
|
||||
@@ -31,7 +32,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象
|
||||
*
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
*/
|
||||
@@ -43,7 +44,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象
|
||||
*
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
@@ -79,7 +80,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success()
|
||||
@@ -89,7 +90,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回成功数据
|
||||
*
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(Object data)
|
||||
@@ -109,7 +110,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 成功消息
|
||||
*/
|
||||
@@ -120,7 +121,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 成功消息
|
||||
@@ -155,7 +156,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
*
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error()
|
||||
@@ -165,7 +166,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
@@ -176,7 +177,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 错误消息
|
||||
@@ -188,7 +189,7 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
* @return 错误消息
|
||||
@@ -198,6 +199,36 @@ public class AjaxResult extends HashMap<String, Object>
|
||||
return new AjaxResult(code, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为成功消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为警告消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isWarn()
|
||||
{
|
||||
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为错误消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isError()
|
||||
{
|
||||
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便链式调用
|
||||
*
|
||||
|
||||
@@ -1,126 +1,175 @@
|
||||
package com.fastbee.common.core.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class BaseEntity implements Serializable
|
||||
{
|
||||
public class BaseEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 搜索值 */
|
||||
/**
|
||||
* 搜索值
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty("搜索值")
|
||||
@JsonIgnore
|
||||
private String searchValue;
|
||||
|
||||
/** 创建者 */
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@ApiModelProperty("创建者")
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ApiModelProperty("创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@ApiModelProperty("更新者")
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ApiModelProperty("更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/** 备注 */
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
/** 请求参数 */
|
||||
/**
|
||||
* 当前记录起始索引 默认值
|
||||
*/
|
||||
public static final int DEFAULT_PAGE_NUM = 1;
|
||||
|
||||
/**
|
||||
* 每页显示记录数 默认值 默认查全部
|
||||
*/
|
||||
public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* 构建分页对象
|
||||
*/
|
||||
public <T> Page<T> buildPage() {
|
||||
Integer pageNum = ObjectUtil.defaultIfNull(this.pageNum, DEFAULT_PAGE_NUM);
|
||||
Integer pageSize = ObjectUtil.defaultIfNull(this.pageSize, DEFAULT_PAGE_SIZE);
|
||||
if (pageNum <= 0) {
|
||||
pageNum = DEFAULT_PAGE_NUM;
|
||||
}
|
||||
Page<T> page = new Page<>(pageNum, pageSize);
|
||||
return page;
|
||||
}
|
||||
|
||||
public Integer getPageNum() {
|
||||
return ObjectUtil.defaultIfNull(this.pageNum, DEFAULT_PAGE_NUM);
|
||||
}
|
||||
|
||||
public void setPageNum(Integer pageNum) {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return ObjectUtil.defaultIfNull(this.pageSize, DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
@TableField(exist = false)
|
||||
private Integer pageNum;
|
||||
|
||||
@TableField(exist = false)
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty("请求参数")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private Map<String, Object> params;
|
||||
|
||||
public String getSearchValue()
|
||||
{
|
||||
public String getSearchValue() {
|
||||
return searchValue;
|
||||
}
|
||||
|
||||
public void setSearchValue(String searchValue)
|
||||
{
|
||||
public void setSearchValue(String searchValue) {
|
||||
this.searchValue = searchValue;
|
||||
}
|
||||
|
||||
public String getCreateBy()
|
||||
{
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy)
|
||||
{
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public Date getCreateTime()
|
||||
{
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime)
|
||||
{
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getUpdateBy()
|
||||
{
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy)
|
||||
{
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public Date getUpdateTime()
|
||||
{
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime)
|
||||
{
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getRemark()
|
||||
{
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParams()
|
||||
{
|
||||
if (params == null)
|
||||
{
|
||||
public Map<String, Object> getParams() {
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Map<String, Object> params)
|
||||
{
|
||||
public void setParams(Map<String, Object> params) {
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.fastbee.common.core.domain;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author admin
|
||||
* @version 1.0
|
||||
* @description: 分页参数基础类
|
||||
* @date 2024-11-15 18:00
|
||||
*/
|
||||
@Data
|
||||
public class PageEntity implements Serializable {
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
||||
@TableField(exist = false)
|
||||
private Integer pageNum;
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
||||
@TableField(exist = false)
|
||||
private Integer pageSize;
|
||||
/**
|
||||
* 当前记录起始索引 默认值
|
||||
*/
|
||||
public static final int DEFAULT_PAGE_NUM = 1;
|
||||
|
||||
/**
|
||||
* 每页显示记录数 默认值 默认查全部
|
||||
*/
|
||||
public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* 构建分页对象
|
||||
*/
|
||||
public <T> Page<T> buildPage() {
|
||||
Integer pageNum = ObjectUtil.defaultIfNull(this.pageNum, DEFAULT_PAGE_NUM);
|
||||
Integer pageSize = ObjectUtil.defaultIfNull(this.pageSize, DEFAULT_PAGE_SIZE);
|
||||
if (pageNum <= 0) {
|
||||
pageNum = DEFAULT_PAGE_NUM;
|
||||
}
|
||||
Page<T> page = new Page<>(pageNum, pageSize);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty("请求参数")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private Map<String, Object> params;
|
||||
|
||||
public Map<String, Object> getParams() {
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public Integer getPageNum() {
|
||||
return ObjectUtil.defaultIfNull(this.pageNum, DEFAULT_PAGE_NUM);
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return ObjectUtil.defaultIfNull(this.pageSize, DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import com.fastbee.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 菜单权限表 sys_menu
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@ApiModel(value = "SysMenu", description = "菜单权限表 sys_menu")
|
||||
@@ -54,6 +54,9 @@ public class SysMenu extends BaseEntity
|
||||
@ApiModelProperty("路由参数")
|
||||
private String query;
|
||||
|
||||
/** 路由名称,默认和路由地址相同的驼峰格式(注意:因为vue3版本的router会删除名称相同路由,为避免名字的冲突,特殊情况可以自定义) */
|
||||
private String routeName;
|
||||
|
||||
/** 是否为外链(0是 1否) */
|
||||
@ApiModelProperty("是否为外链(0是 1否)")
|
||||
private String isFrame;
|
||||
@@ -69,7 +72,7 @@ public class SysMenu extends BaseEntity
|
||||
/** 显示状态(0显示 1隐藏) */
|
||||
@ApiModelProperty("显示状态(0显示 1隐藏)")
|
||||
private String visible;
|
||||
|
||||
|
||||
/** 菜单状态(0正常 1停用) */
|
||||
@ApiModelProperty("菜单状态(0正常 1停用)")
|
||||
private String status;
|
||||
@@ -171,6 +174,16 @@ public class SysMenu extends BaseEntity
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public String getRouteName()
|
||||
{
|
||||
return routeName;
|
||||
}
|
||||
|
||||
public void setRouteName(String routeName)
|
||||
{
|
||||
this.routeName = routeName;
|
||||
}
|
||||
|
||||
public String getIsFrame()
|
||||
{
|
||||
return isFrame;
|
||||
@@ -252,7 +265,7 @@ public class SysMenu extends BaseEntity
|
||||
{
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
@@ -262,6 +275,8 @@ public class SysMenu extends BaseEntity
|
||||
.append("orderNum", getOrderNum())
|
||||
.append("path", getPath())
|
||||
.append("component", getComponent())
|
||||
.append("query", getQuery())
|
||||
.append("routeName", getRouteName())
|
||||
.append("isFrame", getIsFrame())
|
||||
.append("IsCache", getIsCache())
|
||||
.append("menuType", getMenuType())
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.fastbee.common.xss.Xss;
|
||||
|
||||
/**
|
||||
* 用户对象 sys_user
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@ApiModel(value = "SysUser", description = "用户对象 sys_user")
|
||||
@@ -27,7 +27,7 @@ public class SysUser extends BaseEntity
|
||||
|
||||
/** 用户ID */
|
||||
@ApiModelProperty("用户ID")
|
||||
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
||||
@Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
||||
private Long userId;
|
||||
|
||||
/** 部门ID */
|
||||
@@ -52,7 +52,7 @@ public class SysUser extends BaseEntity
|
||||
|
||||
/** 手机号码 */
|
||||
@ApiModelProperty("手机号码")
|
||||
@Excel(name = "手机号码")
|
||||
@Excel(name = "手机号码", cellType = ColumnType.TEXT)
|
||||
private String phonenumber;
|
||||
|
||||
/** 用户性别 */
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package com.fastbee.common.core.domain.model;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
|
||||
/**
|
||||
* 登录用户身份权限
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class LoginUser implements UserDetails
|
||||
{
|
||||
public class LoginUser implements UserDetails {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -31,6 +31,9 @@ public class LoginUser implements UserDetails
|
||||
*/
|
||||
private String token;
|
||||
|
||||
|
||||
private String requestToken;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
@@ -71,64 +74,100 @@ public class LoginUser implements UserDetails
|
||||
*/
|
||||
private SysUser user;
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
private String language;
|
||||
|
||||
private Long deptUserId;
|
||||
|
||||
private Boolean neverExpire = Boolean.FALSE;
|
||||
|
||||
public LoginUser() {
|
||||
}
|
||||
|
||||
public LoginUser(SysUser user, Set<String> permissions) {
|
||||
this.user = user;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions) {
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
this.user = user;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public LoginUser(Long userId, Long deptId, String language, SysUser user, Set<String> permissions) {
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
this.user = user;
|
||||
this.language = language;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public Boolean getNeverExpire() {
|
||||
return neverExpire;
|
||||
}
|
||||
|
||||
public void setNeverExpire(Boolean neverExpire) {
|
||||
this.neverExpire = neverExpire;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public Long getDeptUserId() {
|
||||
return deptUserId;
|
||||
}
|
||||
|
||||
public void setDeptUserId(Long deptUserId) {
|
||||
this.deptUserId = deptUserId;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId)
|
||||
{
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getDeptId()
|
||||
{
|
||||
public Long getDeptId() {
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(Long deptId)
|
||||
{
|
||||
public void setDeptId(Long deptId) {
|
||||
this.deptId = deptId;
|
||||
}
|
||||
|
||||
public String getToken()
|
||||
{
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token)
|
||||
{
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public LoginUser()
|
||||
{
|
||||
public String getRequestToken() {
|
||||
return requestToken;
|
||||
}
|
||||
|
||||
public LoginUser(SysUser user, Set<String> permissions)
|
||||
{
|
||||
this.user = user;
|
||||
this.permissions = permissions;
|
||||
public void setRequestToken(String requestToken) {
|
||||
this.requestToken = requestToken;
|
||||
}
|
||||
|
||||
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
|
||||
{
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
this.user = user;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public String getPassword()
|
||||
{
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername()
|
||||
{
|
||||
public String getUsername() {
|
||||
return user.getUserName();
|
||||
}
|
||||
|
||||
@@ -137,130 +176,109 @@ public class LoginUser implements UserDetails
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isAccountNonExpired()
|
||||
{
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户是否解锁,锁定的用户无法进行身份验证
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isAccountNonLocked()
|
||||
{
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired()
|
||||
{
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可用 ,禁用的用户不能身份验证
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Long getLoginTime()
|
||||
{
|
||||
public Long getLoginTime() {
|
||||
return loginTime;
|
||||
}
|
||||
|
||||
public void setLoginTime(Long loginTime)
|
||||
{
|
||||
public void setLoginTime(Long loginTime) {
|
||||
this.loginTime = loginTime;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
public String getIpaddr() {
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
public void setIpaddr(String ipaddr) {
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLoginLocation()
|
||||
{
|
||||
public String getLoginLocation() {
|
||||
return loginLocation;
|
||||
}
|
||||
|
||||
public void setLoginLocation(String loginLocation)
|
||||
{
|
||||
public void setLoginLocation(String loginLocation) {
|
||||
this.loginLocation = loginLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
public String getBrowser() {
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
public void setBrowser(String browser) {
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
public String getOs() {
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
public void setOs(String os) {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public Long getExpireTime()
|
||||
{
|
||||
public Long getExpireTime() {
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
public void setExpireTime(Long expireTime)
|
||||
{
|
||||
public void setExpireTime(Long expireTime) {
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions()
|
||||
{
|
||||
public Set<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(Set<String> permissions)
|
||||
{
|
||||
public void setPermissions(Set<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public SysUser getUser()
|
||||
{
|
||||
public SysUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(SysUser user)
|
||||
{
|
||||
public void setUser(SysUser user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities()
|
||||
{
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
package com.fastbee.common.core.page;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.sql.SqlUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页数据
|
||||
@@ -24,6 +33,16 @@ public class PageDomain
|
||||
/** 分页参数合理化 */
|
||||
private Boolean reasonable = true;
|
||||
|
||||
/**
|
||||
* 当前记录起始索引 默认值
|
||||
*/
|
||||
public static final int DEFAULT_PAGE_NUM = 1;
|
||||
|
||||
/**
|
||||
* 每页显示记录数 默认值 默认查全部
|
||||
*/
|
||||
public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
|
||||
|
||||
public String getOrderBy()
|
||||
{
|
||||
if (StringUtils.isEmpty(orderByColumn))
|
||||
@@ -33,6 +52,64 @@ public class PageDomain
|
||||
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建分页对象
|
||||
*/
|
||||
public <T> Page<T> build() {
|
||||
Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
|
||||
Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
|
||||
if (pageNum <= 0) {
|
||||
pageNum = DEFAULT_PAGE_NUM;
|
||||
}
|
||||
Page<T> page = new Page<>(pageNum, pageSize);
|
||||
List<OrderItem> orderItems = buildOrderItem();
|
||||
if (CollUtil.isNotEmpty(orderItems)) {
|
||||
page.addOrder(orderItems);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建排序
|
||||
*
|
||||
* 支持的用法如下:
|
||||
* {isAsc:"asc",orderByColumn:"id"} order by id asc
|
||||
* {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc
|
||||
* {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc
|
||||
* {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc
|
||||
*/
|
||||
private List<OrderItem> buildOrderItem() {
|
||||
if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) {
|
||||
return null;
|
||||
}
|
||||
String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
|
||||
orderBy = StringUtils.toUnderScoreCase(orderBy);
|
||||
|
||||
// 兼容前端排序类型
|
||||
isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"});
|
||||
|
||||
String[] orderByArr = orderBy.split(StringUtils.SLASH);
|
||||
String[] isAscArr = isAsc.split(StringUtils.SLASH);
|
||||
if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) {
|
||||
throw new ServiceException("排序参数有误");
|
||||
}
|
||||
|
||||
List<OrderItem> list = new ArrayList<>();
|
||||
// 每个字段各自排序
|
||||
for (int i = 0; i < orderByArr.length; i++) {
|
||||
String orderByStr = orderByArr[i];
|
||||
String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i];
|
||||
if ("asc".equals(isAscStr)) {
|
||||
list.add(OrderItem.asc(orderByStr));
|
||||
} else if ("desc".equals(isAscStr)) {
|
||||
list.add(OrderItem.desc(orderByStr));
|
||||
} else {
|
||||
throw new ServiceException("排序参数有误");
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Integer getPageNum()
|
||||
{
|
||||
return pageNum;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.fastbee.common.core.page;
|
||||
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@@ -43,6 +46,40 @@ public class TableDataInfo implements Serializable
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分页对象构建表格分页数据对象
|
||||
*/
|
||||
public static <T> TableDataInfo build(IPage<T> page) {
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
rspData.setCode(HttpStatus.HTTP_OK);
|
||||
rspData.setMsg("查询成功");
|
||||
rspData.setRows(page.getRecords());
|
||||
rspData.setTotal(page.getTotal());
|
||||
return rspData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数据列表构建表格分页数据对象
|
||||
*/
|
||||
public static <T> TableDataInfo build(List<T> list) {
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
rspData.setCode(HttpStatus.HTTP_OK);
|
||||
rspData.setMsg("查询成功");
|
||||
rspData.setRows(list);
|
||||
rspData.setTotal(list.size());
|
||||
return rspData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建表格分页数据对象
|
||||
*/
|
||||
public static <T> TableDataInfo build() {
|
||||
TableDataInfo rspData = new TableDataInfo();
|
||||
rspData.setCode(HttpStatus.HTTP_OK);
|
||||
rspData.setMsg("查询成功");
|
||||
return rspData;
|
||||
}
|
||||
|
||||
public long getTotal()
|
||||
{
|
||||
return total;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.fastbee.common.core.text;
|
||||
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Set;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
/**
|
||||
* 类型转换器
|
||||
@@ -364,6 +365,10 @@ public class Convert
|
||||
*/
|
||||
public static String[] toStrArray(String str)
|
||||
{
|
||||
if (StringUtils.isEmpty(str))
|
||||
{
|
||||
return new String[] {};
|
||||
}
|
||||
return toStrArray(",", str);
|
||||
}
|
||||
|
||||
@@ -536,7 +541,7 @@ public class Convert
|
||||
|
||||
/**
|
||||
* 转换为boolean<br>
|
||||
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* String支持的值为:true、false、yes、ok、no、1、0、是、否, 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
@@ -565,10 +570,12 @@ public class Convert
|
||||
case "yes":
|
||||
case "ok":
|
||||
case "1":
|
||||
case "是":
|
||||
return true;
|
||||
case "false":
|
||||
case "no":
|
||||
case "0":
|
||||
case "否":
|
||||
return false;
|
||||
default:
|
||||
return defaultValue;
|
||||
@@ -791,14 +798,23 @@ public class Convert
|
||||
{
|
||||
return (String) obj;
|
||||
}
|
||||
else if (obj instanceof byte[])
|
||||
else if (obj instanceof byte[] || obj instanceof Byte[])
|
||||
{
|
||||
return str((byte[]) obj, charset);
|
||||
}
|
||||
else if (obj instanceof Byte[])
|
||||
{
|
||||
byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
|
||||
return str(bytes, charset);
|
||||
if (obj instanceof byte[])
|
||||
{
|
||||
return str((byte[]) obj, charset);
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte[] bytes = (Byte[]) obj;
|
||||
int length = bytes.length;
|
||||
byte[] dest = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
dest[i] = bytes[i];
|
||||
}
|
||||
return str(dest, charset);
|
||||
}
|
||||
}
|
||||
else if (obj instanceof ByteBuffer)
|
||||
{
|
||||
@@ -954,9 +970,7 @@ public class Convert
|
||||
c[i] = (char) (c[i] - 65248);
|
||||
}
|
||||
}
|
||||
String returnString = new String(c);
|
||||
|
||||
return returnString;
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -977,7 +991,12 @@ public class Convert
|
||||
String s = "";
|
||||
for (int i = 0; i < fraction.length; i++)
|
||||
{
|
||||
s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
|
||||
// 优化double计算精度丢失问题
|
||||
BigDecimal nNum = new BigDecimal(n);
|
||||
BigDecimal decimal = new BigDecimal(10);
|
||||
BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
|
||||
double d = scale.doubleValue();
|
||||
s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
|
||||
}
|
||||
if (s.length() < 1)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.fastbee.common.enums;
|
||||
|
||||
import com.fastbee.common.utils.DesensitizedUtil;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 脱敏类型
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public enum DesensitizedType
|
||||
{
|
||||
/**
|
||||
* 姓名,第2位星号替换
|
||||
*/
|
||||
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
|
||||
|
||||
/**
|
||||
* 密码,全部字符都用*代替
|
||||
*/
|
||||
PASSWORD(DesensitizedUtil::password),
|
||||
|
||||
/**
|
||||
* 身份证,中间10位星号替换
|
||||
*/
|
||||
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
|
||||
|
||||
/**
|
||||
* 手机号,中间4位星号替换
|
||||
*/
|
||||
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
|
||||
|
||||
/**
|
||||
* 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
|
||||
*/
|
||||
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
|
||||
|
||||
/**
|
||||
* 银行卡号,保留最后4位,其他星号替换
|
||||
*/
|
||||
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
|
||||
|
||||
/**
|
||||
* 车牌号码,包含普通车辆、新能源车辆
|
||||
*/
|
||||
CAR_LICENSE(DesensitizedUtil::carLicense);
|
||||
|
||||
private final Function<String, String> desensitizer;
|
||||
|
||||
DesensitizedType(Function<String, String> desensitizer)
|
||||
{
|
||||
this.desensitizer = desensitizer;
|
||||
}
|
||||
|
||||
public Function<String, String> desensitizer()
|
||||
{
|
||||
return desensitizer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.fastbee.common.exception.file;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* 文件上传异常类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FileUploadException extends Exception
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Throwable cause;
|
||||
|
||||
public FileUploadException()
|
||||
{
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public FileUploadException(final String msg)
|
||||
{
|
||||
this(msg, null);
|
||||
}
|
||||
|
||||
public FileUploadException(String msg, Throwable cause)
|
||||
{
|
||||
super(msg);
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintStream stream)
|
||||
{
|
||||
super.printStackTrace(stream);
|
||||
if (cause != null)
|
||||
{
|
||||
stream.println("Caused by:");
|
||||
cause.printStackTrace(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter writer)
|
||||
{
|
||||
super.printStackTrace(writer);
|
||||
if (cause != null)
|
||||
{
|
||||
writer.println("Caused by:");
|
||||
cause.printStackTrace(writer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable getCause()
|
||||
{
|
||||
return cause;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.fastbee.common.exception.user;
|
||||
|
||||
/**
|
||||
* 黑名单IP异常类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class BlackListException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public BlackListException()
|
||||
{
|
||||
super("login.blocked", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.fastbee.common.exception.user;
|
||||
|
||||
/**
|
||||
* 用户不存在异常类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class UserNotExistsException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UserNotExistsException()
|
||||
{
|
||||
super("user.not.exists", null);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import com.fastbee.common.enums.HttpMethod;
|
||||
|
||||
/**
|
||||
* 防止XSS攻击的过滤器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class XssFilter implements Filter
|
||||
@@ -32,10 +32,10 @@ public class XssFilter implements Filter
|
||||
String tempExcludes = filterConfig.getInitParameter("excludes");
|
||||
if (StringUtils.isNotEmpty(tempExcludes))
|
||||
{
|
||||
String[] url = tempExcludes.split(",");
|
||||
for (int i = 0; url != null && i < url.length; i++)
|
||||
String[] urls = tempExcludes.split(",");
|
||||
for (String url : urls)
|
||||
{
|
||||
excludes.add(url[i]);
|
||||
excludes.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,4 +72,4 @@ public class XssFilter implements Filter
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.fastbee.common.mybatis.enums;
|
||||
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 数据库类型
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DataBaseType {
|
||||
|
||||
/**
|
||||
* MySQL
|
||||
*/
|
||||
MY_SQL("MySQL"),
|
||||
|
||||
/**
|
||||
* Oracle
|
||||
*/
|
||||
ORACLE("Oracle"),
|
||||
|
||||
/**
|
||||
* PostgreSQL
|
||||
*/
|
||||
POSTGRE_SQL("PostgreSQL"),
|
||||
|
||||
/**
|
||||
* SQL Server
|
||||
*/
|
||||
SQL_SERVER("Microsoft SQL Server"),
|
||||
|
||||
/**
|
||||
* 达梦
|
||||
*/
|
||||
DM("DM DBMS");
|
||||
|
||||
/**
|
||||
* 数据库类型
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* 根据数据库产品名称查找对应的数据库类型
|
||||
*
|
||||
* @param databaseProductName 数据库产品名称
|
||||
* @return 对应的数据库类型枚举值,如果未找到则返回 null
|
||||
*/
|
||||
public static DataBaseType find(String databaseProductName) {
|
||||
if (StringUtils.isBlank(databaseProductName)) {
|
||||
return null;
|
||||
}
|
||||
for (DataBaseType type : values()) {
|
||||
if (type.getType().equals(databaseProductName)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.fastbee.framework.mybatis.mapper;
|
||||
package com.fastbee.common.mybatis.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
@@ -9,7 +9,7 @@ import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import com.fastbee.common.core.domain.PageParam;
|
||||
import com.fastbee.common.core.domain.PageResult;
|
||||
import com.fastbee.framework.mybatis.utils.MyBatisUtils;
|
||||
import com.fastbee.common.mybatis.utils.MyBatisUtils;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.fastbee.framework.mybatis.utils;
|
||||
package com.fastbee.common.mybatis.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
@@ -5,7 +5,7 @@ import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 精确的浮点数运算
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Arith
|
||||
@@ -108,7 +108,6 @@ public class Arith
|
||||
"The scale must be a positive integer or zero");
|
||||
}
|
||||
BigDecimal b = new BigDecimal(Double.toString(v));
|
||||
BigDecimal one = BigDecimal.ONE;
|
||||
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
return b.divide(BigDecimal.ONE, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package com.fastbee.common.utils;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.*;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
/**
|
||||
* 时间工具类
|
||||
*
|
||||
@@ -160,16 +156,20 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个时间差
|
||||
* 计算时间差
|
||||
*
|
||||
* @param endDate 最后时间
|
||||
* @param startTime 开始时间
|
||||
* @return 时间差(天/小时/分钟)
|
||||
*/
|
||||
public static String getDatePoor(Date endDate, Date nowDate)
|
||||
public static String timeDistance(Date endDate, Date startTime)
|
||||
{
|
||||
long nd = 1000 * 24 * 60 * 60;
|
||||
long nh = 1000 * 60 * 60;
|
||||
long nm = 1000 * 60;
|
||||
// long ns = 1000;
|
||||
// 获得两个时间的毫秒时间差异
|
||||
long diff = endDate.getTime() - nowDate.getTime();
|
||||
long diff = endDate.getTime() - startTime.getTime();
|
||||
// 计算差多少天
|
||||
long day = diff / nd;
|
||||
// 计算差多少小时
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.fastbee.common.utils;
|
||||
|
||||
/**
|
||||
* 脱敏工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class DesensitizedUtil
|
||||
{
|
||||
/**
|
||||
* 密码的全部字符都用*代替,比如:******
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 脱敏后的密码
|
||||
*/
|
||||
public static String password(String password)
|
||||
{
|
||||
if (StringUtils.isBlank(password))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return StringUtils.repeat('*', password.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* 车牌中间用*代替,如果是错误的车牌,不处理
|
||||
*
|
||||
* @param carLicense 完整的车牌号
|
||||
* @return 脱敏后的车牌
|
||||
*/
|
||||
public static String carLicense(String carLicense)
|
||||
{
|
||||
if (StringUtils.isBlank(carLicense))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
// 普通车牌
|
||||
if (carLicense.length() == 7)
|
||||
{
|
||||
carLicense = StringUtils.hide(carLicense, 3, 6);
|
||||
}
|
||||
else if (carLicense.length() == 8)
|
||||
{
|
||||
// 新能源车牌
|
||||
carLicense = StringUtils.hide(carLicense, 3, 7);
|
||||
}
|
||||
return carLicense;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.fastbee.common.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.fastbee.common.constant.CacheConstants;
|
||||
import com.fastbee.common.core.domain.entity.SysDictData;
|
||||
import com.fastbee.common.core.redis.RedisCache;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 字典工具类
|
||||
*
|
||||
@@ -56,6 +57,10 @@ public class DictUtils
|
||||
*/
|
||||
public static String getDictLabel(String dictType, String dictValue)
|
||||
{
|
||||
if (StringUtils.isEmpty(dictValue))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getDictLabel(dictType, dictValue, SEPARATOR);
|
||||
}
|
||||
|
||||
@@ -68,6 +73,10 @@ public class DictUtils
|
||||
*/
|
||||
public static String getDictValue(String dictType, String dictLabel)
|
||||
{
|
||||
if (StringUtils.isEmpty(dictLabel))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getDictValue(dictType, dictLabel, SEPARATOR);
|
||||
}
|
||||
|
||||
@@ -83,31 +92,31 @@ public class DictUtils
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StringUtils.isNotNull(datas))
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
if (StringUtils.containsAny(separator, dictValue))
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (StringUtils.containsAny(separator, dictValue))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
for (String value : dictValue.split(separator))
|
||||
{
|
||||
for (String value : dictValue.split(separator))
|
||||
if (value.equals(dict.getDictValue()))
|
||||
{
|
||||
if (value.equals(dict.getDictValue()))
|
||||
{
|
||||
propertyString.append(dict.getDictLabel()).append(separator);
|
||||
break;
|
||||
}
|
||||
propertyString.append(dict.getDictLabel()).append(separator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
if (dictValue.equals(dict.getDictValue()))
|
||||
{
|
||||
if (dictValue.equals(dict.getDictValue()))
|
||||
{
|
||||
return dict.getDictLabel();
|
||||
}
|
||||
return dict.getDictLabel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,8 +135,11 @@ public class DictUtils
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
|
||||
if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas))
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (StringUtils.containsAny(separator, dictLabel))
|
||||
{
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
@@ -154,6 +166,48 @@ public class DictUtils
|
||||
return StringUtils.stripEnd(propertyString.toString(), separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型获取字典所有值
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictValues(String dictType)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
propertyString.append(dict.getDictValue()).append(SEPARATOR);
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型获取字典所有标签
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 字典值
|
||||
*/
|
||||
public static String getDictLabels(String dictType)
|
||||
{
|
||||
StringBuilder propertyString = new StringBuilder();
|
||||
List<SysDictData> datas = getDictCache(dictType);
|
||||
if (StringUtils.isNull(datas))
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
for (SysDictData dict : datas)
|
||||
{
|
||||
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
|
||||
}
|
||||
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定字典缓存
|
||||
*
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
package com.fastbee.common.utils;
|
||||
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.constant.HttpStatus;
|
||||
import com.fastbee.common.core.domain.entity.SysRole;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import com.fastbee.common.constant.HttpStatus;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 安全服务工具类
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SecurityUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
**/
|
||||
@@ -43,7 +51,7 @@ public class SecurityUtils
|
||||
throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户账户
|
||||
**/
|
||||
@@ -109,7 +117,7 @@ public class SecurityUtils
|
||||
|
||||
/**
|
||||
* 是否为管理员
|
||||
*
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -117,4 +125,55 @@ public class SecurityUtils
|
||||
{
|
||||
return userId != null && 1L == userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具备某权限
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public static boolean hasPermi(String permission)
|
||||
{
|
||||
return hasPermi(getLoginUser().getPermissions(), permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
* @param authorities 权限列表
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public static boolean hasPermi(Collection<String> authorities, String permission)
|
||||
{
|
||||
return authorities.stream().filter(StringUtils::hasText)
|
||||
.anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否拥有某个角色
|
||||
*
|
||||
* @param role 角色标识
|
||||
* @return 用户是否具备某角色
|
||||
*/
|
||||
public static boolean hasRole(String role)
|
||||
{
|
||||
List<SysRole> roleList = getLoginUser().getUser().getRoles();
|
||||
Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
|
||||
return hasRole(roles, role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含角色
|
||||
*
|
||||
* @param roles 角色列表
|
||||
* @param role 角色
|
||||
* @return 用户是否具备某角色权限
|
||||
*/
|
||||
public static boolean hasRole(Collection<String> roles, String role)
|
||||
{
|
||||
return roles.stream().filter(StringUtils::hasText)
|
||||
.anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,43 +1,37 @@
|
||||
package com.fastbee.common.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.core.text.StrFormatter;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 字符串工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/**
|
||||
* 空字符串
|
||||
*/
|
||||
public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
{
|
||||
/** 空字符串 */
|
||||
private static final String NULLSTR = "";
|
||||
|
||||
/**
|
||||
* 下划线
|
||||
*/
|
||||
/** 下划线 */
|
||||
private static final char SEPARATOR = '_';
|
||||
|
||||
/** 星号 */
|
||||
private static final char ASTERISK = '*';
|
||||
|
||||
public static final String SLASH = "/";
|
||||
|
||||
/**
|
||||
* 获取参数不为空值
|
||||
*
|
||||
* @param value defaultValue 要判断的value
|
||||
* @return value 返回值
|
||||
*/
|
||||
public static <T> T nvl(T value, T defaultValue) {
|
||||
public static <T> T nvl(T value, T defaultValue)
|
||||
{
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
@@ -47,7 +41,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param coll 要判断的Collection
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(Collection<?> coll) {
|
||||
public static boolean isEmpty(Collection<?> coll)
|
||||
{
|
||||
return isNull(coll) || coll.isEmpty();
|
||||
}
|
||||
|
||||
@@ -57,7 +52,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param coll 要判断的Collection
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotEmpty(Collection<?> coll) {
|
||||
public static boolean isNotEmpty(Collection<?> coll)
|
||||
{
|
||||
return !isEmpty(coll);
|
||||
}
|
||||
|
||||
@@ -65,9 +61,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* * 判断一个对象数组是否为空
|
||||
*
|
||||
* @param objects 要判断的对象数组
|
||||
* * @return true:为空 false:非空
|
||||
** @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(Object[] objects) {
|
||||
public static boolean isEmpty(Object[] objects)
|
||||
{
|
||||
return isNull(objects) || (objects.length == 0);
|
||||
}
|
||||
|
||||
@@ -77,7 +74,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param objects 要判断的对象数组
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotEmpty(Object[] objects) {
|
||||
public static boolean isNotEmpty(Object[] objects)
|
||||
{
|
||||
return !isEmpty(objects);
|
||||
}
|
||||
|
||||
@@ -87,7 +85,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param map 要判断的Map
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(Map<?, ?> map) {
|
||||
public static boolean isEmpty(Map<?, ?> map)
|
||||
{
|
||||
return isNull(map) || map.isEmpty();
|
||||
}
|
||||
|
||||
@@ -97,7 +96,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param map 要判断的Map
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotEmpty(Map<?, ?> map) {
|
||||
public static boolean isNotEmpty(Map<?, ?> map)
|
||||
{
|
||||
return !isEmpty(map);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param str String
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(String str) {
|
||||
public static boolean isEmpty(String str)
|
||||
{
|
||||
return isNull(str) || NULLSTR.equals(str.trim());
|
||||
}
|
||||
|
||||
@@ -117,7 +118,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param str String
|
||||
* @return true:非空串 false:空串
|
||||
*/
|
||||
public static boolean isNotEmpty(String str) {
|
||||
public static boolean isNotEmpty(String str)
|
||||
{
|
||||
return !isEmpty(str);
|
||||
}
|
||||
|
||||
@@ -127,7 +129,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param object Object
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isNull(Object object) {
|
||||
public static boolean isNull(Object object)
|
||||
{
|
||||
return object == null;
|
||||
}
|
||||
|
||||
@@ -137,7 +140,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param object Object
|
||||
* @return true:非空 false:空
|
||||
*/
|
||||
public static boolean isNotNull(Object object) {
|
||||
public static boolean isNotNull(Object object)
|
||||
{
|
||||
return !isNull(object);
|
||||
}
|
||||
|
||||
@@ -147,37 +151,87 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param object 对象
|
||||
* @return true:是数组 false:不是数组
|
||||
*/
|
||||
public static boolean isArray(Object object) {
|
||||
public static boolean isArray(Object object)
|
||||
{
|
||||
return isNotNull(object) && object.getClass().isArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 去空格
|
||||
*/
|
||||
public static String trim(String str) {
|
||||
public static String trim(String str)
|
||||
{
|
||||
return (str == null ? "" : str.trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换指定字符串的指定区间内字符为"*"
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param startInclude 开始位置(包含)
|
||||
* @param endExclude 结束位置(不包含)
|
||||
* @return 替换后的字符串
|
||||
*/
|
||||
public static String hide(CharSequence str, int startInclude, int endExclude)
|
||||
{
|
||||
if (isEmpty(str))
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
final int strLength = str.length();
|
||||
if (startInclude > strLength)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
if (endExclude > strLength)
|
||||
{
|
||||
endExclude = strLength;
|
||||
}
|
||||
if (startInclude > endExclude)
|
||||
{
|
||||
// 如果起始位置大于结束位置,不替换
|
||||
return NULLSTR;
|
||||
}
|
||||
final char[] chars = new char[strLength];
|
||||
for (int i = 0; i < strLength; i++)
|
||||
{
|
||||
if (i >= startInclude && i < endExclude)
|
||||
{
|
||||
chars[i] = ASTERISK;
|
||||
}
|
||||
else
|
||||
{
|
||||
chars[i] = str.charAt(i);
|
||||
}
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param str 字符串
|
||||
* @param start 开始
|
||||
* @return 结果
|
||||
*/
|
||||
public static String substring(final String str, int start) {
|
||||
if (str == null) {
|
||||
public static String substring(final String str, int start)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
if (start < 0)
|
||||
{
|
||||
start = str.length() + start;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
if (start > str.length()) {
|
||||
if (start > str.length())
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
@@ -187,41 +241,99 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param str 字符串
|
||||
* @param start 开始
|
||||
* @param end 结束
|
||||
* @param end 结束
|
||||
* @return 结果
|
||||
*/
|
||||
public static String substring(final String str, int start, int end) {
|
||||
if (str == null) {
|
||||
public static String substring(final String str, int start, int end)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
if (end < 0) {
|
||||
if (end < 0)
|
||||
{
|
||||
end = str.length() + end;
|
||||
}
|
||||
if (start < 0) {
|
||||
if (start < 0)
|
||||
{
|
||||
start = str.length() + start;
|
||||
}
|
||||
|
||||
if (end > str.length()) {
|
||||
if (end > str.length())
|
||||
{
|
||||
end = str.length();
|
||||
}
|
||||
|
||||
if (start > end) {
|
||||
if (start > end)
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
if (end < 0) {
|
||||
if (end < 0)
|
||||
{
|
||||
end = 0;
|
||||
}
|
||||
|
||||
return str.substring(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
|
||||
*
|
||||
* @param str 要截取的字符串
|
||||
* @param open 起始字符串
|
||||
* @param close 结束字符串
|
||||
* @return 截取结果
|
||||
*/
|
||||
public static String substringBetweenLast(final String str, final String open, final String close)
|
||||
{
|
||||
if (isEmpty(str) || isEmpty(open) || isEmpty(close))
|
||||
{
|
||||
return NULLSTR;
|
||||
}
|
||||
final int start = str.indexOf(open);
|
||||
if (start != INDEX_NOT_FOUND)
|
||||
{
|
||||
final int end = str.lastIndexOf(close);
|
||||
if (end != INDEX_NOT_FOUND)
|
||||
{
|
||||
return str.substring(start + open.length(), end);
|
||||
}
|
||||
}
|
||||
return NULLSTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空,并且不是空白字符
|
||||
*
|
||||
* @param str 要判断的value
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean hasText(String str)
|
||||
{
|
||||
return (str != null && !str.isEmpty() && containsText(str));
|
||||
}
|
||||
|
||||
private static boolean containsText(CharSequence str)
|
||||
{
|
||||
int strLen = str.length();
|
||||
for (int i = 0; i < strLen; i++)
|
||||
{
|
||||
if (!Character.isWhitespace(str.charAt(i)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文本, {} 表示占位符<br>
|
||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
||||
@@ -232,11 +344,13 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
|
||||
*
|
||||
* @param template 文本模板,被替换的部分用 {} 表示
|
||||
* @param params 参数值
|
||||
* @param params 参数值
|
||||
* @return 格式化后的文本
|
||||
*/
|
||||
public static String format(String template, Object... params) {
|
||||
if (isEmpty(params) || isEmpty(template)) {
|
||||
public static String format(String template, Object... params)
|
||||
{
|
||||
if (isEmpty(params) || isEmpty(template))
|
||||
{
|
||||
return template;
|
||||
}
|
||||
return StrFormatter.format(template, params);
|
||||
@@ -248,7 +362,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param link 链接
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean ishttp(String link) {
|
||||
public static boolean ishttp(String link)
|
||||
{
|
||||
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
|
||||
}
|
||||
|
||||
@@ -259,35 +374,54 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param sep 分隔符
|
||||
* @return set集合
|
||||
*/
|
||||
public static final Set<String> str2Set(String str, String sep) {
|
||||
public static final Set<String> str2Set(String str, String sep)
|
||||
{
|
||||
return new HashSet<String>(str2List(str, sep, true, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转list
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @param filterBlank 过滤纯空白
|
||||
* @param trim 去掉首尾空白
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @return list集合
|
||||
*/
|
||||
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
|
||||
public static final List<String> str2List(String str, String sep)
|
||||
{
|
||||
return str2List(str, sep, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转list
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @param filterBlank 过滤纯空白
|
||||
* @param trim 去掉首尾空白
|
||||
* @return list集合
|
||||
*/
|
||||
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
|
||||
{
|
||||
List<String> list = new ArrayList<String>();
|
||||
if (StringUtils.isEmpty(str)) {
|
||||
if (StringUtils.isEmpty(str))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
// 过滤空白字符串
|
||||
if (filterBlank && StringUtils.isBlank(str)) {
|
||||
if (filterBlank && StringUtils.isBlank(str))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
String[] split = str.split(sep);
|
||||
for (String string : split) {
|
||||
if (filterBlank && StringUtils.isBlank(string)) {
|
||||
for (String string : split)
|
||||
{
|
||||
if (filterBlank && StringUtils.isBlank(string))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (trim) {
|
||||
if (trim)
|
||||
{
|
||||
string = string.trim();
|
||||
}
|
||||
list.add(string);
|
||||
@@ -297,18 +431,24 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
|
||||
* 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
|
||||
*
|
||||
* @param set 给定的集合
|
||||
* @param collection 给定的集合
|
||||
* @param array 给定的数组
|
||||
* @return boolean 结果
|
||||
*/
|
||||
public static boolean containsAny(Collection<String> collection, String... array) {
|
||||
if (isEmpty(collection) || isEmpty(array)) {
|
||||
public static boolean containsAny(Collection<String> collection, String... array)
|
||||
{
|
||||
if (isEmpty(collection) || isEmpty(array))
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
for (String str : array) {
|
||||
if (collection.contains(str)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for (String str : array)
|
||||
{
|
||||
if (collection.contains(str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -319,16 +459,20 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/**
|
||||
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
|
||||
*
|
||||
* @param cs 指定字符串
|
||||
* @param cs 指定字符串
|
||||
* @param searchCharSequences 需要检查的字符串数组
|
||||
* @return 是否包含任意一个字符串
|
||||
*/
|
||||
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
|
||||
if (isEmpty(cs) || isEmpty(searchCharSequences)) {
|
||||
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
|
||||
{
|
||||
if (isEmpty(cs) || isEmpty(searchCharSequences))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (CharSequence testStr : searchCharSequences) {
|
||||
if (containsIgnoreCase(cs, testStr)) {
|
||||
for (CharSequence testStr : searchCharSequences)
|
||||
{
|
||||
if (containsIgnoreCase(cs, testStr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -338,8 +482,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/**
|
||||
* 驼峰转下划线命名
|
||||
*/
|
||||
public static String toUnderScoreCase(String str) {
|
||||
if (str == null) {
|
||||
public static String toUnderScoreCase(String str)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -349,23 +495,31 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
boolean curreCharIsUpperCase = true;
|
||||
// 下一字符是否大写
|
||||
boolean nexteCharIsUpperCase = true;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
for (int i = 0; i < str.length(); i++)
|
||||
{
|
||||
char c = str.charAt(i);
|
||||
if (i > 0) {
|
||||
if (i > 0)
|
||||
{
|
||||
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
preCharIsUpperCase = false;
|
||||
}
|
||||
|
||||
curreCharIsUpperCase = Character.isUpperCase(c);
|
||||
|
||||
if (i < (str.length() - 1)) {
|
||||
if (i < (str.length() - 1))
|
||||
{
|
||||
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
|
||||
}
|
||||
|
||||
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
|
||||
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
|
||||
}
|
||||
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
@@ -377,14 +531,18 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/**
|
||||
* 是否包含字符串
|
||||
*
|
||||
* @param str 验证字符串
|
||||
* @param str 验证字符串
|
||||
* @param strs 字符串组
|
||||
* @return 包含返回true
|
||||
*/
|
||||
public static boolean inStringIgnoreCase(String str, String... strs) {
|
||||
if (str != null && strs != null) {
|
||||
for (String s : strs) {
|
||||
if (str.equalsIgnoreCase(trim(s))) {
|
||||
public static boolean inStringIgnoreCase(String str, String... strs)
|
||||
{
|
||||
if (str != null && strs != null)
|
||||
{
|
||||
for (String s : strs)
|
||||
{
|
||||
if (str.equalsIgnoreCase(trim(s)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -398,21 +556,27 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* @param name 转换前的下划线大写方式命名的字符串
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String convertToCamelCase(String name) {
|
||||
public static String convertToCamelCase(String name)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
// 快速检查
|
||||
if (name == null || name.isEmpty()) {
|
||||
if (name == null || name.isEmpty())
|
||||
{
|
||||
// 没必要转换
|
||||
return "";
|
||||
} else if (!name.contains("_")) {
|
||||
}
|
||||
else if (!name.contains("_"))
|
||||
{
|
||||
// 不含下划线,仅将首字母大写
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
// 用下划线将原始字符串分割
|
||||
String[] camels = name.split("_");
|
||||
for (String camel : camels) {
|
||||
for (String camel : camels)
|
||||
{
|
||||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||||
if (camel.isEmpty()) {
|
||||
if (camel.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// 首字母大写
|
||||
@@ -423,24 +587,37 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰式命名法 例如:user_name->userName
|
||||
* 驼峰式命名法
|
||||
* 例如:user_name->userName
|
||||
*/
|
||||
public static String toCamelCase(String s) {
|
||||
if (s == null) {
|
||||
public static String toCamelCase(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (s.indexOf(SEPARATOR) == -1)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
s = s.toLowerCase();
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
boolean upperCase = false;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == SEPARATOR) {
|
||||
if (c == SEPARATOR)
|
||||
{
|
||||
upperCase = true;
|
||||
} else if (upperCase) {
|
||||
}
|
||||
else if (upperCase)
|
||||
{
|
||||
sb.append(Character.toUpperCase(c));
|
||||
upperCase = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
@@ -450,16 +627,20 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
/**
|
||||
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param str 指定字符串
|
||||
* @param strs 需要检查的字符串数组
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matches(String str, List<String> strs) {
|
||||
if (isEmpty(str) || isEmpty(strs)) {
|
||||
public static boolean matches(String str, List<String> strs)
|
||||
{
|
||||
if (isEmpty(str) || isEmpty(strs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String pattern : strs) {
|
||||
if (isMatch(pattern, str)) {
|
||||
for (String pattern : strs)
|
||||
{
|
||||
if (isMatch(pattern, str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -473,202 +654,67 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
* ** 表示任意层路径;
|
||||
*
|
||||
* @param pattern 匹配规则
|
||||
* @param url 需要匹配的url
|
||||
* @param url 需要匹配的url
|
||||
* @return
|
||||
*/
|
||||
public static boolean isMatch(String pattern, String url) {
|
||||
public static boolean isMatch(String pattern, String url)
|
||||
{
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
return matcher.match(pattern, url);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T cast(Object obj) {
|
||||
public static <T> T cast(Object obj)
|
||||
{
|
||||
return (T) obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
|
||||
*
|
||||
* @param num 数字对象
|
||||
* @param num 数字对象
|
||||
* @param size 字符串指定长度
|
||||
* @return 返回数字的字符串格式,该字符串为指定长度。
|
||||
*/
|
||||
public static final String padl(final Number num, final int size) {
|
||||
public static final String padl(final Number num, final int size)
|
||||
{
|
||||
return padl(num.toString(), size, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
|
||||
*
|
||||
* @param s 原始字符串
|
||||
* @param s 原始字符串
|
||||
* @param size 字符串指定长度
|
||||
* @param c 用于补齐的字符
|
||||
* @param c 用于补齐的字符
|
||||
* @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
|
||||
*/
|
||||
public static final String padl(final String s, final int size, final char c) {
|
||||
public static final String padl(final String s, final int size, final char c)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(size);
|
||||
if (s != null) {
|
||||
if (s != null)
|
||||
{
|
||||
final int len = s.length();
|
||||
if (s.length() <= size) {
|
||||
for (int i = size - len; i > 0; i--) {
|
||||
if (s.length() <= size)
|
||||
{
|
||||
for (int i = size - len; i > 0; i--)
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
sb.append(s);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return s.substring(len - size, len);
|
||||
}
|
||||
} else {
|
||||
for (int i = size; i > 0; i--) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = size; i > 0; i--)
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/*将字符串转小写,首字母大写,其他小写*/
|
||||
public static String upperCase(String str) {
|
||||
char[] ch = str.toLowerCase().toCharArray();
|
||||
if (ch[0] >= 'a' && ch[0] <= 'z') {
|
||||
ch[0] = (char) (ch[0] - 32);
|
||||
}
|
||||
return new String(ch);
|
||||
}
|
||||
|
||||
public static String toString(Object value) {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
if (value instanceof ByteBuf) {
|
||||
return ByteBufUtil.hexDump((ByteBuf) value);
|
||||
}
|
||||
if (!value.getClass().isArray()) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
StringBuilder root = new StringBuilder(32);
|
||||
toString(value, root);
|
||||
return root.toString();
|
||||
}
|
||||
|
||||
public static StringBuilder toString(Object value, StringBuilder builder) {
|
||||
if (value == null) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
builder.append('[');
|
||||
int start = builder.length();
|
||||
|
||||
if (value instanceof long[]) {
|
||||
long[] array = (long[]) value;
|
||||
for (long t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof int[]) {
|
||||
int[] array = (int[]) value;
|
||||
for (int t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof short[]) {
|
||||
short[] array = (short[]) value;
|
||||
for (short t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof byte[]) {
|
||||
byte[] array = (byte[]) value;
|
||||
for (byte t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof char[]) {
|
||||
char[] array = (char[]) value;
|
||||
for (char t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof double[]) {
|
||||
double[] array = (double[]) value;
|
||||
for (double t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof float[]) {
|
||||
float[] array = (float[]) value;
|
||||
for (float t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof boolean[]) {
|
||||
boolean[] array = (boolean[]) value;
|
||||
for (boolean t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof String[]) {
|
||||
String[] array = (String[]) value;
|
||||
for (String t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
|
||||
} else if (isArray1(value)) {
|
||||
Object[] array = (Object[]) value;
|
||||
for (Object t : array) {
|
||||
toString(t, builder).append(',');
|
||||
}
|
||||
|
||||
} else if (value instanceof Object[]) {
|
||||
Object[] array = (Object[]) value;
|
||||
for (Object t : array) {
|
||||
builder.append(t).append(',');
|
||||
}
|
||||
}
|
||||
|
||||
int end = builder.length();
|
||||
if (end <= start) {
|
||||
builder.append(']');
|
||||
} else {
|
||||
builder.setCharAt(end - 1, ']');
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static boolean isArray1(Object value) {
|
||||
Class<?> componentType = value.getClass().getComponentType();
|
||||
if (componentType == null) {
|
||||
return false;
|
||||
}
|
||||
return componentType.isArray();
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, char ch) {
|
||||
int length = str.length();
|
||||
int pads = size - length;
|
||||
if (pads > 0) {
|
||||
char[] result = new char[size];
|
||||
str.getChars(0, length, result, pads);
|
||||
while (pads > 0) {
|
||||
result[--pads] = ch;
|
||||
}
|
||||
return new String(result);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字符串中的数字
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static Integer matcherNum(String str){
|
||||
Pattern pattern = Pattern.compile("\\d+");
|
||||
Matcher matcher = pattern.matcher(str);
|
||||
while (matcher.find()){
|
||||
return Integer.parseInt(matcher.group());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +24,7 @@ import java.util.*;
|
||||
@Component
|
||||
public class TopicsUtils {
|
||||
|
||||
@Value("${server.broker.enabled}")
|
||||
private Boolean enabled;
|
||||
private Boolean enabled = true;
|
||||
|
||||
/**
|
||||
* 拼接topic
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* 通用http发送方法
|
||||
@@ -74,7 +75,7 @@ public class HttpUtils
|
||||
URLConnection connection = realUrl.openConnection();
|
||||
connection.setRequestProperty("accept", "*/*");
|
||||
connection.setRequestProperty("connection", "Keep-Alive");
|
||||
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
connection.connect();
|
||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
|
||||
String line;
|
||||
@@ -121,10 +122,23 @@ public class HttpUtils
|
||||
* 向指定 URL 发送POST方法的请求
|
||||
*
|
||||
* @param url 发送请求的 URL
|
||||
* @param param 请求参数,请求参数应该是 JSON String格式 的形式。
|
||||
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
|
||||
* @return 所代表远程资源的响应结果
|
||||
*/
|
||||
public static String sendPost(String url, String param)
|
||||
{
|
||||
return sendPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 URL 发送POST方法的请求
|
||||
*
|
||||
* @param url 发送请求的 URL
|
||||
* @param param 请求参数
|
||||
* @param contentType 内容类型
|
||||
* @return 所代表远程资源的响应结果
|
||||
*/
|
||||
public static String sendPost(String url, String param, String contentType)
|
||||
{
|
||||
PrintWriter out = null;
|
||||
BufferedReader in = null;
|
||||
@@ -136,9 +150,9 @@ public class HttpUtils
|
||||
URLConnection conn = realUrl.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("contentType", "utf-8");
|
||||
conn.setRequestProperty("Content-Type", contentType);
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
out = new PrintWriter(conn.getOutputStream());
|
||||
@@ -190,6 +204,11 @@ public class HttpUtils
|
||||
}
|
||||
|
||||
public static String sendSSLPost(String url, String param)
|
||||
{
|
||||
return sendSSLPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
||||
}
|
||||
|
||||
public static String sendSSLPost(String url, String param, String contentType)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
String urlNameString = url + "?" + param;
|
||||
@@ -202,9 +221,9 @@ public class HttpUtils
|
||||
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("contentType", "utf-8");
|
||||
conn.setRequestProperty("Content-Type", contentType);
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
|
||||
|
||||
@@ -1,20 +1,39 @@
|
||||
package com.fastbee.common.utils.ip;
|
||||
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 获取IP方法
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class IpUtils
|
||||
{
|
||||
public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
|
||||
// 匹配 ip
|
||||
public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
|
||||
public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
|
||||
// 匹配网段
|
||||
public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
|
||||
|
||||
/**
|
||||
* 获取客户端IP
|
||||
*
|
||||
*
|
||||
* @return IP地址
|
||||
*/
|
||||
public static String getIpAddr()
|
||||
{
|
||||
return getIpAddr(ServletUtils.getRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端IP
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @return IP地址
|
||||
*/
|
||||
@@ -52,7 +71,7 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 检查是否为内部IP地址
|
||||
*
|
||||
*
|
||||
* @param ip IP地址
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -64,7 +83,7 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 检查是否为内部IP地址
|
||||
*
|
||||
*
|
||||
* @param addr byte地址
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -107,7 +126,7 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 将IPv4地址转换成字节
|
||||
*
|
||||
*
|
||||
* @param text IPv4地址
|
||||
* @return byte 字节
|
||||
*/
|
||||
@@ -195,7 +214,7 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 获取IP地址
|
||||
*
|
||||
*
|
||||
* @return 本地IP地址
|
||||
*/
|
||||
public static String getHostIp()
|
||||
@@ -212,7 +231,7 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 获取主机名
|
||||
*
|
||||
*
|
||||
* @return 本地主机名
|
||||
*/
|
||||
public static String getHostName()
|
||||
@@ -248,7 +267,7 @@ public class IpUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
return ip;
|
||||
return StringUtils.substring(ip, 0, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,4 +280,104 @@ public class IpUtils
|
||||
{
|
||||
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为IP
|
||||
*/
|
||||
public static boolean isIP(String ip)
|
||||
{
|
||||
return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为IP,或 *为间隔的通配符地址
|
||||
*/
|
||||
public static boolean isIpWildCard(String ip)
|
||||
{
|
||||
return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测参数是否在ip通配符里
|
||||
*/
|
||||
public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
|
||||
{
|
||||
String[] s1 = ipWildCard.split("\\.");
|
||||
String[] s2 = ip.split("\\.");
|
||||
boolean isMatchedSeg = true;
|
||||
for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
|
||||
{
|
||||
if (!s1[i].equals(s2[i]))
|
||||
{
|
||||
isMatchedSeg = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isMatchedSeg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串
|
||||
*/
|
||||
public static boolean isIPSegment(String ipSeg)
|
||||
{
|
||||
return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断ip是否在指定网段中
|
||||
*/
|
||||
public static boolean ipIsInNetNoCheck(String iparea, String ip)
|
||||
{
|
||||
int idx = iparea.indexOf('-');
|
||||
String[] sips = iparea.substring(0, idx).split("\\.");
|
||||
String[] sipe = iparea.substring(idx + 1).split("\\.");
|
||||
String[] sipt = ip.split("\\.");
|
||||
long ips = 0L, ipe = 0L, ipt = 0L;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
ips = ips << 8 | Integer.parseInt(sips[i]);
|
||||
ipe = ipe << 8 | Integer.parseInt(sipe[i]);
|
||||
ipt = ipt << 8 | Integer.parseInt(sipt[i]);
|
||||
}
|
||||
if (ips > ipe)
|
||||
{
|
||||
long t = ips;
|
||||
ips = ipe;
|
||||
ipe = t;
|
||||
}
|
||||
return ips <= ipt && ipt <= ipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验ip是否符合过滤串规则
|
||||
*
|
||||
* @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99`
|
||||
* @param ip 校验IP地址
|
||||
* @return boolean 结果
|
||||
*/
|
||||
public static boolean isMatchedIp(String filter, String ip)
|
||||
{
|
||||
if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String[] ips = filter.split(";");
|
||||
for (String iStr : ips)
|
||||
{
|
||||
if (isIP(iStr) && iStr.equals(ip))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
package com.fastbee.common.utils.poi;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
/**
|
||||
* Excel数据格式处理适配器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ExcelHandlerAdapter
|
||||
{
|
||||
/**
|
||||
* 格式化
|
||||
*
|
||||
*
|
||||
* @param value 单元格数据值
|
||||
* @param args excel注解args参数组
|
||||
* @param cell 单元格对象
|
||||
* @param wb 工作簿对象
|
||||
*
|
||||
* @return 处理后的值
|
||||
*/
|
||||
Object format(Object value, String[] args);
|
||||
Object format(Object value, String[] args, Cell cell, Workbook wb);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
package com.fastbee.common.utils.spring;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.AopContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
@@ -18,11 +19,11 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* spring工具类 方便在非spring管理环境中获取bean
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
|
||||
{
|
||||
/** Spring应用上下文环境 */
|
||||
private static ConfigurableListableBeanFactory beanFactory;
|
||||
@@ -30,13 +31,13 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
|
||||
{
|
||||
SpringUtils.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
SpringUtils.applicationContext = applicationContext;
|
||||
}
|
||||
@@ -119,14 +120,19 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
|
||||
|
||||
/**
|
||||
* 获取aop代理对象
|
||||
*
|
||||
*
|
||||
* @param invoker
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getAopProxy(T invoker)
|
||||
{
|
||||
return (T) AopContext.currentProxy();
|
||||
Object proxy = AopContext.currentProxy();
|
||||
if (((Advised) proxy).getTargetSource().getTargetClass() == invoker.getClass())
|
||||
{
|
||||
return (T) proxy;
|
||||
}
|
||||
return invoker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* sql操作工具类
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SqlUtil
|
||||
@@ -13,13 +13,18 @@ public class SqlUtil
|
||||
/**
|
||||
* 定义常用的 sql关键字
|
||||
*/
|
||||
public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
|
||||
public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
|
||||
|
||||
/**
|
||||
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
|
||||
*/
|
||||
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
|
||||
|
||||
/**
|
||||
* 限制orderBy最大长度
|
||||
*/
|
||||
private static final int ORDER_BY_MAX_LENGTH = 500;
|
||||
|
||||
/**
|
||||
* 检查字符,防止注入绕过
|
||||
*/
|
||||
@@ -29,6 +34,10 @@ public class SqlUtil
|
||||
{
|
||||
throw new UtilException("参数不符合规范,不能进行查询");
|
||||
}
|
||||
if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
|
||||
{
|
||||
throw new UtilException("参数已超过最大限制,不能进行查询");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,21 +22,21 @@ public class Seq
|
||||
private static AtomicInteger uploadSeq = new AtomicInteger(1);
|
||||
|
||||
// 机器标识
|
||||
private static String machineCode = "A";
|
||||
private static final String machineCode = "A";
|
||||
|
||||
/**
|
||||
* 获取通用序列号
|
||||
*
|
||||
*
|
||||
* @return 序列值
|
||||
*/
|
||||
public static String getId()
|
||||
{
|
||||
return getId(commSeqType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
|
||||
*
|
||||
*
|
||||
* @return 序列值
|
||||
*/
|
||||
public static String getId(String type)
|
||||
@@ -51,7 +51,7 @@ public class Seq
|
||||
|
||||
/**
|
||||
* 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
|
||||
*
|
||||
*
|
||||
* @param atomicInt 序列数
|
||||
* @param length 数值长度
|
||||
* @return 序列值
|
||||
@@ -66,7 +66,7 @@ public class Seq
|
||||
|
||||
/**
|
||||
* 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
|
||||
*
|
||||
*
|
||||
* @return 序列值
|
||||
*/
|
||||
private synchronized static String getSeq(AtomicInteger atomicInt, int length)
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 自定义xss校验注解实现
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class XssValidator implements ConstraintValidator<Xss, String>
|
||||
@@ -27,8 +27,13 @@ public class XssValidator implements ConstraintValidator<Xss, String>
|
||||
|
||||
public static boolean containsHtml(String value)
|
||||
{
|
||||
StringBuilder sHtml = new StringBuilder();
|
||||
Pattern pattern = Pattern.compile(HTML_PATTERN);
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
return matcher.matches();
|
||||
while (matcher.find())
|
||||
{
|
||||
sHtml.append(matcher.group());
|
||||
}
|
||||
return pattern.matcher(sHtml).matches();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>fastbee</artifactId>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<version>3.8.5</version>
|
||||
<version>${fastbee.version}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot Web容器 -->
|
||||
<dependency>
|
||||
@@ -59,6 +63,13 @@
|
||||
<artifactId>oshi-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 动态数据源 -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.annotation.DataScope;
|
||||
import com.fastbee.common.constant.UserConstants;
|
||||
import com.fastbee.common.core.domain.BaseEntity;
|
||||
import com.fastbee.common.core.domain.entity.SysRole;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
@@ -73,8 +74,7 @@ public class DataScopeAspect
|
||||
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
|
||||
{
|
||||
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
|
||||
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
|
||||
controllerDataScope.userAlias(), permission);
|
||||
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,29 +92,42 @@ public class DataScopeAspect
|
||||
{
|
||||
StringBuilder sqlString = new StringBuilder();
|
||||
List<String> conditions = new ArrayList<String>();
|
||||
List<String> scopeCustomIds = new ArrayList<String>();
|
||||
user.getRoles().forEach(role -> {
|
||||
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||
{
|
||||
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
|
||||
}
|
||||
});
|
||||
|
||||
for (SysRole role : user.getRoles())
|
||||
{
|
||||
String dataScope = role.getDataScope();
|
||||
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
|
||||
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
|
||||
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (DATA_SCOPE_ALL.equals(dataScope))
|
||||
{
|
||||
sqlString = new StringBuilder();
|
||||
conditions.add(dataScope);
|
||||
break;
|
||||
}
|
||||
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
|
||||
role.getRoleId()));
|
||||
if (scopeCustomIds.size() > 1)
|
||||
{
|
||||
// 多个自定数据权限使用in查询,避免多次拼接。
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
|
||||
}
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT.equals(dataScope))
|
||||
{
|
||||
@@ -122,9 +135,7 @@ public class DataScopeAspect
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
|
||||
deptAlias, user.getDeptId(), user.getDeptId()));
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
|
||||
}
|
||||
else if (DATA_SCOPE_SELF.equals(dataScope))
|
||||
{
|
||||
@@ -141,6 +152,12 @@ public class DataScopeAspect
|
||||
conditions.add(dataScope);
|
||||
}
|
||||
|
||||
// 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
|
||||
if (StringUtils.isEmpty(conditions))
|
||||
{
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(sqlString.toString()))
|
||||
{
|
||||
Object params = joinPoint.getArgs()[0];
|
||||
|
||||
@@ -1,24 +1,14 @@
|
||||
package com.fastbee.framework.aspectj;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.fastbee.common.annotation.Log;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.core.text.Convert;
|
||||
import com.fastbee.common.enums.BusinessStatus;
|
||||
import com.fastbee.common.enums.HttpMethod;
|
||||
import com.fastbee.common.filter.PropertyPreExcludeFilter;
|
||||
import com.fastbee.common.utils.ExceptionUtil;
|
||||
import com.fastbee.common.utils.SecurityUtils;
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
@@ -26,10 +16,27 @@ import com.fastbee.common.utils.ip.IpUtils;
|
||||
import com.fastbee.framework.manager.AsyncManager;
|
||||
import com.fastbee.framework.manager.factory.AsyncFactory;
|
||||
import com.fastbee.system.domain.SysOperLog;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志记录处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@@ -41,6 +48,18 @@ public class LogAspect
|
||||
/** 排除敏感属性字段 */
|
||||
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
|
||||
|
||||
/** 计算操作消耗时间 */
|
||||
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
|
||||
|
||||
/**
|
||||
* 处理请求前执行
|
||||
*/
|
||||
@Before(value = "@annotation(controllerLog)")
|
||||
public void doBefore(JoinPoint joinPoint, Log controllerLog)
|
||||
{
|
||||
TIME_THREADLOCAL.set(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理完请求后执行
|
||||
*
|
||||
@@ -54,7 +73,7 @@ public class LogAspect
|
||||
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param e 异常
|
||||
*/
|
||||
@@ -75,18 +94,23 @@ public class LogAspect
|
||||
SysOperLog operLog = new SysOperLog();
|
||||
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||
// 请求的地址
|
||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||
String ip = IpUtils.getIpAddr();
|
||||
operLog.setOperIp(ip);
|
||||
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||
if (loginUser != null)
|
||||
{
|
||||
operLog.setOperName(loginUser.getUsername());
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
if (StringUtils.isNotNull(currentUser) && StringUtils.isNotNull(currentUser.getDept()))
|
||||
{
|
||||
operLog.setDeptName(currentUser.getDept().getDeptName());
|
||||
}
|
||||
}
|
||||
|
||||
if (e != null)
|
||||
{
|
||||
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||
operLog.setErrorMsg(StringUtils.substring(Convert.toStr(e.getMessage(), ExceptionUtil.getExceptionMessage(e)), 0, 2000));
|
||||
}
|
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
@@ -96,6 +120,8 @@ public class LogAspect
|
||||
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
||||
// 设置消耗时间
|
||||
operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
|
||||
// 保存数据库
|
||||
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
||||
}
|
||||
@@ -105,11 +131,15 @@ public class LogAspect
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
TIME_THREADLOCAL.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
*
|
||||
* @param log 日志
|
||||
* @param operLog 操作日志
|
||||
* @throws Exception
|
||||
@@ -126,7 +156,7 @@ public class LogAspect
|
||||
if (log.isSaveRequestData())
|
||||
{
|
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(joinPoint, operLog);
|
||||
setRequestValue(joinPoint, operLog, log.excludeParamNames());
|
||||
}
|
||||
// 是否需要保存response,参数和值
|
||||
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
|
||||
@@ -137,29 +167,29 @@ public class LogAspect
|
||||
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
*
|
||||
* @param operLog 操作日志
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
|
||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
|
||||
{
|
||||
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||
String requestMethod = operLog.getRequestMethod();
|
||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
|
||||
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
|
||||
{
|
||||
String params = argsArrayToString(joinPoint.getArgs());
|
||||
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||
}
|
||||
else
|
||||
{
|
||||
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000));
|
||||
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数拼装
|
||||
*/
|
||||
private String argsArrayToString(Object[] paramsArray)
|
||||
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
|
||||
{
|
||||
String params = "";
|
||||
if (paramsArray != null && paramsArray.length > 0)
|
||||
@@ -170,7 +200,7 @@ public class LogAspect
|
||||
{
|
||||
try
|
||||
{
|
||||
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter());
|
||||
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
|
||||
params += jsonObj.toString() + " ";
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -185,14 +215,14 @@ public class LogAspect
|
||||
/**
|
||||
* 忽略敏感属性
|
||||
*/
|
||||
public PropertyPreExcludeFilter excludePropertyPreFilter()
|
||||
public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
|
||||
{
|
||||
return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES);
|
||||
return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要过滤的对象。
|
||||
*
|
||||
*
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
|
||||
@@ -79,7 +79,7 @@ public class RateLimiterAspect
|
||||
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
|
||||
if (rateLimiter.limitType() == LimitType.IP)
|
||||
{
|
||||
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
|
||||
stringBuffer.append(IpUtils.getIpAddr()).append("-");
|
||||
}
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -15,8 +14,6 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
@Configuration
|
||||
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
// 指定要扫描的Mapper类的包的路径
|
||||
@MapperScan("com.fastbee.**.mapper")
|
||||
public class ApplicationConfig
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
|
||||
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class DataSourceConfig {
|
||||
private final DynamicDataSourceProperties properties;
|
||||
private final DefaultDataSourceCreator dataSourceCreator;
|
||||
|
||||
|
||||
public DataSourceConfig(DynamicDataSourceProperties properties,
|
||||
DefaultDataSourceCreator dataSourceCreator) {
|
||||
this.properties = properties;
|
||||
this.dataSourceCreator = dataSourceCreator;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider() {
|
||||
return new AbstractDataSourceProvider(dataSourceCreator) {
|
||||
@Override
|
||||
public Map<String, DataSource> loadDataSources() {
|
||||
Map<String, DataSource> dataSourceMap = new HashMap<>();
|
||||
return dataSourceMap;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public DataSource dataSource(List<DynamicDataSourceProvider> providers) {
|
||||
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(providers);
|
||||
dataSource.setPrimary(properties.getPrimary());
|
||||
dataSource.setStrict(properties.getStrict());
|
||||
dataSource.setStrategy(properties.getStrategy());
|
||||
dataSource.setP6spy(properties.getP6spy());
|
||||
dataSource.setSeata(properties.getSeata());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +1,23 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.sql.DataSource;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
import com.alibaba.druid.util.Utils;
|
||||
import com.fastbee.common.enums.DataSourceType;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
import com.fastbee.framework.config.properties.DruidProperties;
|
||||
import com.fastbee.framework.datasource.DynamicDataSource;
|
||||
|
||||
/**
|
||||
* druid 配置多数据源
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
import javax.servlet.*;
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
public class DruidConfig
|
||||
{
|
||||
@Bean
|
||||
@ConfigurationProperties("spring.datasource.druid.master")
|
||||
public DataSource masterDataSource(DruidProperties druidProperties)
|
||||
{
|
||||
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
|
||||
return druidProperties.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties("spring.datasource.druid.slave")
|
||||
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
|
||||
public DataSource slaveDataSource(DruidProperties druidProperties)
|
||||
{
|
||||
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
|
||||
return druidProperties.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Bean(name = "dynamicDataSource")
|
||||
@Primary
|
||||
public DynamicDataSource dataSource(DataSource masterDataSource)
|
||||
{
|
||||
Map<Object, Object> targetDataSources = new HashMap<>();
|
||||
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
|
||||
setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
|
||||
return new DynamicDataSource(masterDataSource, targetDataSources);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据源
|
||||
*
|
||||
* @param targetDataSources 备选数据源集合
|
||||
* @param sourceName 数据源名称
|
||||
* @param beanName bean名称
|
||||
*/
|
||||
public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
|
||||
{
|
||||
try
|
||||
{
|
||||
DataSource dataSource = SpringUtils.getBean(beanName);
|
||||
targetDataSources.put(sourceName, dataSource);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class DruidConfig {
|
||||
/**
|
||||
* 去除监控页面底部的广告
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
|
||||
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
|
||||
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
|
||||
{
|
||||
// 获取web监控页面的参数
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.alibaba.fastjson2.JSONWriter;
|
||||
|
||||
/**
|
||||
* Redis使用FastJson序列化
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.DispatcherType;
|
||||
import com.fastbee.common.filter.RepeatableFilter;
|
||||
import com.fastbee.common.filter.XssFilter;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.fastbee.common.filter.RepeatableFilter;
|
||||
import com.fastbee.common.filter.XssFilter;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
|
||||
/**
|
||||
* 资源文件配置加载
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class I18nConfig implements WebMvcConfigurer
|
||||
{
|
||||
@Bean
|
||||
public LocaleResolver localeResolver()
|
||||
{
|
||||
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||
// 默认语言
|
||||
slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
|
||||
return slr;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocaleChangeInterceptor localeChangeInterceptor()
|
||||
{
|
||||
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
|
||||
// 参数名
|
||||
lci.setParamName("lang");
|
||||
return lci;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry)
|
||||
{
|
||||
registry.addInterceptor(localeChangeInterceptor());
|
||||
}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import org.apache.ibatis.io.VFS;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Mybatis支持*匹配扫描包
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class MyBatisConfig
|
||||
{
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
|
||||
|
||||
public static String setTypeAliasesPackage(String typeAliasesPackage)
|
||||
{
|
||||
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
|
||||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
|
||||
List<String> allResult = new ArrayList<String>();
|
||||
try
|
||||
{
|
||||
for (String aliasesPackage : typeAliasesPackage.split(","))
|
||||
{
|
||||
List<String> result = new ArrayList<String>();
|
||||
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
|
||||
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
|
||||
Resource[] resources = resolver.getResources(aliasesPackage);
|
||||
if (resources != null && resources.length > 0)
|
||||
{
|
||||
MetadataReader metadataReader = null;
|
||||
for (Resource resource : resources)
|
||||
{
|
||||
if (resource.isReadable())
|
||||
{
|
||||
metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||
try
|
||||
{
|
||||
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.size() > 0)
|
||||
{
|
||||
HashSet<String> hashResult = new HashSet<String>(result);
|
||||
allResult.addAll(hashResult);
|
||||
}
|
||||
}
|
||||
if (allResult.size() > 0)
|
||||
{
|
||||
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return typeAliasesPackage;
|
||||
}
|
||||
|
||||
public Resource[] resolveMapperLocations(String[] mapperLocations)
|
||||
{
|
||||
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
if (mapperLocations != null)
|
||||
{
|
||||
for (String mapperLocation : mapperLocations)
|
||||
{
|
||||
try
|
||||
{
|
||||
Resource[] mappers = resourceResolver.getResources(mapperLocation);
|
||||
resources.addAll(Arrays.asList(mappers));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return resources.toArray(new Resource[resources.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* mybatis 配置
|
||||
*/
|
||||
// @Bean(name = "mysqlSessionFactory")
|
||||
// @Primary
|
||||
// public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
|
||||
// {
|
||||
// String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
|
||||
// String mapperLocations = env.getProperty("mybatis.mapperLocations");
|
||||
// String configLocation = env.getProperty("mybatis.configLocation");
|
||||
// typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
|
||||
// VFS.addImplClass(SpringBootVFS.class);
|
||||
//
|
||||
// final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
|
||||
// sessionFactory.setDataSource(dataSource);
|
||||
// sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
|
||||
// sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
|
||||
// sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
|
||||
// return sessionFactory.getObject();
|
||||
// }
|
||||
|
||||
/**
|
||||
* mybatis-plus 配置:把 SqlSessionFactoryBean 换成 MybatisSqlSessionFactoryBean就行
|
||||
* @param dataSource 数据源
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = "mysqlSessionFactory")
|
||||
@Primary
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
|
||||
{
|
||||
String typeAliasesPackage = env.getProperty("mybatis-plus.typeAliasesPackage");
|
||||
String mapperLocations = env.getProperty("mybatis-plus.mapperLocations");
|
||||
String configLocation = env.getProperty("mybatis-plus.configLocation");
|
||||
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
|
||||
VFS.addImplClass(SpringBootVFS.class);
|
||||
|
||||
final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
|
||||
sessionFactory.setDataSource(dataSource);
|
||||
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
|
||||
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
|
||||
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
|
||||
return sessionFactory.getObject();
|
||||
}
|
||||
|
||||
@Bean(name = "mysqlTransactionManager")
|
||||
@Primary
|
||||
public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
|
||||
@Bean(name = "mysqlSqlSessionTemplate")
|
||||
@Primary
|
||||
public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
|
||||
return new SqlSessionTemplate(sqlSessionFactory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* redis配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.fastbee.framework.interceptor.RepeatSubmitInterceptor;
|
||||
|
||||
/**
|
||||
* 通用配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@@ -36,7 +36,7 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
/** swagger配置 */
|
||||
registry.addResourceHandler("/swagger-ui/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
||||
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
|
||||
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,4 +70,4 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
// 返回新的CorsFilter
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import com.fastbee.framework.config.properties.PermitAllUrlProperties;
|
||||
import com.fastbee.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.fastbee.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.fastbee.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* spring security配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
@Configuration
|
||||
public class SecurityConfig
|
||||
{
|
||||
/**
|
||||
* 自定义用户认证逻辑
|
||||
@@ -65,16 +68,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
private PermitAllUrlProperties permitAllUrl;
|
||||
|
||||
/**
|
||||
* 解决 无法直接注入 AuthenticationManager
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
* 身份验证实现
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception
|
||||
public AuthenticationManager authenticationManager()
|
||||
{
|
||||
return super.authenticationManagerBean();
|
||||
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
|
||||
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
|
||||
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
|
||||
return new ProviderManager(daoAuthenticationProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,44 +94,45 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
* rememberMe | 允许通过remember-me登录的用户访问
|
||||
* authenticated | 用户登录后可访问
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception
|
||||
@Bean
|
||||
@Primary
|
||||
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception
|
||||
{
|
||||
// 注解标记允许匿名访问的url
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
|
||||
permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
|
||||
|
||||
httpSecurity
|
||||
// CSRF禁用,因为不使用session
|
||||
.csrf().disable()
|
||||
// 禁用HTTP响应标头
|
||||
.headers().cacheControl().disable().and()
|
||||
// 认证失败处理类
|
||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
|
||||
// 基于token,所以不需要session
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
// 过滤请求
|
||||
.authorizeRequests()
|
||||
return httpSecurity
|
||||
// CSRF禁用,因为不使用session
|
||||
.csrf(csrf -> csrf.disable())
|
||||
// 禁用HTTP响应标头
|
||||
.headers((headersCustomizer) -> {
|
||||
headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
|
||||
})
|
||||
// 认证失败处理类
|
||||
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
|
||||
// 基于token,所以不需要session
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
// 注解标记允许匿名访问的url
|
||||
.authorizeHttpRequests((requests) -> {
|
||||
permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
|
||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
||||
.antMatchers("/login", "/register", "/captchaImage","/iot/tool/register","/iot/tool/ntp","/iot/tool/download",
|
||||
"/iot/tool/mqtt/auth","/iot/tool/mqtt/authv5","/iot/tool/mqtt/webhook","/iot/tool/mqtt/webhookv5","/auth/**/**",
|
||||
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll()
|
||||
.antMatchers("/zlmhook/**").permitAll()
|
||||
.antMatchers("/goview/sys/login","/goview/project/getData").permitAll()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.headers().frameOptions().disable();
|
||||
// 添加Logout filter
|
||||
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
|
||||
// 添加JWT filter
|
||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
// 添加CORS filter
|
||||
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
|
||||
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
|
||||
requests.antMatchers("/login", "/register", "/captchaImage","/iot/tool/register","/iot/tool/ntp","/iot/tool/download",
|
||||
"/iot/tool/mqtt/auth","/iot/tool/mqtt/authv5","/iot/tool/mqtt/webhook","/iot/tool/mqtt/webhookv5","/auth/**/**",
|
||||
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll()
|
||||
.antMatchers("/zlmhook/**").permitAll()
|
||||
.antMatchers("/goview/sys/login","/goview/project/getData").permitAll()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated();
|
||||
})
|
||||
// 添加Logout filter
|
||||
.logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
|
||||
// 添加JWT filter
|
||||
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// 添加CORS filter
|
||||
.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
|
||||
.addFilterBefore(corsFilter, LogoutFilter.class)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,13 +143,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
{
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 身份认证接口
|
||||
*/
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception
|
||||
{
|
||||
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 服务相关配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
@@ -14,7 +15,7 @@ public class ServerConfig
|
||||
{
|
||||
/**
|
||||
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
|
||||
*
|
||||
*
|
||||
* @return 服务地址
|
||||
*/
|
||||
public String getUrl()
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 解决Mybatis Plus Order By SQL注入问题
|
||||
* @author admin
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final static String[] KEYWORDS = { "master", "truncate", "insert", "select", "delete", "update", "declare",
|
||||
"alter", "drop", "sleep" };
|
||||
|
||||
/**
|
||||
* 判断Controller是否包含page 参数
|
||||
* @param parameter 参数
|
||||
* @return 是否过滤
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.getParameterType().equals(Page.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameter 入参集合
|
||||
* @param mavContainer model 和 view
|
||||
* @param webRequest web相关
|
||||
* @param binderFactory 入参解析
|
||||
* @return 检查后新的page对象
|
||||
* <p>
|
||||
* page 只支持查询 GET .如需解析POST获取请求报文体处理
|
||||
*/
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
|
||||
|
||||
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
|
||||
String[] ascs = request.getParameterValues("ascs");
|
||||
String[] descs = request.getParameterValues("descs");
|
||||
String current = request.getParameter("current");
|
||||
String size = request.getParameter("size");
|
||||
|
||||
Page<?> page = new Page<>();
|
||||
if (StrUtil.isNotBlank(current)) {
|
||||
page.setCurrent(Long.parseLong(current));
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(size)) {
|
||||
page.setSize(Long.parseLong(size));
|
||||
}
|
||||
List<OrderItem> orderItemList = new ArrayList<>();
|
||||
Optional.ofNullable(ascs).ifPresent(s -> orderItemList.addAll(
|
||||
Arrays.stream(s).filter(sqlInjectPredicate()).map(OrderItem::asc).collect(Collectors.toList())));
|
||||
Optional.ofNullable(descs).ifPresent(s -> orderItemList.addAll(
|
||||
Arrays.stream(s).filter(sqlInjectPredicate()).map(OrderItem::desc).collect(Collectors.toList())));
|
||||
page.addOrder(orderItemList);
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户输入里面有没有关键字
|
||||
* @return Predicate
|
||||
*/
|
||||
private Predicate<String> sqlInjectPredicate() {
|
||||
return sql -> {
|
||||
for (String keyword : KEYWORDS) {
|
||||
if (StrUtil.containsIgnoreCase(sql, keyword)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,31 @@
|
||||
package com.fastbee.framework.config.properties;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* druid 配置属性
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "spring.datasource.dynamic.druid")
|
||||
public class DruidProperties
|
||||
{
|
||||
@Value("${spring.datasource.druid.initialSize}")
|
||||
private int initialSize;
|
||||
|
||||
@Value("${spring.datasource.druid.minIdle}")
|
||||
private int minIdle;
|
||||
|
||||
@Value("${spring.datasource.druid.maxActive}")
|
||||
private int maxActive;
|
||||
|
||||
@Value("${spring.datasource.druid.maxWait}")
|
||||
private int maxWait;
|
||||
|
||||
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
|
||||
private int timeBetweenEvictionRunsMillis;
|
||||
|
||||
@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
|
||||
private int minEvictableIdleTimeMillis;
|
||||
|
||||
@Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
|
||||
private int maxEvictableIdleTimeMillis;
|
||||
|
||||
@Value("${spring.datasource.druid.validationQuery}")
|
||||
private Integer initialSize;
|
||||
private Integer minIdle;
|
||||
private Integer maxActive;
|
||||
private Integer maxWait;
|
||||
private Long timeBetweenEvictionRunsMillis;
|
||||
private Long minEvictableIdleTimeMillis;
|
||||
private Long maxEvictableIdleTimeMillis;
|
||||
private String validationQuery;
|
||||
|
||||
@Value("${spring.datasource.druid.testWhileIdle}")
|
||||
private boolean testWhileIdle;
|
||||
|
||||
@Value("${spring.datasource.druid.testOnBorrow}")
|
||||
private boolean testOnBorrow;
|
||||
|
||||
@Value("${spring.datasource.druid.testOnReturn}")
|
||||
private boolean testOnReturn;
|
||||
|
||||
private Boolean testWhileIdle;
|
||||
private Boolean testOnBorrow;
|
||||
private Boolean testOnReturn;
|
||||
public DruidDataSource dataSource(DruidDataSource datasource)
|
||||
{
|
||||
/** 配置初始化大小、最小、最大 */
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.fastbee.framework.config.properties;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
@@ -19,7 +20,7 @@ import com.fastbee.common.annotation.Anonymous;
|
||||
|
||||
/**
|
||||
* 设置Anonymous注解允许匿名访问的url
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@@ -44,12 +45,12 @@ public class PermitAllUrlProperties implements InitializingBean, ApplicationCont
|
||||
|
||||
// 获取方法上边的注解 替代path variable 为 *
|
||||
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
|
||||
Optional.ofNullable(method).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()
|
||||
Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
|
||||
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
||||
|
||||
// 获取类上边的注解, 替代path variable 为 *
|
||||
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
|
||||
Optional.ofNullable(controller).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()
|
||||
Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
|
||||
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 数据源切换处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class DynamicDataSourceContextHolder
|
||||
@@ -14,7 +14,7 @@ public class DynamicDataSourceContextHolder
|
||||
|
||||
/**
|
||||
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||
*/
|
||||
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||
|
||||
|
||||
@@ -47,8 +47,9 @@ public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
|
||||
/**
|
||||
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @param request 请求信息
|
||||
* @param annotation 防重复注解参数
|
||||
* @return 结果
|
||||
* @throws Exception
|
||||
*/
|
||||
public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
|
||||
|
||||
@@ -18,7 +18,7 @@ import eu.bitwalker.useragentutils.UserAgent;
|
||||
|
||||
/**
|
||||
* 异步工厂(产生任务用)
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AsyncFactory
|
||||
@@ -27,7 +27,7 @@ public class AsyncFactory
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param status 状态
|
||||
* @param message 消息
|
||||
@@ -38,7 +38,7 @@ public class AsyncFactory
|
||||
final Object... args)
|
||||
{
|
||||
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||
final String ip = IpUtils.getIpAddr();
|
||||
return new TimerTask()
|
||||
{
|
||||
@Override
|
||||
@@ -82,7 +82,7 @@ public class AsyncFactory
|
||||
|
||||
/**
|
||||
* 操作日志记录
|
||||
*
|
||||
*
|
||||
* @param operLog 操作日志信息
|
||||
* @return 任务task
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.fastbee.framework.mybatis.config;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.DialectFactory;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class AutoPaginationInnerInterceptor extends PaginationInnerInterceptor {
|
||||
@Override
|
||||
protected IDialect findIDialect(Executor executor) {
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = executor.getTransaction().getConnection();
|
||||
String jdbcUrl = conn.getMetaData().getURL();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (this.getDialect() != null) {
|
||||
return this.getDialect();
|
||||
} else if (this.getDbType() != null) {
|
||||
this.setDialect(DialectFactory.getDialect(this.getDbType()));
|
||||
return this.getDialect();
|
||||
} else {
|
||||
return DialectFactory.getDialect(JdbcUtils.getDbType(executor));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.fastbee.framework.mybatis.config;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.fastbee.framework.config.SqlFilterArgumentResolver;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author admin
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@MapperScan("com.fastbee.**.mapper")
|
||||
public class MybatisPlusConfig implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* SQL 过滤器避免SQL 注入
|
||||
* @param argumentResolvers
|
||||
*/
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(new SqlFilterArgumentResolver());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(paginationInnerInterceptor());
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页插件,自动识别数据库类型
|
||||
*/
|
||||
public PaginationInnerInterceptor paginationInnerInterceptor() {
|
||||
PaginationInnerInterceptor paginationInnerInterceptor = new AutoPaginationInnerInterceptor();
|
||||
// 分页合理化
|
||||
paginationInnerInterceptor.setOverflow(true);
|
||||
return paginationInnerInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用网卡信息绑定雪花生成器
|
||||
* 防止集群雪花ID重复
|
||||
*/
|
||||
@Bean
|
||||
public IdentifierGenerator idGenerator() {
|
||||
return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
|
||||
}
|
||||
/**
|
||||
* 审计字段自动填充
|
||||
* @return {@link MybatisPlusMetaObjectHandler}
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusMetaObjectHandler mybatisPlusMetaObjectHandler() {
|
||||
return new MybatisPlusMetaObjectHandler();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.fastbee.framework.mybatis.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.utils.SecurityUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* MybatisPlus 自动填充配置
|
||||
*
|
||||
* @author admin
|
||||
*/
|
||||
@Slf4j
|
||||
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
log.debug("mybatisPlus插入填充--------------");
|
||||
Date date = new Date();
|
||||
|
||||
fillValIfNullByName("createTime", date, metaObject, false);
|
||||
fillValIfNullByName("updateTime", date, metaObject, false);
|
||||
fillValIfNullByName("createBy", getUserName(), metaObject, false);
|
||||
fillValIfNullByName("updateBy", getUserName(), metaObject, false);
|
||||
fillValIfNullByName("deleteFlag", "1", metaObject, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
log.debug("mybatisPlus更新填充--------------");
|
||||
fillValIfNullByName("updateTime", new Date(), metaObject, true);
|
||||
fillValIfNullByName("updateBy", getUserName(), metaObject, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充值,先判断是否有手动设置,优先手动设置的值,例如:job必须手动设置
|
||||
* @param fieldName 属性名
|
||||
* @param fieldVal 属性值
|
||||
* @param metaObject MetaObject
|
||||
* @param isCover 是否覆盖原有值,避免更新操作手动入参
|
||||
*/
|
||||
private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {
|
||||
// 1. 没有 get 方法
|
||||
if (!metaObject.hasSetter(fieldName)) {
|
||||
return;
|
||||
}
|
||||
// 2. 如果用户有手动设置的值
|
||||
Object userSetValue = metaObject.getValue(fieldName);
|
||||
String setValueStr = StrUtil.str(userSetValue, Charset.defaultCharset());
|
||||
if (StrUtil.isNotBlank(setValueStr) && !isCover) {
|
||||
return;
|
||||
}
|
||||
// 3. field 类型相同时设置
|
||||
Class<?> getterType = metaObject.getGetterType(fieldName);
|
||||
if (ClassUtils.isAssignableValue(getterType, fieldVal)) {
|
||||
metaObject.setValue(fieldName, fieldVal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 spring security 当前的用户名
|
||||
* @return 当前用户名
|
||||
*/
|
||||
private String getUserName() {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
return loginUser.getUsername();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.fastbee.framework.mybatis.helper;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.mybatis.enums.DataBaseType;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据库助手
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class DataBaseHelper {
|
||||
|
||||
private static final DynamicRoutingDataSource DS = SpringUtils.getBean(DynamicRoutingDataSource.class);
|
||||
public static final String DEFAULT_DATASOURCE_NAME = "master";
|
||||
|
||||
/**
|
||||
* 获取当前数据库类型
|
||||
*/
|
||||
public static DataBaseType getDataBaseType(String dataName) {
|
||||
DataSource dataSource = DS.getDataSources().get(dataName);
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
String databaseProductName = metaData.getDatabaseProductName();
|
||||
return DataBaseType.find(databaseProductName);
|
||||
} catch (SQLException e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMySql() {
|
||||
return DataBaseType.MY_SQL == getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
}
|
||||
|
||||
public static boolean isOracle() {
|
||||
return DataBaseType.ORACLE == getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
}
|
||||
|
||||
public static boolean isPostgerSql() {
|
||||
return DataBaseType.POSTGRE_SQL == getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
}
|
||||
|
||||
public static boolean isSqlServer() {
|
||||
return DataBaseType.SQL_SERVER == getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
}
|
||||
|
||||
public static boolean isDm() {
|
||||
return DataBaseType.DM == getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
}
|
||||
|
||||
public static boolean isMySql(String dataName) {
|
||||
return DataBaseType.MY_SQL == getDataBaseType(dataName);
|
||||
}
|
||||
|
||||
public static boolean isOracle(String dataName) {
|
||||
return DataBaseType.ORACLE == getDataBaseType(dataName);
|
||||
}
|
||||
|
||||
public static boolean isPostgerSql(String dataName) {
|
||||
return DataBaseType.POSTGRE_SQL == getDataBaseType(dataName);
|
||||
}
|
||||
|
||||
public static boolean isSqlServer(String dataName) {
|
||||
return DataBaseType.SQL_SERVER == getDataBaseType(dataName);
|
||||
}
|
||||
|
||||
public static boolean isDm(String dataName) {
|
||||
return DataBaseType.DM == getDataBaseType(dataName);
|
||||
}
|
||||
|
||||
public static String findInSet(Object var1, String var2) {
|
||||
DataBaseType dataBasyType = getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
String var = Convert.toStr(var1);
|
||||
if (dataBasyType == DataBaseType.SQL_SERVER) {
|
||||
// charindex(',100,' , ',0,100,101,') <> 0
|
||||
return String.format("charindex(',%s,' , ','+%s+',') <> 0", var, var2);
|
||||
} else if (dataBasyType == DataBaseType.POSTGRE_SQL) {
|
||||
// (select strpos(',0,100,101,' , ',100,')) <> 0
|
||||
return String.format("(select strpos(','||%s||',' , ',%s,')) <> 0", var2, var);
|
||||
} else if (dataBasyType == DataBaseType.ORACLE || dataBasyType == DataBaseType.DM) {
|
||||
// instr(',0,100,101,' , ',100,') <> 0
|
||||
return String.format("instr(','||%s||',' , ',%s,') <> 0", var2, var);
|
||||
}
|
||||
// find_in_set(100 , '0,100,101')
|
||||
return String.format("find_in_set(%s , %s) <> 0", var, var2);
|
||||
}
|
||||
|
||||
public static String findInSetColumn(String var1, String var2) {
|
||||
DataBaseType dataBasyType = getDataBaseType(DEFAULT_DATASOURCE_NAME);
|
||||
String var = Convert.toStr(var1);
|
||||
if (dataBasyType == DataBaseType.SQL_SERVER) {
|
||||
// charindex(','+de.dept_id+',' , ',0,100,101,') <> 0
|
||||
return String.format("charindex(',' + %s + ',' , ',' + %s + ',') <> 0", var, var2);
|
||||
} else if (dataBasyType == DataBaseType.POSTGRE_SQL) {
|
||||
// (select strpos(',0,100,101,' , ',' || de.dept_id || ',')) <> 0
|
||||
return String.format("(select strpos(','||%s||',' , ','|| %s ||',')) <> 0", var2, var);
|
||||
} else if (dataBasyType == DataBaseType.ORACLE|| dataBasyType == DataBaseType.DM) {
|
||||
// instr(',0,100,101,' , ','||de.dept_id||',') <> 0
|
||||
return String.format("instr(','||%s||',' , ','||%s||',') <> 0", var2, var);
|
||||
}
|
||||
// find_in_set(de.dept_id , '0,100,101')
|
||||
return String.format("find_in_set(%s , '%s') <> 0", var, var2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前加载的数据库名
|
||||
*/
|
||||
public static List<String> getDataSourceNameList() {
|
||||
return new ArrayList<>(DS.getDataSources().keySet());
|
||||
}
|
||||
|
||||
public static String getDeptCondition(Long deptId) {
|
||||
if (deptId == null || deptId == 0) {
|
||||
// 无效条件,确保查询不会返回结果
|
||||
return "1=1";
|
||||
}
|
||||
if (isPostgerSql()) {
|
||||
return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE " + deptId + "::text = ANY(string_to_array(ancestors, ',')) OR dept_id = " + deptId + ")";
|
||||
} else if (isSqlServer()) {
|
||||
return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE CHARINDEX(',' + CAST(" + deptId + " AS VARCHAR) + ',', ',' + ancestors + ',') > 0 OR dept_id = " + deptId + ")";
|
||||
} else if (isOracle()) {
|
||||
return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE INSTR(',' || ancestors || ',', ',' || " + deptId + " || ',') > 0 OR dept_id = " + deptId + ")";
|
||||
} else if (isDm()) {
|
||||
return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE INSTR(',' || ancestors || ',', ',' || " + deptId + " || ',') > 0 OR dept_id = " + deptId + ")";
|
||||
} else if (isMySql()) {
|
||||
return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE FIND_IN_SET(" + deptId + ", ancestors) > 0 OR dept_id = " + deptId + ")";
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported database type");
|
||||
}
|
||||
}
|
||||
|
||||
public static String checkTime(Integer timeout) {
|
||||
if (timeout == null || timeout == 0) {
|
||||
// 无效条件,确保查询不会返回结果
|
||||
return "";
|
||||
}
|
||||
if (isPostgerSql()) {
|
||||
return "CURRENT_TIMESTAMP > last_connect_time + interval '1 seconds' * " + timeout;
|
||||
} else if (isSqlServer()) {
|
||||
return "CURRENT_TIMESTAMP > DATEADD(SECOND, " + timeout + " last_connect_time)";
|
||||
} else if (isOracle()) {
|
||||
return "CURRENT_TIMESTAMP > last_connect_time + (" + timeout + " / 86400)";
|
||||
} else if (isDm()) {
|
||||
return "CURRENT_TIMESTAMP > DATEADD(SECOND, " + timeout + ", last_connect_time)";
|
||||
} else if (isMySql()) {
|
||||
return "CURRENT_TIMESTAMP > DATE_ADD(last_connect_time, INTERVAL " + timeout + " SECOND)";
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported database type");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.fastbee.common.utils.MessageUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -20,7 +22,7 @@ import com.fastbee.framework.web.service.TokenService;
|
||||
|
||||
/**
|
||||
* 自定义退出处理类 返回成功
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@@ -31,7 +33,7 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
|
||||
|
||||
/**
|
||||
* 退出处理
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@@ -45,8 +47,8 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
|
||||
// 删除用户缓存记录
|
||||
tokenService.delLoginUser(loginUser.getToken());
|
||||
// 记录用户退出日志
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
|
||||
}
|
||||
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功")));
|
||||
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success"))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
package com.fastbee.framework.web.domain;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import com.fastbee.common.utils.Arith;
|
||||
import com.fastbee.common.utils.ip.IpUtils;
|
||||
import com.fastbee.framework.web.domain.server.Cpu;
|
||||
import com.fastbee.framework.web.domain.server.Jvm;
|
||||
import com.fastbee.framework.web.domain.server.Mem;
|
||||
import com.fastbee.framework.web.domain.server.Sys;
|
||||
import com.fastbee.framework.web.domain.server.SysFile;
|
||||
import com.fastbee.framework.web.domain.server.*;
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
import oshi.hardware.CentralProcessor.TickType;
|
||||
@@ -21,15 +13,20 @@ import oshi.software.os.OSFileStore;
|
||||
import oshi.software.os.OperatingSystem;
|
||||
import oshi.util.Util;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 服务器相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Server
|
||||
{
|
||||
private static final int OSHI_WAIT_SECOND = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* CPU相关信息
|
||||
*/
|
||||
@@ -209,7 +206,7 @@ public class Server
|
||||
|
||||
/**
|
||||
* 字节转换
|
||||
*
|
||||
*
|
||||
* @param size 字节大小
|
||||
* @return 转换后值
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.fastbee.framework.web.domain.server;
|
||||
|
||||
|
||||
import com.fastbee.common.utils.Arith;
|
||||
|
||||
/**
|
||||
* CPU相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Cpu
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.fastbee.framework.web.domain.server;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import com.fastbee.common.utils.Arith;
|
||||
import com.fastbee.common.utils.DateUtils;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
/**
|
||||
* JVM相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Jvm
|
||||
@@ -117,7 +119,7 @@ public class Jvm
|
||||
*/
|
||||
public String getRunTime()
|
||||
{
|
||||
return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
|
||||
return DateUtils.timeDistance(DateUtils.getNowDate(), DateUtils.getServerStartDate());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.fastbee.framework.web.domain.server;
|
||||
|
||||
|
||||
import com.fastbee.common.utils.Arith;
|
||||
|
||||
/**
|
||||
* 內存相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Mem
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.fastbee.framework.web.domain.server;
|
||||
|
||||
/**
|
||||
* 系统相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Sys
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.fastbee.framework.web.domain.server;
|
||||
|
||||
/**
|
||||
* 系统文件相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SysFile
|
||||
|
||||
@@ -7,17 +7,21 @@ import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingPathVariableException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import com.fastbee.common.constant.HttpStatus;
|
||||
import com.fastbee.common.core.domain.AjaxResult;
|
||||
import com.fastbee.common.core.text.Convert;
|
||||
import com.fastbee.common.exception.DemoModeException;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.html.EscapeUtil;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
@@ -59,6 +63,33 @@ public class GlobalExceptionHandler
|
||||
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求路径中缺少必需的路径变量
|
||||
*/
|
||||
@ExceptionHandler(MissingPathVariableException.class)
|
||||
public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
|
||||
{
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
|
||||
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求参数类型不匹配
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
|
||||
{
|
||||
String requestURI = request.getRequestURI();
|
||||
String value = Convert.toStr(e.getValue());
|
||||
if (StringUtils.isNotEmpty(value))
|
||||
{
|
||||
value = EscapeUtil.clean(value);
|
||||
}
|
||||
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
|
||||
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截未知的运行时异常
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user