若依 2.1

pull/13/head
RuoYi 2018-07-09 08:44:52 +08:00
parent a66f603437
commit 57773e6eff
458 changed files with 103815 additions and 0 deletions

20
LICENSE Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 RuoYi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

92
README.md Normal file
View File

@ -0,0 +1,92 @@
## 平台简介
一直想做一款后台管理系统看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序如网站管理后台网站会员中心CMSCRMOA。所有前端后台代码封装过后十分精简易上手出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
性别男,若依是女儿的名字。
若依基于hplus和inspinia两套后台系统摸版开发。有需要可自行到群内下载。
http://www.zi-han.net/theme/hplus
http://webapplayers.com/inspinia_admin-v2.7.1
## 内置功能
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现。
3. 岗位管理:配置系统用户所属担任职务。
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 参数管理:对系统动态配置常用参数。
8. 通知公告:系统通知公告信息发布维护。
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
10. 登录日志:系统登录日志记录查询包含登录异常。
11. 在线用户:当前系统中活跃用户状态监控。
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
13. 代码生成前后端代码的生成java、html、xml、sql)支持CRUD下载 。
14. 系统接口根据业务代码自动生成相关的api接口文档。
15. 在线构建器拖动表单元素生成相应的HTML代码。
16. 连接池监视监视当期系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
## 在线体验
> admin/admin123
地址http://www.ruoyi.club
## 演示图
<table>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%99%BB%E5%BD%95%E7%95%8C%E9%9D%A2.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E9%A6%96%E9%A1%B5.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%94%A8%E6%88%B7%E4%BF%AE%E6%94%B9.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E8%A7%92%E8%89%B2%E7%AE%A1%E7%90%86.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E8%A7%92%E8%89%B2%E4%BF%AE%E6%94%B9.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E8%8F%9C%E5%8D%95%E7%AE%A1%E7%90%86.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E4%BF%AE%E6%94%B9%E8%8F%9C%E5%8D%95.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E9%83%A8%E9%97%A8%E7%AE%A1%E7%90%86.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E4%BF%AE%E6%94%B9%E9%83%A8%E9%97%A8.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%B2%97%E4%BD%8D%E7%AE%A1%E7%90%86.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%B2%97%E4%BD%8D%E4%BF%AE%E6%94%B9.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AD%97%E5%85%B8%E7%B1%BB%E5%9E%8B.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AD%97%E5%85%B8%E6%95%B0%E6%8D%AE.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E9%80%9A%E7%9F%A5%E7%AE%A1%E7%90%86.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E6%93%8D%E4%BD%9C%E6%97%A5%E5%BF%97.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%99%BB%E5%BD%95%E6%97%A5%E5%BF%97.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E6%97%A5%E5%BF%97.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%9C%A8%E7%BA%BF%E7%94%A8%E6%88%B7.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90.png"/></td>
</tr>
<tr>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E6%95%B0%E6%8D%AE%E7%9B%91%E6%8E%A7.png"/></td>
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%B3%BB%E7%BB%9F%E6%8E%A5%E5%8F%A3.png"/></td>
</tr>
</table>
## 若依交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/QQ群-1389287-blue.svg)](http://shang.qq.com/wpa/qunwpa?idkey=4a9a52f5d9d9c65a8ea67859170ba835d95fc50ec74a2a722293e60e036b5016) 或 [![加入QQ群](https://img.shields.io/badge/QQ群-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN),推荐点击按钮入群,当然如果无法成功操作,请自行搜索群号`1389287`进行添加

Binary file not shown.

290
pom.xml Normal file
View File

@ -0,0 +1,290 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<artifactId>RuoYi</artifactId>
<version>2.1.0</version>
<packaging>jar</packaging>
<name>RuoYi</name>
<description>若依管理系统</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<shiro.version>1.4.0</shiro.version>
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
<mybatis.spring.boot.starter.version>1.3.2</mybatis.spring.boot.starter.version>
<pagehelper.spring.boot.starter.version>1.2.5</pagehelper.spring.boot.starter.version>
<fastjson.version>1.2.47</fastjson.version>
<druid.version>1.1.10</druid.version>
<commons.io.version>2.5</commons.io.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version>
<bitwalker.version>1.19</bitwalker.version>
<lombok.version>1.16.18</lombok.version>
<velocity.version>1.7</velocity.version>
<kaptcha.version>2.3.2</kaptcha.version>
<swagger.version>2.7.0</swagger.version>
<jsoup.version>1.11.3</jsoup.version>
</properties>
<dependencies>
<!-- SpringBoot 核心包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!--
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
-->
</dependency>
<!-- SpringBoot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot集成thymeleaf模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
<!-- thymeleaf网页解析 -->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.starter.version}</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.spring.boot.starter.version}</version>
</dependency>
<!--阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<!--文件上传工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
<!--Shiro核心框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- Shiro使用Srping框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- Shiro使用EhCache缓存框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- thymeleaf模板引擎和shiro框架的整合 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>${thymeleaf.extras.shiro.version}</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 解析客户端操作系统、浏览器等 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>${bitwalker.version}</version>
</dependency>
<!--Spring框架基本的核心工具-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- 定时任务 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<exclusions>
<exclusion>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>${velocity.version}</version>
</dependency>
<!--验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
<exclusions>
<exclusion>
<artifactId>javax.servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- swagger2-UI-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- HTML解析器 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

86
ry.sh Normal file
View File

@ -0,0 +1,86 @@
#!/bin/bash
AppName=RuoYi.jar
#JVM参数
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
APP_HOME=`pwd`
LOG_PATH=$APP_HOME/logs/$AppName.log
if [ "$1" = "" ];
then
echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m"
exit 1
fi
if [ "$AppName" = "" ];
then
echo -e "\033[0;31m 未输入应用名 \033[0m"
exit 1
fi
function start()
{
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
if [ x"$PID" != x"" ]; then
echo "$AppName is running..."
else
nohup java -jar $JVM_OPTS target/$AppName > /dev/null 2>&1 &
echo "Start $AppName success..."
fi
}
function stop()
{
echo "Stop $AppName"
PID=""
query(){
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
}
query
if [ x"$PID" != x"" ]; then
kill -TERM $PID
echo "$AppName (pid:$PID) exiting..."
while [ x"$PID" != x"" ]
do
sleep 1
query
done
echo "$AppName exited."
else
echo "$AppName already stopped."
fi
}
function restart()
{
stop
sleep 2
start
}
function status()
{
PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`
if [ $PID != 0 ];then
echo "$AppName is running..."
else
echo "$AppName is not running..."
fi
}
case $1 in
start)
start;;
stop)
stop;;
restart)
restart;;
status)
status;;
*)
esac

170
sql/quartz.sql Normal file
View File

@ -0,0 +1,170 @@
-- ----------------------------
-- 1、存储每一个已配置的 jobDetail 的详细信息
-- ----------------------------
drop table if exists QRTZ_JOB_DETAILS;
create table QRTZ_JOB_DETAILS (
sched_name varchar(120) not null,
job_name varchar(200) not null,
job_group varchar(200) not null,
description varchar(250) null,
job_class_name varchar(250) not null,
is_durable varchar(1) not null,
is_nonconcurrent varchar(1) not null,
is_update_data varchar(1) not null,
requests_recovery varchar(1) not null,
job_data blob null,
primary key (sched_name,job_name,job_group)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 2、 存储已配置的 Trigger 的信息
-- ----------------------------
drop table if exists QRTZ_TRIGGERS;
create table QRTZ_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
job_name varchar(200) not null,
job_group varchar(200) not null,
description varchar(250) null,
next_fire_time bigint(13) null,
prev_fire_time bigint(13) null,
priority integer null,
trigger_state varchar(16) not null,
trigger_type varchar(8) not null,
start_time bigint(13) not null,
end_time bigint(13) null,
calendar_name varchar(200) null,
misfire_instr smallint(2) null,
job_data blob null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,job_name,job_group) references QRTZ_JOB_DETAILS(sched_name,job_name,job_group)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 3、 存储简单的 Trigger包括重复次数间隔以及已触发的次数
-- ----------------------------
drop table if exists QRTZ_SIMPLE_TRIGGERS;
create table QRTZ_SIMPLE_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
repeat_count bigint(7) not null,
repeat_interval bigint(12) not null,
times_triggered bigint(10) not null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 4、 存储 Cron Trigger包括 Cron 表达式和时区信息
-- ----------------------------
drop table if exists QRTZ_CRON_TRIGGERS;
create table QRTZ_CRON_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
cron_expression varchar(200) not null,
time_zone_id varchar(80),
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型JobStore 并不知道如何存储实例的时候)
-- ----------------------------
drop table if exists QRTZ_BLOB_TRIGGERS;
create table QRTZ_BLOB_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
blob_data blob null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围
-- ----------------------------
drop table if exists QRTZ_CALENDARS;
create table QRTZ_CALENDARS (
sched_name varchar(120) not null,
calendar_name varchar(200) not null,
calendar blob not null,
primary key (sched_name,calendar_name)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 7、 存储已暂停的 Trigger 组的信息
-- ----------------------------
drop table if exists QRTZ_PAUSED_TRIGGER_GRPS;
create table QRTZ_PAUSED_TRIGGER_GRPS (
sched_name varchar(120) not null,
trigger_group varchar(200) not null,
primary key (sched_name,trigger_group)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息
-- ----------------------------
drop table if exists QRTZ_FIRED_TRIGGERS;
create table QRTZ_FIRED_TRIGGERS (
sched_name varchar(120) not null,
entry_id varchar(95) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
instance_name varchar(200) not null,
fired_time bigint(13) not null,
sched_time bigint(13) not null,
priority integer not null,
state varchar(16) not null,
job_name varchar(200) null,
job_group varchar(200) null,
is_nonconcurrent varchar(1) null,
requests_recovery varchar(1) null,
primary key (sched_name,entry_id)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例
-- ----------------------------
drop table if exists QRTZ_SCHEDULER_STATE;
create table QRTZ_SCHEDULER_STATE (
sched_name varchar(120) not null,
instance_name varchar(200) not null,
last_checkin_time bigint(13) not null,
checkin_interval bigint(13) not null,
primary key (sched_name,instance_name)
) engine=innodb default charset=utf8;
-- ----------------------------
-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁)
-- ----------------------------
drop table if exists QRTZ_LOCKS;
create table QRTZ_LOCKS (
sched_name varchar(120) not null,
lock_name varchar(40) not null,
primary key (sched_name,lock_name)
) engine=innodb default charset=utf8;
drop table if exists QRTZ_SIMPROP_TRIGGERS;
create table QRTZ_SIMPROP_TRIGGERS (
sched_name varchar(120) not null,
trigger_name varchar(200) not null,
trigger_group varchar(200) not null,
str_prop_1 varchar(512) null,
str_prop_2 varchar(512) null,
str_prop_3 varchar(512) null,
int_prop_1 int null,
int_prop_2 int null,
long_prop_1 bigint null,
long_prop_2 bigint null,
dec_prop_1 numeric(13,4) null,
dec_prop_2 numeric(13,4) null,
bool_prop_1 varchar(1) null,
bool_prop_2 varchar(1) null,
primary key (sched_name,trigger_name,trigger_group),
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
) engine=innodb default charset=utf8;
commit;

2890
sql/ruoyi.html Normal file

File diff suppressed because it is too large Load Diff

4068
sql/ruoyi.pdm Normal file

File diff suppressed because it is too large Load Diff

597
sql/ry_20180709.sql Normal file
View File

@ -0,0 +1,597 @@
-- ----------------------------
-- 1、部门表
-- ----------------------------
drop table if exists sys_dept;
create table sys_dept (
dept_id int(11) not null auto_increment comment '部门id',
parent_id int(11) default 0 comment '父部门id',
dept_name varchar(30) default '' comment '部门名称',
order_num int(4) default 0 comment '显示顺序',
leader varchar(20) default '' comment '负责人',
phone varchar(11) default '' comment '联系电话',
email varchar(50) default '' comment '邮箱',
status char(1) default '0' comment '部门状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
primary key (dept_id)
) engine=innodb auto_increment=200 default charset=utf8 comment = '部门表';
-- ----------------------------
-- 初始化-部门表数据
-- ----------------------------
insert into sys_dept values(100, 0, '若依集团', 0, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(101, 100, '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(102, 100, '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(103, 100, '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(104, 100, '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(105, 100, '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(106, 101, '研发一部', 1, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(107, 101, '研发二部', 2, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(108, 102, '市场一部', 1, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
insert into sys_dept values(109, 102, '市场二部', 2, '若依', '15888888888', 'ry@qq.com', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00');
-- ----------------------------
-- 2、用户信息表
-- ----------------------------
drop table if exists sys_user;
create table sys_user (
user_id int(11) not null auto_increment comment '用户ID',
dept_id int(11) default null comment '部门ID',
login_name varchar(30) not null comment '登录账号',
user_name varchar(30) not null comment '用户昵称',
user_type varchar(2) default '00' comment '用户类型00系统用户',
email varchar(50) default '' comment '用户邮箱',
phonenumber varchar(11) default '' comment '手机号码',
sex char(1) default '0' comment '用户性别0男 1女 2未知',
avatar varchar(100) default '' comment '头像路径',
password varchar(50) default '' comment '密码',
salt varchar(20) default '' comment '盐加密',
status char(1) default '0' comment '帐号状态0正常 1停用',
del_flag char(1) default '0' comment '删除标志0代表存在 2代表删除',
login_ip varchar(20) default '' comment '最后登陆IP',
login_date datetime comment '最后登陆时间',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (user_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '用户信息表';
-- ----------------------------
-- 初始化-用户信息表数据
-- ----------------------------
insert into sys_user values(1, 106, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', '2018-03-16 11-33-00', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
insert into sys_user values(2, 108, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', '2018-03-16 11-33-00', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '测试员');
-- ----------------------------
-- 3、岗位信息表
-- ----------------------------
drop table if exists sys_post;
create table sys_post
(
post_id int(11) not null auto_increment comment '岗位ID',
post_code varchar(64) not null comment '岗位编码',
post_name varchar(50) not null comment '岗位名称',
post_sort int(4) not null comment '显示顺序',
status char(1) not null comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (post_id)
) engine=innodb default charset=utf8 comment = '岗位信息表';
-- ----------------------------
-- 初始化-岗位信息表数据
-- ----------------------------
insert into sys_post values(1, 'ceo', '董事长', 1, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- ----------------------------
-- 4、角色信息表
-- ----------------------------
drop table if exists sys_role;
create table sys_role (
role_id int(11) not null auto_increment comment '角色ID',
role_name varchar(30) not null comment '角色名称',
role_key varchar(100) not null comment '角色权限字符串',
role_sort int(4) not null comment '显示顺序',
status char(1) not null comment '角色状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (role_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '角色信息表';
-- ----------------------------
-- 初始化-角色信息表数据
-- ----------------------------
insert into sys_role values('1', '管理员', 'admin', 1, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
insert into sys_role values('2', '普通角色', 'common', 2, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '普通角色');
-- ----------------------------
-- 5、菜单权限表
-- ----------------------------
drop table if exists sys_menu;
create table sys_menu (
menu_id int(11) not null auto_increment comment '菜单ID',
menu_name varchar(50) not null comment '菜单名称',
parent_id int(11) default 0 comment '父菜单ID',
order_num int(4) default null comment '显示顺序',
url varchar(200) default '' comment '请求地址',
menu_type char(1) default '' comment '菜单类型M目录 C菜单 F按钮',
visible char(1) default 0 comment '菜单状态0显示 1隐藏',
perms varchar(100) default '' comment '权限标识',
icon varchar(100) default '' comment '菜单图标',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (menu_id)
) engine=innodb auto_increment=2000 default charset=utf8 comment = '菜单权限表';
-- ----------------------------
-- 初始化-菜单信息表数据
-- ----------------------------
-- 一级菜单
insert into sys_menu values('1', '系统管理', '0', '1', '#', 'M', '0', '', 'fa fa-gear', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统管理目录');
insert into sys_menu values('2', '系统监控', '0', '2', '#', 'M', '0', '', 'fa fa-video-camera', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统监控目录');
insert into sys_menu values('3', '系统工具', '0', '3', '#', 'M', '0', '', 'fa fa-bars', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统工具目录');
-- 二级菜单
insert into sys_menu values('100', '用户管理', '1', '1', '/system/user', 'C', '0', 'system:user:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '用户管理菜单');
insert into sys_menu values('101', '角色管理', '1', '2', '/system/role', 'C', '0', 'system:role:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '角色管理菜单');
insert into sys_menu values('102', '菜单管理', '1', '3', '/system/menu', 'C', '0', 'system:menu:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '菜单管理菜单');
insert into sys_menu values('103', '部门管理', '1', '4', '/system/dept', 'C', '0', 'system:dept:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '部门管理菜单');
insert into sys_menu values('104', '岗位管理', '1', '5', '/system/post', 'C', '0', 'system:post:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '岗位管理菜单');
insert into sys_menu values('105', '字典管理', '1', '6', '/system/dict', 'C', '0', 'system:dict:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '字典管理菜单');
insert into sys_menu values('106', '参数设置', '1', '7', '/system/config', 'C', '0', 'system:config:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '参数设置菜单');
insert into sys_menu values('107', '通知公告', '1', '8', '/system/notice', 'C', '0', 'system:notice:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知公告菜单');
insert into sys_menu values('108', '日志管理', '1', '9', '#', 'M', '0', '', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '日志管理菜单');
insert into sys_menu values('109', '在线用户', '2', '1', '/monitor/online', 'C', '0', 'monitor:online:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '在线用户菜单');
insert into sys_menu values('110', '定时任务', '2', '2', '/monitor/job', 'C', '0', 'monitor:job:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '定时任务菜单');
insert into sys_menu values('111', '数据监控', '2', '3', '/monitor/data', 'C', '0', 'monitor:data:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '数据监控菜单');
insert into sys_menu values('112', '表单构建', '3', '1', '/tool/build', 'C', '0', 'tool:build:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '表单构建菜单');
insert into sys_menu values('113', '代码生成', '3', '2', '/tool/gen', 'C', '0', 'tool:gen:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '代码生成菜单');
insert into sys_menu values('114', '系统接口', '3', '3', '/tool/swagger', 'C', '0', 'tool:swagger:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统接口菜单');
-- 三级菜单
insert into sys_menu values('500', '操作日志', '108', '1', '/monitor/operlog', 'C', '0', 'monitor:operlog:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '操作日志菜单');
insert into sys_menu values('501', '登录日志', '108', '2', '/monitor/logininfor', 'C', '0', 'monitor:logininfor:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '登录日志菜单');
-- 用户管理按钮
insert into sys_menu values('1000', '用户查询', '100', '1', '#', 'F', '0', 'system:user:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1001', '用户新增', '100', '2', '#', 'F', '0', 'system:user:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1002', '用户修改', '100', '3', '#', 'F', '0', 'system:user:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1003', '用户删除', '100', '4', '#', 'F', '0', 'system:user:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1004', '用户保存', '100', '5', '#', 'F', '0', 'system:user:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1005', '重置密码', '100', '6', '#', 'F', '0', 'system:user:resetPwd', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 角色管理按钮
insert into sys_menu values('1006', '角色查询', '101', '1', '#', 'F', '0', 'system:role:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1007', '角色新增', '101', '2', '#', 'F', '0', 'system:role:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1008', '角色修改', '101', '3', '#', 'F', '0', 'system:role:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1009', '角色删除', '101', '4', '#', 'F', '0', 'system:role:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1010', '角色保存', '101', '5', '#', 'F', '0', 'system:role:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 菜单管理按钮
insert into sys_menu values('1011', '菜单查询', '102', '1', '#', 'F', '0', 'system:menu:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1012', '菜单新增', '102', '2', '#', 'F', '0', 'system:menu:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1013', '菜单修改', '102', '3', '#', 'F', '0', 'system:menu:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1014', '菜单删除', '102', '4', '#', 'F', '0', 'system:menu:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1015', '菜单保存', '102', '5', '#', 'F', '0', 'system:menu:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 部门管理按钮
insert into sys_menu values('1016', '部门查询', '103', '1', '#', 'F', '0', 'system:dept:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1017', '部门新增', '103', '2', '#', 'F', '0', 'system:dept:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1018', '部门修改', '103', '3', '#', 'F', '0', 'system:dept:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1019', '部门删除', '103', '4', '#', 'F', '0', 'system:dept:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1020', '部门保存', '103', '5', '#', 'F', '0', 'system:dept:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 岗位管理按钮
insert into sys_menu values('1021', '岗位查询', '104', '1', '#', 'F', '0', 'system:post:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1022', '岗位新增', '104', '2', '#', 'F', '0', 'system:post:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1023', '岗位修改', '104', '3', '#', 'F', '0', 'system:post:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1024', '岗位删除', '104', '4', '#', 'F', '0', 'system:post:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1025', '岗位保存', '104', '5', '#', 'F', '0', 'system:post:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 字典管理按钮
insert into sys_menu values('1026', '字典查询', '105', '1', '#', 'F', '0', 'system:dict:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1027', '字典新增', '105', '2', '#', 'F', '0', 'system:dict:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1028', '字典修改', '105', '3', '#', 'F', '0', 'system:dict:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1029', '字典删除', '105', '4', '#', 'F', '0', 'system:dict:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1030', '字典保存', '105', '5', '#', 'F', '0', 'system:dict:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 参数设置按钮
insert into sys_menu values('1031', '参数查询', '106', '1', '#', 'F', '0', 'system:config:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1032', '参数新增', '106', '2', '#', 'F', '0', 'system:config:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1033', '参数修改', '106', '3', '#', 'F', '0', 'system:config:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1034', '参数删除', '106', '4', '#', 'F', '0', 'system:config:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1035', '参数保存', '106', '5', '#', 'F', '0', 'system:config:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 通知公告按钮
insert into sys_menu values('1036', '公告查询', '107', '1', '#', 'F', '0', 'system:notice:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1037', '公告新增', '107', '2', '#', 'F', '0', 'system:notice:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1038', '公告修改', '107', '3', '#', 'F', '0', 'system:notice:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1039', '公告删除', '107', '4', '#', 'F', '0', 'system:notice:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1040', '公告保存', '107', '5', '#', 'F', '0', 'system:notice:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 操作日志按钮
insert into sys_menu values('1041', '操作查询', '500', '1', '#', 'F', '0', 'monitor:operlog:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1042', '操作删除', '500', '2', '#', 'F', '0', 'monitor:operlog:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1043', '详细信息', '500', '3', '#', 'F', '0', 'monitor:operlog:detail', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 登录日志按钮
insert into sys_menu values('1044', '登录查询', '501', '1', '#', 'F', '0', 'monitor:logininfor:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1045', '登录删除', '501', '2', '#', 'F', '0', 'monitor:logininfor:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 在线用户按钮
insert into sys_menu values('1046', '在线查询', '109', '1', '#', 'F', '0', 'monitor:online:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1047', '批量强退', '109', '2', '#', 'F', '0', 'monitor:online:batchForceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1048', '单条强退', '109', '3', '#', 'F', '0', 'monitor:online:forceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 定时任务按钮
insert into sys_menu values('1049', '任务查询', '110', '1', '#', 'F', '0', 'monitor:job:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1050', '任务新增', '110', '2', '#', 'F', '0', 'monitor:job:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1051', '任务修改', '110', '3', '#', 'F', '0', 'monitor:job:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1052', '任务删除', '110', '4', '#', 'F', '0', 'monitor:job:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1053', '任务保存', '110', '5', '#', 'F', '0', 'monitor:job:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1054', '状态修改', '110', '6', '#', 'F', '0', 'monitor:job:changeStatus', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- 代码生成按钮
insert into sys_menu values('1055', '生成查询', '113', '1', '#', 'F', '0', 'tool:gen:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_menu values('1056', '生成代码', '113', '2', '#', 'F', '0', 'tool:gen:code', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- ----------------------------
-- 6、用户和角色关联表 用户N-1角色
-- ----------------------------
drop table if exists sys_user_role;
create table sys_user_role (
user_id int(11) not null comment '用户ID',
role_id int(11) not null comment '角色ID',
primary key(user_id, role_id)
) engine=innodb default charset=utf8 comment = '用户和角色关联表';
-- ----------------------------
-- 初始化-用户和角色关联表数据
-- ----------------------------
insert into sys_user_role values ('1', '1');
insert into sys_user_role values ('2', '2');
-- ----------------------------
-- 7、角色和菜单关联表 角色1-N菜单
-- ----------------------------
drop table if exists sys_role_menu;
create table sys_role_menu (
role_id int(11) not null comment '角色ID',
menu_id int(11) not null comment '菜单ID',
primary key(role_id, menu_id)
) engine=innodb default charset=utf8 comment = '角色和菜单关联表';
-- ----------------------------
-- 初始化-角色和菜单关联表数据
-- ----------------------------
insert into sys_role_menu values ('1', '1');
insert into sys_role_menu values ('1', '2');
insert into sys_role_menu values ('1', '3');
insert into sys_role_menu values ('1', '100');
insert into sys_role_menu values ('1', '101');
insert into sys_role_menu values ('1', '102');
insert into sys_role_menu values ('1', '103');
insert into sys_role_menu values ('1', '104');
insert into sys_role_menu values ('1', '105');
insert into sys_role_menu values ('1', '106');
insert into sys_role_menu values ('1', '107');
insert into sys_role_menu values ('1', '108');
insert into sys_role_menu values ('1', '109');
insert into sys_role_menu values ('1', '110');
insert into sys_role_menu values ('1', '111');
insert into sys_role_menu values ('1', '112');
insert into sys_role_menu values ('1', '113');
insert into sys_role_menu values ('1', '114');
insert into sys_role_menu values ('1', '500');
insert into sys_role_menu values ('1', '501');
insert into sys_role_menu values ('1', '1000');
insert into sys_role_menu values ('1', '1001');
insert into sys_role_menu values ('1', '1002');
insert into sys_role_menu values ('1', '1003');
insert into sys_role_menu values ('1', '1004');
insert into sys_role_menu values ('1', '1005');
insert into sys_role_menu values ('1', '1006');
insert into sys_role_menu values ('1', '1007');
insert into sys_role_menu values ('1', '1008');
insert into sys_role_menu values ('1', '1009');
insert into sys_role_menu values ('1', '1010');
insert into sys_role_menu values ('1', '1011');
insert into sys_role_menu values ('1', '1012');
insert into sys_role_menu values ('1', '1013');
insert into sys_role_menu values ('1', '1014');
insert into sys_role_menu values ('1', '1015');
insert into sys_role_menu values ('1', '1016');
insert into sys_role_menu values ('1', '1017');
insert into sys_role_menu values ('1', '1018');
insert into sys_role_menu values ('1', '1019');
insert into sys_role_menu values ('1', '1020');
insert into sys_role_menu values ('1', '1021');
insert into sys_role_menu values ('1', '1022');
insert into sys_role_menu values ('1', '1023');
insert into sys_role_menu values ('1', '1024');
insert into sys_role_menu values ('1', '1025');
insert into sys_role_menu values ('1', '1026');
insert into sys_role_menu values ('1', '1027');
insert into sys_role_menu values ('1', '1028');
insert into sys_role_menu values ('1', '1029');
insert into sys_role_menu values ('1', '1030');
insert into sys_role_menu values ('1', '1031');
insert into sys_role_menu values ('1', '1032');
insert into sys_role_menu values ('1', '1033');
insert into sys_role_menu values ('1', '1034');
insert into sys_role_menu values ('1', '1035');
insert into sys_role_menu values ('1', '1036');
insert into sys_role_menu values ('1', '1037');
insert into sys_role_menu values ('1', '1038');
insert into sys_role_menu values ('1', '1039');
insert into sys_role_menu values ('1', '1040');
insert into sys_role_menu values ('1', '1041');
insert into sys_role_menu values ('1', '1042');
insert into sys_role_menu values ('1', '1043');
insert into sys_role_menu values ('1', '1044');
insert into sys_role_menu values ('1', '1045');
insert into sys_role_menu values ('1', '1046');
insert into sys_role_menu values ('1', '1047');
insert into sys_role_menu values ('1', '1048');
insert into sys_role_menu values ('1', '1049');
insert into sys_role_menu values ('1', '1050');
insert into sys_role_menu values ('1', '1051');
insert into sys_role_menu values ('1', '1052');
insert into sys_role_menu values ('1', '1053');
insert into sys_role_menu values ('1', '1054');
insert into sys_role_menu values ('1', '1055');
insert into sys_role_menu values ('1', '1056');
-- ----------------------------
-- 8、用户与岗位关联表 用户1-N岗位
-- ----------------------------
drop table if exists sys_user_post;
create table sys_user_post
(
user_id varchar(64) not null comment '用户ID',
post_id varchar(64) not null comment '岗位ID',
primary key (user_id, post_id)
) engine=innodb default charset=utf8 comment = '用户与岗位关联表';
-- ----------------------------
-- 初始化-用户与岗位关联表数据
-- ----------------------------
insert into sys_user_post values ('1', '1');
insert into sys_user_post values ('2', '2');
-- ----------------------------
-- 9、操作日志记录
-- ----------------------------
drop table if exists sys_oper_log;
create table sys_oper_log (
oper_id int(11) not null auto_increment comment '日志主键',
title varchar(50) default '' comment '模块标题',
action varchar(100) default '' comment '功能请求',
method varchar(100) default '' comment '方法名称',
channel varchar(20) default '' comment '来源渠道manage后台用户 mobile手机端用户 other其它',
oper_name varchar(50) default '' comment '操作人员',
dept_name varchar(50) default '' comment '部门名称',
oper_url varchar(255) default '' comment '请求URL',
oper_ip varchar(30) default '' comment '主机地址',
oper_location varchar(255) default '' comment '操作地点',
oper_param varchar(255) default '' comment '请求参数',
status char(1) default '0' comment '操作状态0正常 1异常',
error_msg varchar(2000) default '' comment '错误消息',
oper_time datetime comment '操作时间',
primary key (oper_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '操作日志记录';
-- ----------------------------
-- 10、字典类型表
-- ----------------------------
drop table if exists sys_dict_type;
create table sys_dict_type
(
dict_id int(11) not null auto_increment comment '字典主键',
dict_name varchar(100) default '' comment '字典名称',
dict_type varchar(100) default '' comment '字典类型',
status char(1) default '0' comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (dict_id),
unique (dict_type)
) engine=innodb auto_increment=100 default charset=utf8 comment = '字典类型表';
insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '用户性别列表');
insert into sys_dict_type values(2, '菜单状态', 'sys_show_hide', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '菜单状态列表');
insert into sys_dict_type values(3, '系统开关', 'sys_normal_disable', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统开关列表');
insert into sys_dict_type values(4, '任务状态', 'sys_job_status', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '任务状态列表');
insert into sys_dict_type values(5, '系统是否', 'sys_yes_no', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统是否列表');
insert into sys_dict_type values(6, '通知类型', 'sys_notice_type', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知类型列表');
insert into sys_dict_type values(7, '通知状态', 'sys_notice_status', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知状态列表');
insert into sys_dict_type values(8, '操作类型', 'sys_oper_type', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '操作类型列表');
insert into sys_dict_type values(9, '系统状态', 'sys_common_status', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '登录状态列表');
-- ----------------------------
-- 11、字典数据表
-- ----------------------------
drop table if exists sys_dict_data;
create table sys_dict_data
(
dict_code int(11) not null auto_increment comment '字典编码',
dict_sort int(4) default 0 comment '字典排序',
dict_label varchar(100) default '' comment '字典标签',
dict_value varchar(100) default '' comment '字典键值',
dict_type varchar(100) default '' comment '字典类型',
css_class varchar(500) default '' comment '样式属性',
is_default char(1) default 'N' comment '是否默认Y是 N否',
status char(1) default '0' comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (dict_code)
) engine=innodb auto_increment=100 default charset=utf8 comment = '字典数据表';
insert into sys_dict_data values(1, 1, '', '0', 'sys_user_sex', '', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '性别男');
insert into sys_dict_data values(2, 2, '', '1', 'sys_user_sex', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '性别女');
insert into sys_dict_data values(3, 3, '未知', '2', 'sys_user_sex', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '性别未知');
insert into sys_dict_data values(4, 1, '显示', '0', 'sys_show_hide', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '显示菜单');
insert into sys_dict_data values(5, 2, '隐藏', '1', 'sys_show_hide', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '隐藏菜单');
insert into sys_dict_data values(6, 1, '正常', '0', 'sys_normal_disable', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态');
insert into sys_dict_data values(7, 2, '停用', '1', 'sys_normal_disable', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '停用状态');
insert into sys_dict_data values(8, 1, '正常', '0', 'sys_job_status', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态');
insert into sys_dict_data values(9, 2, '暂停', '1', 'sys_job_status', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '停用状态');
insert into sys_dict_data values(10, 1, '', 'Y', 'sys_yes_no', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统默认是');
insert into sys_dict_data values(11, 2, '', 'N', 'sys_yes_no', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统默认否');
insert into sys_dict_data values(12, 1, '通知', '1', 'sys_notice_type', '', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知');
insert into sys_dict_data values(13, 2, '公告', '2', 'sys_notice_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '公告');
insert into sys_dict_data values(14, 1, '正常', '0', 'sys_notice_status', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态');
insert into sys_dict_data values(15, 2, '关闭', '1', 'sys_notice_status', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '关闭状态');
insert into sys_dict_data values(16, 1, '新增', '1', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(17, 2, '修改', '2', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(18, 3, '保存', '3', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(19, 4, '删除', '4', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(20, 5, '授权', '5', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(21, 6, '导出', '6', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(22, 7, '导入', '7', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(23, 8, '强退', '8', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(24, 9, '禁止访问', '9', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(25, 10, '生成代码', '10', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作');
insert into sys_dict_data values(26, 1, '成功', '0', 'sys_common_status', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态');
insert into sys_dict_data values(27, 2, '失败', '1', 'sys_common_status', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '停用状态');
-- ----------------------------
-- 12、参数配置表
-- ----------------------------
drop table if exists sys_config;
create table sys_config (
config_id int(5) not null auto_increment comment '参数主键',
config_name varchar(100) default '' comment '参数名称',
config_key varchar(100) default '' comment '参数键名',
config_value varchar(100) default '' comment '参数键值',
config_type char(1) default 'N' comment '系统内置Y是 N否',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (config_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '参数配置表';
insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-default', 'Y', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '默认 skin-default、蓝色 skin-blue、黄色 skin-yellow' );
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '初始化密码 123456' );
-- ----------------------------
-- 13、系统访问记录
-- ----------------------------
drop table if exists sys_logininfor;
create table sys_logininfor (
info_id int(11) not null auto_increment comment '访问ID',
login_name varchar(50) default '' comment '登录账号',
ipaddr varchar(50) default '' comment '登录IP地址',
login_location varchar(255) default '' comment '登录地点',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
status char(1) default '0' comment '登录状态0成功 1失败',
msg varchar(255) default '' comment '提示消息',
login_time datetime comment '访问时间',
primary key (info_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '系统访问记录';
-- ----------------------------
-- 14、在线用户记录
-- ----------------------------
drop table if exists sys_user_online;
create table sys_user_online (
sessionId varchar(50) default '' comment '用户会话id',
login_name varchar(50) default '' comment '登录账号',
dept_name varchar(50) default '' comment '部门名称',
ipaddr varchar(50) default '' comment '登录IP地址',
login_location varchar(255) default '' comment '登录地点',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
status varchar(10) default '' comment '在线状态on_line在线off_line离线',
start_timestsamp datetime comment 'session创建时间',
last_access_time datetime comment 'session最后访问时间',
expire_time int(5) default 0 comment '超时时间,单位为分钟',
primary key (sessionId)
) engine=innodb default charset=utf8 comment = '在线用户记录';
-- ----------------------------
-- 15、定时任务调度表
-- ----------------------------
drop table if exists sys_job;
create table sys_job (
job_id int(11) not null auto_increment comment '任务ID',
job_name varchar(64) default '' comment '任务名称',
job_group varchar(64) default '' comment '任务组名',
method_name varchar(500) default '' comment '任务方法',
params varchar(200) default '' comment '方法参数',
cron_expression varchar(255) default '' comment 'cron执行表达式',
status char(1) default '0' comment '状态0正常 1暂停',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(500) default '' comment '备注信息',
primary key (job_id, job_name, job_group)
) engine=innodb auto_increment=100 default charset=utf8 comment = '定时任务调度表';
insert into sys_job values(1, 'ryTask', '系统默认(无参)', 'ryNoParams', '', '0/10 * * * * ?', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
insert into sys_job values(2, 'ryTask', '系统默认(有参)', 'ryParams', 'ry', '0/20 * * * * ?', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '');
-- ----------------------------
-- 16、定时任务调度日志表
-- ----------------------------
drop table if exists sys_job_log;
create table sys_job_log (
job_log_id int(11) not null auto_increment comment '任务日志ID',
job_name varchar(64) not null comment '任务名称',
job_group varchar(64) not null comment '任务组名',
method_name varchar(500) comment '任务方法',
params varchar(200) default '' comment '方法参数',
job_message varchar(500) comment '日志信息',
status char(1) default '0' comment '执行状态0正常 1失败',
exception_info text comment '异常信息',
create_time datetime comment '创建时间',
primary key (job_log_id)
) engine=innodb default charset=utf8 comment = '定时任务调度日志表';
-- ----------------------------
-- 17、通知公告表
-- ----------------------------
drop table if exists sys_notice;
create table sys_notice (
notice_id int(4) not null auto_increment comment '公告ID',
notice_title varchar(50) not null comment '公告标题',
notice_type char(2) not null comment '公告类型1通知 2公告',
notice_content varchar(500) not null comment '公告内容',
status char(1) default '0' comment '公告状态0正常 1关闭',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time datetime comment '更新时间',
remark varchar(255) default '' comment '备注',
primary key (notice_id)
) engine=innodb auto_increment=10 default charset=utf8 comment = '通知公告表';
-- ----------------------------
-- 初始化-公告信息表数据
-- ----------------------------
insert into sys_notice values('1', '温馨提醒2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
insert into sys_notice values('2', '维护通知2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');

View File

@ -0,0 +1,33 @@
package com.ruoyi;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
*
*
* @author ruoyi
*/
@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.ruoyi.project.*.*.mapper")
public class RuoYiApplication
{
public static void main(String[] args)
{
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@ -0,0 +1,19 @@
package com.ruoyi;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* web
*
* @author ruoyi
*/
public class RuoYiServletInitializer extends SpringBootServletInitializer
{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(RuoYiApplication.class);
}
}

View File

@ -0,0 +1,46 @@
package com.ruoyi.common.constant;
import java.util.HashMap;
import java.util.Map;
/**
* Map
*
* @author ruoyi
*/
public class CommonMap
{
/** 状态编码转换 */
public static Map<String, String> javaTypeMap = new HashMap<String, String>();
static
{
initJavaTypeMap();
}
/**
*
*/
public static void initJavaTypeMap()
{
javaTypeMap.put("tinyint", "Integer");
javaTypeMap.put("smallint", "Integer");
javaTypeMap.put("mediumint", "Integer");
javaTypeMap.put("int", "Integer");
javaTypeMap.put("integer", "integer");
javaTypeMap.put("bigint", "Long");
javaTypeMap.put("float", "Float");
javaTypeMap.put("double", "Double");
javaTypeMap.put("decimal", "BigDecimal");
javaTypeMap.put("bit", "Boolean");
javaTypeMap.put("char", "String");
javaTypeMap.put("varchar", "String");
javaTypeMap.put("tinytext", "String");
javaTypeMap.put("text", "String");
javaTypeMap.put("mediumtext", "String");
javaTypeMap.put("longtext", "String");
javaTypeMap.put("date", "Date");
javaTypeMap.put("datetime", "Date");
javaTypeMap.put("timestamp", "Date");
}
}

View File

@ -0,0 +1,65 @@
package com.ruoyi.common.constant;
/**
*
*
* @author ruoyi
*/
public class Constants
{
/**
* UTF-8
*/
public static final String UTF8 = "UTF-8";
/**
*
*/
public static final String SUCCESS = "0";
/**
*
*/
public static final String FAIL = "1";
/**
*
*/
public static final String LOGIN_SUCCESS = "Success";
/**
*
*/
public static final String LOGOUT = "Logout";
/**
*
*/
public static final String LOGIN_FAIL = "Error";
/**
*
*/
public static String AUTO_REOMVE_PRE = "true";
/**
*
*/
public static String PAGENUM = "pageNum";
/**
*
*/
public static String PAGESIZE = "pageSize";
/**
*
*/
public static String ORDERBYCOLUMN = "orderByColumn";
/**
* "desc" "asc".
*/
public static String ISASC = "isAsc";
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.common.constant;
/**
*
*
* @author ruoyi
*/
public interface ScheduleConstants
{
/**
* key
*/
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
public enum Status
{
/**
*
*/
NORMAL("0"),
/**
*
*/
PAUSE("1");
private String value;
private Status(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
}
}

View File

@ -0,0 +1,65 @@
package com.ruoyi.common.constant;
/**
* Shiro
*
* @author ruoyi
*/
public interface ShiroConstants
{
/**
*
*/
public static final String CURRENT_USER = "currentUser";
/**
*
*/
public static final String CURRENT_USERNAME = "username";
/**
* key
*/
public static String MESSAGE = "message";
/**
* key
*/
public static String ERROR = "errorMsg";
/**
*
*/
public static String ENCODING = "UTF-8";
/**
* 线
*/
public String ONLINE_SESSION = "online_session";
/**
* key
*/
public static final String CURRENT_CAPTCHA = "captcha";
/**
*
*/
public static final String CURRENT_EBABLED = "captchaEbabled";
/**
*
*/
public static final String CURRENT_TYPE = "captchaType";
/**
*
*/
public static final String CURRENT_VALIDATECODE = "validateCode";
/**
*
*/
public static final String CAPTCHA_ERROR = "captchaError";
}

View File

@ -0,0 +1,80 @@
package com.ruoyi.common.constant;
/**
*
*
* @author ruoyi
*/
public class UserConstants
{
/** 正常状态 */
public static final String NORMAL = "0";
/** 异常状态 */
public static final String EXCEPTION = "1";
/** 用户封禁状态 */
public static final String USER_BLOCKED = "1";
/** 角色封禁状态 */
public static final String ROLE_BLOCKED = "1";
/** 部门正常状态 */
public static final String DEPT_NORMAL = "0";
/**
*
*/
public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 20;
/** 登录名称是否唯一的返回结果码 */
public final static String USER_NAME_UNIQUE = "0";
public final static String USER_NAME_NOT_UNIQUE = "1";
/** 手机号码是否唯一的返回结果 */
public final static String USER_PHONE_UNIQUE = "0";
public final static String USER_PHONE_NOT_UNIQUE = "1";
/** e-mail 是否唯一的返回结果 */
public final static String USER_EMAIL_UNIQUE = "0";
public final static String USER_EMAIL_NOT_UNIQUE = "1";
/** 部门名称是否唯一的返回结果码 */
public final static String DEPT_NAME_UNIQUE = "0";
public final static String DEPT_NAME_NOT_UNIQUE = "1";
/** 角色名称是否唯一的返回结果码 */
public final static String ROLE_NAME_UNIQUE = "0";
public final static String ROLE_NAME_NOT_UNIQUE = "1";
/** 菜单名称是否唯一的返回结果码 */
public final static String MENU_NAME_UNIQUE = "0";
public final static String MENU_NAME_NOT_UNIQUE = "1";
/** 字典类型是否唯一的返回结果码 */
public final static String DICT_TYPE_UNIQUE = "0";
public final static String DICT_TYPE_NOT_UNIQUE = "1";
/** 参数键名是否唯一的返回结果码 */
public final static String CONFIG_KEY_UNIQUE = "0";
public final static String CONFIG_KEY_NOT_UNIQUE = "1";
/**
*
*/
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
/**
*
*/
public static final String MOBILE_PHONE_NUMBER_PATTERN = "^0{0,1}(13[0-9]|15[0-9]|14[0-9]|18[0-9])[0-9]{8}$";
/**
*
*/
public static final String EMAIL_PATTERN = "^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?";
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.common.exception;
/**
*
*
* @author ruoyi
*/
public class DemoModeException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public DemoModeException()
{
}
}

View File

@ -0,0 +1,105 @@
package com.ruoyi.common.exception.base;
import org.springframework.util.StringUtils;
import com.ruoyi.common.utils.MessageUtils;
/**
*
*
* @author ruoyi
*/
public class BaseException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
*
*/
private String module;
/**
*
*/
private String code;
/**
*
*/
private Object[] args;
/**
*
*/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage)
{
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args)
{
this(module, code, args, null);
}
public BaseException(String module, String defaultMessage)
{
this(module, null, null, defaultMessage);
}
public BaseException(String code, Object[] args)
{
this(null, code, args, null);
}
public BaseException(String defaultMessage)
{
this(null, null, null, defaultMessage);
}
@Override
public String getMessage()
{
String message = null;
if (!StringUtils.isEmpty(code))
{
message = MessageUtils.message(code, args);
}
if (message == null)
{
message = defaultMessage;
}
return message;
}
public String getModule()
{
return module;
}
public String getCode()
{
return code;
}
public Object[] getArgs()
{
return args;
}
public String getDefaultMessage()
{
return defaultMessage;
}
@Override
public String toString()
{
return this.getClass() + "{" + "module='" + module + '\'' + ", message='" + getMessage() + '\'' + '}';
}
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.common.exception.file;
import org.apache.commons.fileupload.FileUploadException;
/**
*
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileUploadException
{
private static final long serialVersionUID = 1L;
private int length;
private int maxLength;
private String filename;
public FileNameLengthLimitExceededException(String filename, int length, int maxLength)
{
super("file name : [" + filename + "], length : [" + length + "], max length : [" + maxLength + "]");
this.length = length;
this.maxLength = maxLength;
this.filename = filename;
}
public String getFilename()
{
return filename;
}
public int getLength()
{
return length;
}
public int getMaxLength()
{
return maxLength;
}
}

View File

@ -0,0 +1,74 @@
package com.ruoyi.common.exception.file;
import java.util.Arrays;
import org.apache.commons.fileupload.FileUploadException;
/**
*
*
* @author ruoyi
*/
public class InvalidExtensionException extends FileUploadException
{
private static final long serialVersionUID = 1L;
private String[] allowedExtension;
private String extension;
private String filename;
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : ["
+ Arrays.toString(allowedExtension) + "]");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;
}
public String[] getAllowedExtension()
{
return allowedExtension;
}
public String getExtension()
{
return extension;
}
public String getFilename()
{
return filename;
}
public static class InvalidImageExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidFlashExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidMediaExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class CaptchaException extends UserException
{
private static final long serialVersionUID = 1L;
public CaptchaException()
{
super("user.jcaptcha.error", null);
}
}

View File

@ -0,0 +1,18 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class RoleBlockedException extends UserException
{
private static final long serialVersionUID = 1L;
public RoleBlockedException(String reason)
{
super("role.blocked", new Object[] { reason });
}
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class UserBlockedException extends UserException
{
private static final long serialVersionUID = 1L;
public UserBlockedException(String reason)
{
super("user.blocked", new Object[] { reason });
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.common.exception.user;
import com.ruoyi.common.exception.base.BaseException;
/**
*
*
* @author ruoyi
*/
public class UserException extends BaseException
{
private static final long serialVersionUID = 1L;
public UserException(String code, Object[] args)
{
super("user", code, args, null);
}
}

View File

@ -0,0 +1,17 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class UserNotExistsException extends UserException
{
private static final long serialVersionUID = 1L;
public UserNotExistsException()
{
super("user.not.exists", null);
}
}

View File

@ -0,0 +1,17 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class UserPasswordNotMatchException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordNotMatchException()
{
super("user.password.not.match", null);
}
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class UserPasswordRetryLimitCountException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordRetryLimitCountException(int retryLimitCount, String password)
{
super("user.password.retry.limit.count", new Object[] { retryLimitCount, password });
}
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
*
*
* @author ruoyi
*/
public class UserPasswordRetryLimitExceedException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordRetryLimitExceedException(int retryLimitCount)
{
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount });
}
}

View File

@ -0,0 +1,88 @@
package com.ruoyi.common.support;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.ruoyi.common.utils.StringUtils;
/**
*
*
* @author ruoyi
*
*/
public class CharsetKit
{
/** ISO-8859-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** UTF-8 */
public static final String UTF_8 = "UTF-8";
/** GBK */
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* Charset
*
* @param charset
* @return Charset
*/
public static Charset charset(String charset)
{
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
*
*
* @param source
* @param srcCharset ISO-8859-1
* @param destCharset UTF-8
* @return
*/
public static String convert(String source, String srcCharset, String destCharset)
{
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
*
*
* @param source
* @param srcCharset ISO-8859-1
* @param destCharset UTF-8
* @return
*/
public static String convert(String source, Charset srcCharset, Charset destCharset)
{
if (null == srcCharset)
{
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset)
{
srcCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
{
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return
*/
public static String systemCharset()
{
return Charset.defaultCharset().name();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
package com.ruoyi.common.support;
import com.ruoyi.common.utils.StringUtils;
/**
*
*
* @author ruoyi
*/
public class StrFormatter
{
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* <br>
* {} <br>
* {} 使 \\ { {} \ 使 \\\\ <br>
* <br>
* 使format("this is {} for {}", "a", "b") -> this is a for b<br>
* {} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* \ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern
* @param argArray
* @return
*/
public static String format(final String strPattern, final Object... argArray)
{
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
{
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
{
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1)
{
if (handledPosition == 0)
{
return strPattern;
}
else
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
}
else
{
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
{
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
{
// 转义符之前还有一个转义符,占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
else
{
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
}
else
{
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// append the characters following the last {} pair.
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}

View File

@ -0,0 +1,96 @@
package com.ruoyi.common.utils;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*
* @author ruoyi
*/
public class AddressUtils
{
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
public static final String IP_URL = "http://ip.taobao.com/service/getIpInfo.php";
/**
*
*
* @param urlStr
* @param content
* @param encoding
* @return
*/
private static String sendPost(String content, String encoding)
{
URL url = null;
HttpURLConnection connection = null;
try
{
url = new URL(IP_URL);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(2000);
connection.setReadTimeout(2000);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.connect();
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(content);
out.flush();
out.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null)
{
buffer.append(line);
}
reader.close();
return buffer.toString();
}
catch (IOException e)
{
log.error("温馨提醒:您的主机已经断网,请您检查主机的网络连接");
log.error("根据IP获取所在位置----------错误消息:" + e.getMessage());
}
finally
{
if (connection != null)
{
connection.disconnect();
}
}
return null;
}
public static String getRealAddressByIP(String ip)
{
String address = "";
try
{
address = sendPost("ip=" + ip, Constants.UTF8);
JSONObject json = JSONObject.parseObject(address);
JSONObject object = json.getObject("data", JSONObject.class);
String region = object.getString("region");
String city = object.getString("city");
address = region + " " + city;
}
catch (Exception e)
{
log.error("根据IP获取所在位置----------错误消息:" + e.getMessage());
}
return address;
}
}

View File

@ -0,0 +1,100 @@
package com.ruoyi.common.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
*
*
* @author ruoyi
*/
public class DateUtils
{
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* Date
*
* @return Date()
*/
public static Date getNowDate()
{
return new Date();
}
/**
* , yyyy-MM-dd
*
* @return String
*/
public static String getDate()
{
return dateTimeNow(YYYY_MM_DD);
}
public static final String getTime()
{
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static final String dateTimeNow()
{
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static final String dateTimeNow(final String format)
{
return parseDateToStr(format, new Date());
}
public static final String dateTime(final Date date)
{
return parseDateToStr(YYYY_MM_DD, date);
}
public static final String parseDateToStr(final String format, final Date date)
{
return new SimpleDateFormat(format).format(date);
}
public static final Date dateTime(final String format, final String ts)
{
try
{
return new SimpleDateFormat(format).parse(ts);
}
catch (ParseException e)
{
throw new RuntimeException(e);
}
}
/**
* // 2018/08/08
*/
public static final String datePath()
{
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
/**
* // 20180808
*/
public static final String dateTime()
{
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
}

View File

@ -0,0 +1,155 @@
package com.ruoyi.common.utils;
import java.io.File;
import java.io.IOException;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.framework.config.RuoYiConfig;
/**
*
*
* @author ruoyi
*/
public class FileUploadUtils
{
// 默认大小 50M
public static final long DEFAULT_MAX_SIZE = 52428800;
// 默认上传的地址
private static String defaultBaseDir = RuoYiConfig.getProfile();
// 默认的文件名最大长度
public static final int DEFAULT_FILE_NAME_LENGTH = 200;
// 默认文件类型jpg
public static final String IMAGE_JPG_EXTENSION = ".jpg";
private static int counter = 0;
public static void setDefaultBaseDir(String defaultBaseDir)
{
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir()
{
return defaultBaseDir;
}
/**
*
*
* @param file
* @return
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException
{
try
{
return upload(getDefaultBaseDir(), file, FileUploadUtils.IMAGE_JPG_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e);
}
}
/**
*
*
* @param baseDir
* @param file
* @return
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, FileUploadUtils.IMAGE_JPG_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e);
}
}
/**
*
*
* @param baseDir
* @param file
* @param needDatePathAndRandomName
* @param extension
* @return
* @throws FileSizeLimitExceededException
* @throws FileNameLengthLimitExceededException
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file, String extension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException
{
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(file.getOriginalFilename(), fileNamelength,
FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file);
String fileName = encodingFilename(file.getOriginalFilename(), extension);
File desc = getAbsoluteFile(baseDir, baseDir + fileName);
file.transferTo(desc);
return fileName;
}
private static final File getAbsoluteFile(String uploadDir, String filename) throws IOException
{
File desc = new File(File.separator + filename);
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
if (!desc.exists())
{
desc.createNewFile();
}
return desc;
}
/**
*
*/
private static final String encodingFilename(String filename, String extension)
{
filename = filename.replace("_", " ");
filename = new Md5Hash(filename + System.nanoTime() + counter++).toHex().toString() + extension;
return filename;
}
/**
*
*
* @param file
* @return
* @throws FileSizeLimitExceededException
*/
public static final void assertAllowed(MultipartFile file) throws FileSizeLimitExceededException
{
long size = file.getSize();
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException("not allowed upload upload", size, DEFAULT_MAX_SIZE);
}
}
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.common.utils;
import javax.servlet.http.HttpServletRequest;
/**
* IP
*
* @author ruoyi
*/
public class IpUtils
{
public static String getIpAddr(HttpServletRequest request)
{
if (request == null)
{
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
}

View File

@ -0,0 +1,136 @@
package com.ruoyi.common.utils;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
/**
*
*
* @author ruoyi
*/
public class LogUtils
{
public static final Logger ERROR_LOG = LoggerFactory.getLogger("sys-error");
public static final Logger ACCESS_LOG = LoggerFactory.getLogger("sys-access");
/**
* 访 [username][jsessionid][ip][accept][UserAgent][url][params][Referer]
*
* @param request
*/
public static void logAccess(HttpServletRequest request)
{
String username = getUsername();
String jsessionId = request.getRequestedSessionId();
String ip = IpUtils.getIpAddr(request);
String accept = request.getHeader("accept");
String userAgent = request.getHeader("User-Agent");
String url = request.getRequestURI();
String params = getParams(request);
StringBuilder s = new StringBuilder();
s.append(getBlock(username));
s.append(getBlock(jsessionId));
s.append(getBlock(ip));
s.append(getBlock(accept));
s.append(getBlock(userAgent));
s.append(getBlock(url));
s.append(getBlock(params));
s.append(getBlock(request.getHeader("Referer")));
getAccessLog().info(s.toString());
}
/**
* [exception]
*
* @param message
* @param e
*/
public static void logError(String message, Throwable e)
{
String username = getUsername();
StringBuilder s = new StringBuilder();
s.append(getBlock("exception"));
s.append(getBlock(username));
s.append(getBlock(message));
ERROR_LOG.error(s.toString(), e);
}
/**
* [page/eception][username][statusCode][errorMessage][servletName][uri][exceptionName][ip][exception]
*
* @param request
*/
public static void logPageError(HttpServletRequest request)
{
String username = getUsername();
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
String message = (String) request.getAttribute("javax.servlet.error.message");
String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception");
if (statusCode == null)
{
statusCode = 0;
}
StringBuilder s = new StringBuilder();
s.append(getBlock(t == null ? "page" : "exception"));
s.append(getBlock(username));
s.append(getBlock(statusCode));
s.append(getBlock(message));
s.append(getBlock(IpUtils.getIpAddr(request)));
s.append(getBlock(uri));
s.append(getBlock(request.getHeader("Referer")));
StringWriter sw = new StringWriter();
while (t != null)
{
t.printStackTrace(new PrintWriter(sw));
t = t.getCause();
}
s.append(getBlock(sw.toString()));
getErrorLog().error(s.toString());
}
public static String getBlock(Object msg)
{
if (msg == null)
{
msg = "";
}
return "[" + msg.toString() + "]";
}
protected static String getParams(HttpServletRequest request)
{
Map<String, String[]> params = request.getParameterMap();
return JSON.toJSONString(params);
}
protected static String getUsername()
{
return (String) SecurityUtils.getSubject().getPrincipal();
}
public static Logger getAccessLog()
{
return ACCESS_LOG;
}
public static Logger getErrorLog()
{
return ERROR_LOG;
}
}

View File

@ -0,0 +1,51 @@
package com.ruoyi.common.utils;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
/**
* Map
*
* @author ruoyi
*/
public class MapDataUtil
{
public static Map<String, Object> convertDataMap(HttpServletRequest request)
{
Map<String, String[]> properties = request.getParameterMap();
Map<String, Object> returnMap = new HashMap<String, Object>();
Iterator<?> entries = properties.entrySet().iterator();
Map.Entry<?, ?> entry;
String name = "";
String value = "";
while (entries.hasNext())
{
entry = (Entry<?, ?>) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if (null == valueObj)
{
value = "";
}
else if (valueObj instanceof String[])
{
String[] values = (String[]) valueObj;
for (int i = 0; i < values.length; i++)
{
value = values[i] + ",";
}
value = value.substring(0, value.length() - 1);
}
else
{
value = valueObj.toString();
}
returnMap.put(name, value);
}
return returnMap;
}
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.common.utils;
import org.springframework.context.MessageSource;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
* i18n
*
* @author ruoyi
*/
public class MessageUtils
{
/**
* spring messageSource
*
* @param code
* @param args
* @return
*/
public static String message(String code, Object... args)
{
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, null);
}
}

View File

@ -0,0 +1,137 @@
package com.ruoyi.common.utils;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.ruoyi.common.support.Convert;
/**
*
*
* @author ruoyi
*/
public class ServletUtils
{
/**
* String
*/
public static String getParameter(String name)
{
return getRequest().getParameter(name);
}
/**
* String
*/
public static String getParameter(String name, String defaultValue)
{
return Convert.toStr(getRequest().getParameter(name), defaultValue);
}
/**
* Integer
*/
public static Integer getParameterToInt(String name)
{
return Convert.toInt(getRequest().getParameter(name));
}
/**
* Integer
*/
public static Integer getParameterToInt(String name, Integer defaultValue)
{
return Convert.toInt(getRequest().getParameter(name), defaultValue);
}
/**
* request
*/
public static HttpServletRequest getRequest()
{
return getRequestAttributes().getRequest();
}
/**
* response
*/
public static HttpServletResponse getResponse()
{
return getRequestAttributes().getResponse();
}
/**
* session
*/
public static HttpSession getSession()
{
return getRequest().getSession();
}
public static ServletRequestAttributes getRequestAttributes()
{
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
/**
*
*
* @param response
* @param string
* @return null
*/
public static String renderString(HttpServletResponse response, String string)
{
try
{
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().print(string);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
/**
* Ajax
*
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request)
{
String accept = request.getHeader("accept");
if (accept != null && accept.indexOf("application/json") != -1)
{
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
{
return true;
}
String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
{
return true;
}
String ajax = request.getParameter("__ajax");
if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
{
return true;
}
return false;
}
}

View File

@ -0,0 +1,373 @@
package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang.text.StrBuilder;
import com.ruoyi.common.support.StrFormatter;
/**
*
*
* @author ruoyi
*/
public class StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
/** 下划线 */
private static final char SEPARATOR = '_';
/**
*
*
* @param value defaultValue value
* @return value
*/
public static <T> T nvl(T value, T defaultValue)
{
return value != null ? value : defaultValue;
}
/**
* * Collection ListSetQueue
*
* @param coll Collection
* @return true false
*/
public static boolean isEmpty(Collection<?> coll)
{
return isNull(coll) || coll.isEmpty();
}
/**
* * CollectionListSetQueue
*
* @param coll Collection
* @return true false
*/
public static boolean isNotEmpty(Collection<?> coll)
{
return !isEmpty(coll);
}
/**
* *
*
* @param objects
** @return true false
*/
public static boolean isEmpty(Object[] objects)
{
return isNull(objects) || (objects.length == 0);
}
/**
* *
*
* @param objects
* @return true false
*/
public static boolean isNotEmpty(Object[] objects)
{
return !isEmpty(objects);
}
/**
* * Map
*
* @param map Map
* @return true false
*/
public static boolean isEmpty(Map<?, ?> map)
{
return isNull(map) || map.isEmpty();
}
/**
* * Map
*
* @param map Map
* @return true false
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
return !isEmpty(map);
}
/**
* *
*
* @param str String
* @return true false
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* *
*
* @param str String
* @return true false
*/
public static boolean isNotEmpty(String str)
{
return !isEmpty(str);
}
/**
* *
*
* @param object Object
* @return true false
*/
public static boolean isNull(Object object)
{
return object == null;
}
/**
* *
*
* @param object Object
* @return true false
*/
public static boolean isNotNull(Object object)
{
return !isNull(object);
}
/**
* * Java
*
* @param object
* @return true false
*/
public static boolean isArray(Object object)
{
return isNotNull(object) && object.getClass().isArray();
}
/**
*
*/
public static String trim(String str)
{
return (str == null ? "" : str.trim());
}
/**
*
*
* @param str
* @param start
* @return
*/
public static String substring(final String str, int start)
{
if (str == null)
{
return NULLSTR;
}
if (start < 0)
{
start = str.length() + start;
}
if (start < 0)
{
start = 0;
}
if (start > str.length())
{
return NULLSTR;
}
return str.substring(start);
}
/**
*
*
* @param str
* @param start
* @param end
* @return
*/
public static String substring(final String str, int start, int end)
{
if (str == null)
{
return NULLSTR;
}
if (end < 0)
{
end = str.length() + end;
}
if (start < 0)
{
start = str.length() + start;
}
if (end > str.length())
{
end = str.length();
}
if (start > end)
{
return NULLSTR;
}
if (start < 0)
{
start = 0;
}
if (end < 0)
{
end = 0;
}
return str.substring(start, end);
}
/**
* , {} <br>
* {} <br>
* {} 使 \\ { {} \ 使 \\\\ <br>
* <br>
* 使format("this is {} for {}", "a", "b") -> this is a for b<br>
* {} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* \ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template {}
* @param params
* @return
*/
public static String format(String template, Object... params)
{
if (isEmpty(params) || isEmpty(template))
{
return template;
}
return StrFormatter.format(template, params);
}
/**
*
*/
public static String uncapitalize(String str)
{
int strLen;
if (str == null || (strLen = str.length()) == 0)
{
return str;
}
return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString();
}
/**
* 线
*/
public static String toUnderScoreCase(String s)
{
if (s == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
boolean nextUpperCase = true;
if (i < (s.length() - 1))
{
nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
}
if ((i > 0) && Character.isUpperCase(c))
{
if (!upperCase || !nextUpperCase)
{
sb.append(SEPARATOR);
}
upperCase = true;
}
else
{
upperCase = false;
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
*
*
* @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)))
{
return true;
}
}
}
return false;
}
/**
* 线线 HELLO_WORLD->HelloWorld
*
* @param name 线
* @return
*/
public static String convertToCamelCase(String name)
{
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty())
{
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
}

View File

@ -0,0 +1,71 @@
package com.ruoyi.common.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
import com.ruoyi.project.monitor.logininfor.service.LogininforServiceImpl;
import eu.bitwalker.useragentutils.UserAgent;
/**
*
*
* @author ruoyi
*/
public class SystemLogUtils
{
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
/**
* [ip][][][]
* <p/>
* loginError loginSuccess passwordError changePassword changeStatus
*
* @param username
* @param op
* @param msg
* @param args
*/
public static void log(String username, String status, String msg, Object... args)
{
StringBuilder s = new StringBuilder();
s.append(LogUtils.getBlock(ShiroUtils.getIp()));
s.append(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
s.append(LogUtils.getBlock(username));
s.append(LogUtils.getBlock(status));
s.append(LogUtils.getBlock(msg));
sys_user_logger.info(s.toString(), args);
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
{
saveOpLog(username, msg, Constants.SUCCESS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
saveOpLog(username, msg, Constants.FAIL);
}
}
public static void saveOpLog(String username, String message, String status)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
LogininforServiceImpl logininforService = SpringUtils.getBean(LogininforServiceImpl.class);
Logininfor logininfor = new Logininfor();
logininfor.setLoginName(username);
logininfor.setStatus(status);
logininfor.setIpaddr(ShiroUtils.getIp());
logininfor.setLoginLocation(AddressUtils.getRealAddressByIP(ShiroUtils.getIp()));
logininfor.setBrowser(browser);
logininfor.setOs(os);
logininfor.setMsg(message);
logininforService.insertLogininfor(logininfor);
}
}

View File

@ -0,0 +1,145 @@
package com.ruoyi.common.utils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.ruoyi.project.system.menu.domain.Menu;
/**
*
*
* @author ruoyi
*/
public class TreeUtils
{
/**
* ID
*
* @param list
* @param typeId ID
* @return String
*/
public static List<Menu> getChildPerms(List<Menu> list, int parentId)
{
List<Menu> returnList = new ArrayList<Menu>();
for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
{
Menu t = (Menu) iterator.next();
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (t.getParentId() == parentId)
{
recursionFn(list, t);
returnList.add(t);
}
}
return returnList;
}
/**
*
*
* @param list
* @param Menu
*/
private static void recursionFn(List<Menu> list, Menu t)
{
// 得到子节点列表
List<Menu> childList = getChildList(list, t);
t.setChildren(childList);
for (Menu tChild : childList)
{
if (hasChild(list, tChild))
{
// 判断是否有子节点
Iterator<Menu> it = childList.iterator();
while (it.hasNext())
{
Menu n = (Menu) it.next();
recursionFn(list, n);
}
}
}
}
/**
*
*/
private static List<Menu> getChildList(List<Menu> list, Menu t)
{
List<Menu> tlist = new ArrayList<Menu>();
Iterator<Menu> it = list.iterator();
while (it.hasNext())
{
Menu n = (Menu) it.next();
if (n.getParentId().longValue() == t.getMenuId().longValue())
{
tlist.add(n);
}
}
return tlist;
}
List<Menu> returnList = new ArrayList<Menu>();
/**
* ID
*
* @param list
* @param typeId ID
* @param prefix
*/
public List<Menu> getChildPerms(List<Menu> list, int typeId, String prefix)
{
if (list == null)
{
return null;
}
for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
{
Menu node = (Menu) iterator.next();
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (node.getParentId() == typeId)
{
recursionFn(list, node, prefix);
}
// 二、遍历所有的父节点下的所有子节点
/*
* if (node.getParentId()==0) { recursionFn(list, node); }
*/
}
return returnList;
}
private void recursionFn(List<Menu> list, Menu node, String p)
{
// 得到子节点列表
List<Menu> childList = getChildList(list, node);
if (hasChild(list, node))
{
// 判断是否有子节点
returnList.add(node);
Iterator<Menu> it = childList.iterator();
while (it.hasNext())
{
Menu n = (Menu) it.next();
n.setMenuName(p + n.getMenuName());
recursionFn(list, n, p + p);
}
}
else
{
returnList.add(node);
}
}
/**
*
*/
private static boolean hasChild(List<Menu> list, Menu t)
{
return getChildList(list, t).size() > 0 ? true : false;
}
}

View File

@ -0,0 +1,409 @@
package com.ruoyi.common.utils.poi;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
import com.ruoyi.framework.web.domain.AjaxResult;
/**
* Excel
*
* @author ruoyi
*/
public class ExcelUtil<T>
{
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class);
public Class<T> clazz;
public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
}
public List<T> importExcel(String sheetName, InputStream input) throws Exception
{
List<T> list = new ArrayList<T>();
Workbook workbook = WorkbookFactory.create(input);
Sheet sheet = workbook.getSheet(sheetName);
if (!sheetName.trim().equals(""))
{
sheet = workbook.getSheet(sheetName); // 如果指定sheet名,则取指定sheet中的内容.
}
if (sheet == null)
{
sheet = workbook.getSheetAt(0); // 如果传入的sheet名不存在则默认指向第1个sheet.
}
int rows = sheet.getPhysicalNumberOfRows();
if (rows > 0)
{
// 有数据时才处理
Field[] allFields = clazz.getDeclaredFields(); // 得到类的所有field.
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>(); // 定义一个map用于存放列的序号和field.
for (Field field : allFields)
{
// 将有注解的field存放到map中.
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
int col = getExcelCol(attr.column());// 获得列号
field.setAccessible(true);// 设置类的私有字段属性可访问.
fieldsMap.put(col, field);
}
}
for (int i = 1; i < rows; i++)
{
// 从第2行开始取数据,默认第一行是表头.
Row row = sheet.getRow(i);
int cellNum = sheet.getRow(0).getPhysicalNumberOfCells();
T entity = null;
for (int j = 0; j < cellNum; j++)
{
Cell cell = row.getCell(j);
if (cell == null)
{
continue;
}
else
{
// 先设置Cell的类型然后就可以把纯数字作为String类型读进来了 by zhuyangyong 20171228
row.getCell(j).setCellType(Cell.CELL_TYPE_STRING);
cell = row.getCell(j);
}
String c = cell.getStringCellValue();
if (c.equals(""))
{
continue;
}
entity = (entity == null ? clazz.newInstance() : entity);// 如果不存在实例则新建.
Field field = fieldsMap.get(j);// 从map中得到对应列的field.
// 取得类型,并根据对象类型设置值.
Class<?> fieldType = field.getType();
if (String.class == fieldType)
{
field.set(entity, String.valueOf(c));
}
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))
{
field.set(entity, Integer.parseInt(c));
}
else if ((Long.TYPE == fieldType) || (Long.class == fieldType))
{
field.set(entity, Long.valueOf(c));
}
else if ((Float.TYPE == fieldType) || (Float.class == fieldType))
{
field.set(entity, Float.valueOf(c));
}
else if ((Short.TYPE == fieldType) || (Short.class == fieldType))
{
field.set(entity, Short.valueOf(c));
}
else if ((Double.TYPE == fieldType) || (Double.class == fieldType))
{
field.set(entity, Double.valueOf(c));
}
else if (Character.TYPE == fieldType)
{
if ((c != null) && (c.length() > 0))
{
field.set(entity, Character.valueOf(c.charAt(0)));
}
}
else if (java.util.Date.class == fieldType)
{
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cell.setCellValue(sdf.format(cell.getNumericCellValue()));
c = sdf.format(cell.getNumericCellValue());
}
else
{
c = cell.getStringCellValue();
}
}
else if (java.math.BigDecimal.class == fieldType)
{
c = cell.getStringCellValue();
}
}
if (entity != null)
{
list.add(entity);
}
}
}
return list;
}
/**
* listexcel
*
* @param sheetName
*/
public AjaxResult exportExcel(List<T> list, String sheetName)
{
Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段
List<Field> fields = new ArrayList<Field>();
// 得到所有field并存放到一个list中.
for (Field field : allFields)
{
if (field.isAnnotationPresent(Excel.class))
{
fields.add(field);
}
}
HSSFWorkbook workbook = new HSSFWorkbook();// 产生工作薄对象
// excel2003中每个sheet中最多有65536行
int sheetSize = 65536;
double sheetNo = Math.ceil(list.size() / sheetSize);// 取出一共有多少个sheet.
for (int index = 0; index <= sheetNo; index++)
{
HSSFSheet sheet = workbook.createSheet();// 产生工作表对象
if (sheetNo == 0)
{
workbook.setSheetName(index, sheetName);
}
else
{
workbook.setSheetName(index, sheetName + index);// 设置工作表的名称.
}
HSSFRow row;
HSSFCell cell; // 产生单元格
row = sheet.createRow(0); // 产生一行
// 写入各个字段的列头名称
for (int i = 0; i < fields.size(); i++)
{
Field field = fields.get(i);
Excel attr = field.getAnnotation(Excel.class);
int col = getExcelCol(attr.column()); // 获得列号
cell = row.createCell(col); // 创建列
cell.setCellType(HSSFCell.CELL_TYPE_STRING); // 设置列中写入内容为String类型
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
if (attr.name().indexOf("注:") >= 0)
{
HSSFFont font = workbook.createFont();
font.setColor(HSSFFont.COLOR_RED);
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
sheet.setColumnWidth(i, 6000);
}
else
{
HSSFFont font = workbook.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 粗体显示
cellStyle.setFont(font); // 选择需要用到的字体格式
cellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
// 设置列宽
sheet.setColumnWidth(i, 3766);
}
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cellStyle.setWrapText(true);
cell.setCellStyle(cellStyle);
cell.setCellValue(attr.name());// 写入列名
// 如果设置了提示信息则鼠标放上去提示.
if (!attr.prompt().trim().equals(""))
{
setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, col, col); // 这里默认设了2-101列提示.
}
// 如果设置了combo属性则本列只能选择不能输入
if (attr.combo().length > 0)
{
setHSSFValidation(sheet, attr.combo(), 1, 100, col, col); // 这里默认设了2-101列只能选择不能输入.
}
}
int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size());
// 写入各条记录,每条记录对应excel表中的一行
HSSFCellStyle cs = workbook.createCellStyle();
cs.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
for (int i = startNo; i < endNo; i++)
{
row = sheet.createRow(i + 1 - startNo);
T vo = (T) list.get(i); // 得到导出对象.
for (int j = 0; j < fields.size(); j++)
{
Field field = fields.get(j); // 获得field.
field.setAccessible(true); // 设置实体类私有属性可访问
Excel attr = field.getAnnotation(Excel.class);
try
{
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
if (attr.isExport())
{
cell = row.createCell(getExcelCol(attr.column()));// 创建cell
cell.setCellStyle(cs);
try
{
if (String.valueOf(field.get(vo)).length() > 10)
throw new Exception("长度超过10位就不用转数字了");
// 如果可以转成数字则导出为数字类型
BigDecimal bc = new BigDecimal(String.valueOf(field.get(vo)));
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
cell.setCellValue(bc.doubleValue());
}
catch (Exception e)
{
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
if (vo == null)
{
cell.setCellValue(""); // 如果数据存在就填入,不存在填入空格.
}
else
{
cell.setCellValue(field.get(vo) == null ? "" : String.valueOf(field.get(vo)));// 如果数据存在就填入,不存在填入空格.
}
}
}
}
catch (Exception e)
{
log.error("导出Excel失败{}", e);
}
}
}
}
try
{
String filename = encodingFilename(sheetName);
OutputStream out = new FileOutputStream(getfile() + filename);
workbook.write(out);
out.close();
return AjaxResult.success(filename);
}
catch (Exception e)
{
log.error("关闭flush失败{}", e);
return AjaxResult.error("导出Excel失败请联系网站管理员");
}
}
/**
* EXCELA,B,C,D,E0,1,2,3
*
* @param col
*/
public static int getExcelCol(String col)
{
col = col.toUpperCase();
// 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。
int count = -1;
char[] cs = col.toCharArray();
for (int i = 0; i < cs.length; i++)
{
count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);
}
return count;
}
/**
*
*
* @param sheet sheet.
* @param promptTitle
* @param promptContent
* @param firstRow
* @param endRow
* @param firstCol
* @param endCol
* @return sheet.
*/
public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle, String promptContent, int firstRow,
int endRow, int firstCol, int endCol)
{
// 构造constraint对象
DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1");
// 四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
HSSFDataValidation data_validation_view = new HSSFDataValidation(regions, constraint);
data_validation_view.createPromptBox(promptTitle, promptContent);
sheet.addValidationData(data_validation_view);
return sheet;
}
/**
* ,.
*
* @param sheet sheet.
* @param textlist
* @param firstRow
* @param endRow
* @param firstCol
* @param endCol
* @return sheet.
*/
public static HSSFSheet setHSSFValidation(HSSFSheet sheet, String[] textlist, int firstRow, int endRow,
int firstCol, int endCol)
{
// 加载下拉列表内容
DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象
HSSFDataValidation data_validation_list = new HSSFDataValidation(regions, constraint);
sheet.addValidationData(data_validation_list);
return sheet;
}
/**
*
*/
public String encodingFilename(String filename)
{
filename = UUID.randomUUID().toString() + "_" + filename + ".xls";
return filename;
}
public String getfile() throws FileNotFoundException
{
return ResourceUtils.getURL("classpath:").getPath() + "static/file/";
}
}

View File

@ -0,0 +1,76 @@
package com.ruoyi.common.utils.security;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.project.system.user.domain.User;
/**
* shiro
*
* @author ruoyi
*/
public class ShiroUtils
{
public static Subject getSubjct()
{
return SecurityUtils.getSubject();
}
public static Session getSession()
{
return SecurityUtils.getSubject().getSession();
}
public static void logout()
{
getSubjct().logout();
}
public static User getUser()
{
return (User) getSubjct().getPrincipal();
}
public static void setUser(User user)
{
Subject subject = getSubjct();
PrincipalCollection principalCollection = subject.getPrincipals();
String realmName = principalCollection.getRealmNames().iterator().next();
PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
// 重新加载Principal
subject.runAs(newPrincipalCollection);
}
public static void clearCachedAuthorizationInfo()
{
RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
UserRealm realm = (UserRealm) rsm.getRealms().iterator().next();
realm.clearCachedAuthorizationInfo();
}
public static Long getUserId()
{
return getUser().getUserId().longValue();
}
public static String getLoginName()
{
return getUser().getLoginName();
}
public static String getIp()
{
return getSubjct().getSession().getHost();
}
public static String getSessionId()
{
return String.valueOf(getSubjct().getSession().getId());
}
}

View File

@ -0,0 +1,102 @@
package com.ruoyi.common.utils.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* spring 便springbean
*
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory;
}
/**
*
*
* @param name
* @return Object bean
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name);
}
/**
* requiredType
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* BeanFactorybeantrue
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name)
{
return beanFactory.containsBean(name);
}
/**
* beansingletonprototype beanNoSuchBeanDefinitionException
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name);
}
/**
* beanbean
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name);
}
}

View File

@ -0,0 +1,86 @@
package com.ruoyi.common.xss;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* XSS
*
* @author ruoyi
*/
@WebFilter(filterName = "xssFilter", urlPatterns = "/system/*")
public class XssFilter implements Filter
{
/**
*
*/
public List<String> excludes = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String temp = filterConfig.getInitParameter("excludes");
if (temp != null)
{
String[] url = temp.split(",");
for (int i = 0; url != null && i < url.length; i++)
{
excludes.add(url[i]);
}
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp))
{
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
if (excludes == null || excludes.isEmpty())
{
return false;
}
String url = request.getServletPath();
for (String pattern : excludes)
{
Pattern p = Pattern.compile("^" + pattern);
Matcher m = p.matcher(url);
if (m.find())
{
return true;
}
}
return false;
}
@Override
public void destroy()
{
}
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.common.xss;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
/**
* XSS
*
* @author ruoyi
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
@Override
public String[] getParameterValues(String name)
{
String[] values = super.getParameterValues(name);
if (values != null)
{
int length = values.length;
String[] escapseValues = new String[length];
for (int i = 0; i < length; i++)
{
// 防xss攻击和过滤前后空格
escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim();
}
return escapseValues;
}
return super.getParameterValues(name);
}
}

View File

@ -0,0 +1,178 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Map;
import com.ruoyi.common.utils.AddressUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.constant.BusinessStatus;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
import com.ruoyi.project.monitor.operlog.service.IOperLogService;
import com.ruoyi.project.system.user.domain.User;
/**
*
*
* @author ruoyi
*/
@Aspect
@Component
@EnableAsync
public class LogAspect
{
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
@Autowired
private IOperLogService operLogService;
// 配置织入点
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)")
public void logPointCut()
{
}
/**
*
*
* @param joinPoint
*/
@AfterReturning(pointcut = "logPointCut()")
public void doBefore(JoinPoint joinPoint)
{
handleLog(joinPoint, null);
}
/**
*
*
* @param joinPoint
* @param e
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfter(JoinPoint joinPoint, Exception e)
{
handleLog(joinPoint, e);
}
@Async
protected void handleLog(final JoinPoint joinPoint, final Exception e)
{
try
{
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// 获取当前的用户
User currentUser = ShiroUtils.getUser();
// *========数据库日志=========*//
OperLog operLog = new OperLog();
operLog.setStatus(BusinessStatus.SUCCESS);
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOperIp(ip);
// 操作地点
operLog.setOperLocation(AddressUtils.getRealAddressByIP(ip));
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if (currentUser != null)
{
operLog.setOperName(currentUser.getLoginName());
operLog.setDeptName(currentUser.getDept().getDeptName());
}
if (e != null)
{
operLog.setStatus(BusinessStatus.FAIL);
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 处理设置注解上的参数
getControllerMethodDescription(controllerLog, operLog);
// 保存数据库
operLogService.insertOperlog(operLog);
}
catch (Exception exp)
{
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
/**
* Controller
*
* @param joinPoint
* @return
* @throws Exception
*/
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception
{
// 设置action动作
operLog.setAction(log.action());
// 设置标题
operLog.setTitle(log.title());
// 设置channel
operLog.setChannel(log.channel());
// 是否需要保存request参数和值
if (log.isSaveRequestData())
{
// 获取参数的信息,传入到数据库中。
setRequestValue(operLog);
}
}
/**
* log
*
* @param operLog
* @param request
*/
private void setRequestValue(OperLog operLog)
{
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
String params = JSONObject.toJSONString(map);
operLog.setOperParam(StringUtils.substring(params, 0, 255));
}
/**
*
*/
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(Log.class);
}
return null;
}
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.framework.aspectj.lang.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author ruoyi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
/**
* Excel.
*/
public abstract String name();
/**
*
*/
public abstract String column();
/**
*
*/
public abstract String prompt() default "";
/**
* .
*/
public abstract String[] combo() default {};
/**
* ,:,.
*/
public abstract boolean isExport() default true;
}

View File

@ -0,0 +1,33 @@
package com.ruoyi.framework.aspectj.lang.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.ruoyi.framework.aspectj.lang.constant.OperatorType;
/**
*
*
* @author ruoyi
*
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/** 模块 */
String title() default "";
/** 功能 */
String action() default "";
/** 渠道 */
String channel() default OperatorType.MANAGE;
/** 是否保存请求的参数 */
boolean isSaveRequestData() default true;
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.framework.aspectj.lang.constant;
/**
*
*
* @author ruoyi
*
*/
public class BusinessStatus
{
/** 其它 */
public static final String OTHER = "-1";
/** 成功 */
public static final String SUCCESS = "0";
/** 失败 */
public static final String FAIL = "1";
}

View File

@ -0,0 +1,33 @@
package com.ruoyi.framework.aspectj.lang.constant;
/**
*
*
* @author ruoyi
*
*/
public class BusinessType
{
/** 其它 */
public static final String OTHER = "0";
/** 新增 */
public static final String INSERT = "1";
/** 修改 */
public static final String UPDATE = "2";
/** 保存 */
public static final String SAVE = "3";
/** 删除 */
public static final String DELETE = "4";
/** 授权 */
public static final String GRANT = "5";
/** 导出 */
public static final String EXPORT = "6";
/** 导入 */
public static final String IMPORT = "7";
/** 强退 */
public static final String FORCE = "8";
/** 禁止访问 */
public static final String FORBID = "9";
/** 生成代码 */
public static final String GENCODE = "10";
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.framework.aspectj.lang.constant;
/**
*
*
* @author ruoyi
*
*/
public class OperatorType
{
/** 其它 */
public static final String OTHER = "0";
/** 后台用户 */
public static final String MANAGE = "1";
/** 渠道用户 */
public static final String CHANNEL = "2";
/** 手机端用户 */
public static final String MOBILE = "3";
}

View File

@ -0,0 +1,61 @@
package com.ruoyi.framework.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
/**
*
*
* @author ruoyi
*/
@Configuration
public class CaptchaConfig
{
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.image.width", "160");
properties.setProperty("kaptcha.image.height", "60");
properties.setProperty("kaptcha.textproducer.font.size", "28");
properties.setProperty("kaptcha.session.key", "kaptchaCode");
properties.setProperty("kaptcha.textproducer.char.spac", "35");
properties.setProperty("kaptcha.textproducer.char.length", "5");
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
properties.setProperty("kaptcha.noise.color", "white");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.image.width", "160");
properties.setProperty("kaptcha.image.height", "60");
properties.setProperty("kaptcha.textproducer.font.size", "38");
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath");
properties.setProperty("kaptcha.textproducer.impl", "com.ruoyi.framework.config.KaptchaTextCreator");
properties.setProperty("kaptcha.textproducer.char.spac", "5");
properties.setProperty("kaptcha.textproducer.char.length", "6");
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
properties.setProperty("kaptcha.noise.color", "white");
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

View File

@ -0,0 +1,161 @@
package com.ruoyi.framework.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
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.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
/**
* Druid
*
* @author ruoyi
*/
@Configuration
public class DruidConfig
{
private static final Logger log = LoggerFactory.getLogger(DruidConfig.class);
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean(initMethod = "init", destroyMethod = "close") /** 声明其为Bean实例 */
@Primary /** 在同样的DataSource中首先使用被标注的DataSource */
public DataSource dataSource()
{
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
/** configuration */
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try
{
datasource.setFilters(filters);
}
catch (SQLException e)
{
log.error("druid configuration initialization filter", e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
/**
* StatViewServlet web.xmlservlet
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public ServletRegistrationBean druidServlet()
{
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/monitor/druid/*");
/** 白名单 */
// reg.addInitParameter("allow", "10.211.61.45,127.0.0.1,123.207.20.136");
/** IP黑名单(共同存在时deny优先于allow) */
// reg.addInitParameter("deny", "10.211.61.4");
/** 是否能够重置数据 禁用HTML页面上的“Reset All”功能 */
reg.addInitParameter("resetEnable", "false");
return reg;
}
/**
* filterRegistrationBean web.xmlFilter
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean filterRegistrationBean()
{
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
/** 添加过滤规则. */
filterRegistrationBean.addUrlPatterns("/*");
/** 监控选项滤器 */
filterRegistrationBean.addInitParameter("DruidWebStatFilter", "/*");
/** 添加不需要忽略的格式信息. */
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/monitor/druid/*");
/** 配置profileEnable能够监控单个url调用的sql列表 */
filterRegistrationBean.addInitParameter("profileEnable", "true");
/** 当前的cookie的用户 */
filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
/** 当前的session的用户 */
filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
return filterRegistrationBean;
}
}

View File

@ -0,0 +1,34 @@
package com.ruoyi.framework.config;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.collect.Maps;
import com.ruoyi.common.xss.XssFilter;
/**
* Filter
*
* @author ruoyi
*/
@Configuration
public class FilterConfig
{
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean xssFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(Integer.MAX_VALUE);
Map<String, String> initParameters = Maps.newHashMap();
initParameters.put("excludes", "/system/notice/*");
registration.setInitParameters(initParameters);
return registration;
}
}

View File

@ -0,0 +1,71 @@
package com.ruoyi.framework.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
*
*
* @author ruoyi
*/
@Component
@ConfigurationProperties(prefix = "gen")
public class GenConfig
{
/** 作者 */
public static String author;
/** 生成包路径 */
public static String packageName;
/** 自动去除表前缀默认是true */
public static String autoRemovePre;
/** 表前缀(类名不会包含表前缀) */
public static String tablePrefix;
public static String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
GenConfig.author = author;
}
public static String getPackageName()
{
return packageName;
}
public void setPackageName(String packageName)
{
GenConfig.packageName = packageName;
}
public static String getAutoRemovePre()
{
return autoRemovePre;
}
public void setAutoRemovePre(String autoRemovePre)
{
GenConfig.autoRemovePre = autoRemovePre;
}
public static String getTablePrefix()
{
return tablePrefix;
}
public void setTablePrefix(String tablePrefix)
{
GenConfig.tablePrefix = tablePrefix;
}
@Override
public String toString()
{
return "GenConfig [getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString()
+ "]";
}
}

View File

@ -0,0 +1,44 @@
package com.ruoyi.framework.config;
import java.util.Locale;
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;
/**
*
*
* @author ruoyi
*/
@Configuration
public class I18nConfig implements WebMvcConfigurer
{
@Bean
public LocaleResolver localeResolver()
{
SessionLocaleResolver slr = new SessionLocaleResolver();
// 默认语言
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor()
{
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
// 参数名
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(localeChangeInterceptor());
}
}

View File

@ -0,0 +1,77 @@
package com.ruoyi.framework.config;
import java.util.Random;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
/**
*
*
* @author ruoyi
*/
public class KaptchaTextCreator extends DefaultTextCreator
{
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override
public String getText()
{
Integer result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0)
{
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
{
if (x >= y)
{
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
}
else
{
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}

View File

@ -0,0 +1,42 @@
package com.ruoyi.framework.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
*
* @author ruoyi
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
/**
*
*/
@Value("${shiro.user.indexUrl}")
private String indexUrl;
/**
*
*/
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
registry.addViewController("/").setViewName("forward:" + indexUrl);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 头像上传路径 */
registry.addResourceHandler("/profile/**").addResourceLocations("file:" + RuoYiConfig.getProfile());
/** swagger配置 */
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.framework.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
*
*
* @author ruoyi
*/
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig
{
/** 项目名称 */
private String name;
/** 版本 */
private String version;
/** 版权年份 */
private String copyrightYear;
/** 上传路径 */
private static String profile;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getCopyrightYear()
{
return copyrightYear;
}
public void setCopyrightYear(String copyrightYear)
{
this.copyrightYear = copyrightYear;
}
public static String getProfile()
{
return profile;
}
public void setProfile(String profile)
{
RuoYiConfig.profile = profile;
}
}

View File

@ -0,0 +1,56 @@
package com.ruoyi.framework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
/**
*
*
* @author ruoyi
*
*/
@Configuration
public class ScheduleConfig
{
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
{
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
// quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 线程池配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
// JobStore配置
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
// 集群配置
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
factory.setQuartzProperties(prop);
factory.setSchedulerName("RuoyiScheduler");
// 延时启动
factory.setStartupDelay(1);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 可选QuartzScheduler
// 启动时更新己存在的Job这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
// 设置自动启动默认为true
factory.setAutoStartup(true);
return factory;
}
}

View File

@ -0,0 +1,360 @@
package com.ruoyi.framework.config;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter;
import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter;
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
/**
*
*
* @author ruoyi
*/
@Configuration
public class ShiroConfig
{
public static final String PREMISSION_STRING = "perms[\"{0}\"]";
// Session超时时间单位为毫秒默认30分钟
@Value("${shiro.session.expireTime}")
private int expireTime;
// 相隔多久检查一次session的有效性单位毫秒默认就是10分钟
@Value("${shiro.session.validationInterval}")
private int validationInterval;
// 验证码开关
@Value("${shiro.user.captchaEbabled}")
private boolean captchaEbabled;
// 验证码类型
@Value("${shiro.user.captchaType}")
private String captchaType;
// 设置Cookie的域名
@Value("${shiro.cookie.domain}")
private String domain;
// 设置cookie的有效访问路径
@Value("${shiro.cookie.path}")
private String path;
// 设置HttpOnly属性
@Value("${shiro.cookie.httpOnly}")
private boolean httpOnly;
// 设置Cookie的过期时间秒为单位
@Value("${shiro.cookie.maxAge}")
private int maxAge;
// 登录地址
@Value("${shiro.user.loginUrl}")
private String loginUrl;
// 权限认证失败地址
@Value("${shiro.user.unauthorizedUrl}")
private String unauthorizedUrl;
/**
* 使Ehcache
*/
@Bean
public EhCacheManager getEhCacheManager()
{
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml");
return em;
}
/**
* Realm
*/
@Bean
public UserRealm userRealm(EhCacheManager cacheManager)
{
UserRealm userRealm = new UserRealm();
userRealm.setCacheManager(cacheManager);
return userRealm;
}
/**
* sessionDAO
*/
@Bean
public OnlineSessionDAO sessionDAO()
{
OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
return sessionDAO;
}
/**
* sessionFactory
*/
@Bean
public OnlineSessionFactory sessionFactory()
{
OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
return sessionFactory;
}
/**
* sessionFactory
*/
@Bean
public SpringSessionValidationScheduler sessionValidationScheduler()
{
SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler();
// 相隔多久检查一次session的有效性单位毫秒默认就是10分钟
sessionValidationScheduler.setSessionValidationInterval(validationInterval * 60 * 1000);
// 设置会话验证调度器进行会话验证时的会话管理器
sessionValidationScheduler.setSessionManager(sessionValidationManager());
return sessionValidationScheduler;
}
/**
*
*/
@Bean
public OnlineWebSessionManager sessionValidationManager()
{
OnlineWebSessionManager manager = new OnlineWebSessionManager();
// 加入缓存管理器
manager.setCacheManager(getEhCacheManager());
// 删除过期的session
manager.setDeleteInvalidSessions(true);
// 设置全局session超时时间
manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
// 去掉 JSESSIONID
manager.setSessionIdUrlRewritingEnabled(false);
// 是否定时检查session
manager.setSessionValidationSchedulerEnabled(true);
// 自定义SessionDao
manager.setSessionDAO(sessionDAO());
// 自定义sessionFactory
manager.setSessionFactory(sessionFactory());
return manager;
}
/**
*
*/
@Bean
public OnlineWebSessionManager sessionManager()
{
OnlineWebSessionManager manager = new OnlineWebSessionManager();
// 加入缓存管理器
manager.setCacheManager(getEhCacheManager());
// 删除过期的session
manager.setDeleteInvalidSessions(true);
// 设置全局session超时时间
manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
// 去掉 JSESSIONID
manager.setSessionIdUrlRewritingEnabled(false);
// 定义要使用的无效的Session定时调度器
manager.setSessionValidationScheduler(sessionValidationScheduler());
// 是否定时检查session
manager.setSessionValidationSchedulerEnabled(true);
// 自定义SessionDao
manager.setSessionDAO(sessionDAO());
// 自定义sessionFactory
manager.setSessionFactory(sessionFactory());
return manager;
}
/**
*
*/
@Bean
public SecurityManager securityManager(UserRealm userRealm)
{
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(userRealm);
// 记住我
securityManager.setRememberMeManager(rememberMeManager());
// 注入缓存管理器;
securityManager.setCacheManager(getEhCacheManager());
// session管理器
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* 退
*/
public LogoutFilter logoutFilter()
{
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setLoginUrl(loginUrl);
return logoutFilter;
}
/**
* Shiro
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// Shiro的核心安全接口,这个属性是必须的
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 身份认证失败,则跳转到登录页面的配置
shiroFilterFactoryBean.setLoginUrl(loginUrl);
// 权限认证失败,则跳转到指定页面
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
// Shiro连接约束配置即过滤链的定义
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 对静态资源设置匿名访问
filterChainDefinitionMap.put("/favicon.ico**", "anon");
filterChainDefinitionMap.put("/ruoyi.png**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/ajax/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/ruoyi/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
// 退出 logout地址shiro去清除session
filterChainDefinitionMap.put("/logout", "logout");
// 不需要拦截的访问
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
// 系统权限列表
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("onlineSession", onlineSessionFilter());
filters.put("syncOnlineSession", syncOnlineSessionFilter());
filters.put("captchaValidate", captchaValidateFilter());
// 注销成功,则跳转到指定页面
filters.put("logout", logoutFilter());
shiroFilterFactoryBean.setFilters(filters);
// 所有请求需要认证
filterChainDefinitionMap.put("/**", "user");
// 系统请求记录当前会话
filterChainDefinitionMap.put("/main", "onlineSession,syncOnlineSession");
filterChainDefinitionMap.put("/system/**", "onlineSession,syncOnlineSession");
filterChainDefinitionMap.put("/monitor/**", "onlineSession,syncOnlineSession");
filterChainDefinitionMap.put("/tool/**", "onlineSession,syncOnlineSession");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 线
*/
@Bean
public OnlineSessionFilter onlineSessionFilter()
{
OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
onlineSessionFilter.setLoginUrl(loginUrl);
return onlineSessionFilter;
}
/**
* 线
*/
@Bean
public SyncOnlineSessionFilter syncOnlineSessionFilter()
{
SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
return syncOnlineSessionFilter;
}
/**
*
*/
@Bean
public CaptchaValidateFilter captchaValidateFilter()
{
CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
captchaValidateFilter.setCaptchaEbabled(captchaEbabled);
captchaValidateFilter.setCaptchaType(captchaType);
return captchaValidateFilter;
}
/**
* cookie
*/
public SimpleCookie rememberMeCookie()
{
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setDomain(domain);
cookie.setPath(path);
cookie.setHttpOnly(httpOnly);
cookie.setMaxAge(maxAge * 24 * 60 * 60);
return cookie;
}
/**
*
*/
public CookieRememberMeManager rememberMeManager()
{
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
cookieRememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ=="));
return cookieRememberMeManager;
}
/**
* Shiro
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator()
{
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}
/**
* thymeleafshiro
*/
@Bean
public ShiroDialect shiroDialect()
{
return new ShiroDialect();
}
/**
* Shiro
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
@Qualifier("securityManager") SecurityManager securityManager)
{
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}

View File

@ -0,0 +1,58 @@
package com.ruoyi.framework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2
*
* @author ruoyi
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig
{
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoYiConfig;
/**
* API
*/
@Bean
public Docket createRestApi()
{
return new Docket(DocumentationType.SWAGGER_2)
// 详细定制
.apiInfo(apiInfo())
.select()
// 指定当前包路径
.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
/**
*
*/
private ApiInfo apiInfo()
{
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
.title("标题若依管理系统_接口文档")
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
.contact(new Contact(ruoYiConfig.getName(), null, null))
.version("版本号:" + ruoYiConfig.getVersion())
.build();
}
}

View File

@ -0,0 +1,126 @@
package com.ruoyi.framework.shiro.realm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.RoleBlockedException;
import com.ruoyi.common.exception.user.UserBlockedException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.shiro.service.LoginService;
import com.ruoyi.project.system.menu.service.IMenuService;
import com.ruoyi.project.system.role.service.IRoleService;
import com.ruoyi.project.system.user.domain.User;
/**
* Realm
*
* @author ruoyi
*/
public class UserRealm extends AuthorizingRealm
{
private static final Logger log = LoggerFactory.getLogger(UserRealm.class);
@Autowired
private IMenuService menuService;
@Autowired
private IRoleService roleService;
@Autowired
private LoginService loginService;
/**
*
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
{
Long userId = ShiroUtils.getUserId();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 角色加入AuthorizationInfo认证对象
info.setRoles(roleService.selectRoleKeys(userId));
// 权限加入AuthorizationInfo认证对象
info.setStringPermissions(menuService.selectPermsByUserId(userId));
return info;
}
/**
*
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
String password = "";
if (upToken.getPassword() != null)
{
password = new String(upToken.getPassword());
}
User user = null;
try
{
user = loginService.login(username, password);
}
catch (CaptchaException e)
{
throw new AuthenticationException(e.getMessage(), e);
}
catch (UserNotExistsException e)
{
throw new UnknownAccountException(e.getMessage(), e);
}
catch (UserPasswordNotMatchException e)
{
throw new IncorrectCredentialsException(e.getMessage(), e);
}
catch (UserPasswordRetryLimitExceedException e)
{
throw new ExcessiveAttemptsException(e.getMessage(), e);
}
catch (UserBlockedException e)
{
throw new LockedAccountException(e.getMessage(), e);
}
catch (RoleBlockedException e)
{
throw new LockedAccountException(e.getMessage(), e);
}
catch (Exception e)
{
log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
throw new AuthenticationException(e.getMessage(), e);
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
}
/**
*
*/
public void clearCachedAuthorizationInfo()
{
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
}
}

View File

@ -0,0 +1,128 @@
package com.ruoyi.framework.shiro.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.UserBlockedException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.SystemLogUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.domain.UserStatus;
import com.ruoyi.project.system.user.service.IUserService;
/**
*
*
* @author ruoyi
*/
@Component
public class LoginService
{
@Autowired
private PasswordService passwordService;
@Autowired
private IUserService userService;
/**
*
*/
public User login(String username, String password)
{
// 验证码校验
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
throw new CaptchaException();
}
// 用户名或密码为空 错误
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"));
throw new UserNotExistsException();
}
// 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
throw new UserPasswordNotMatchException();
}
// 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
throw new UserPasswordNotMatchException();
}
// 查询用户信息
User user = userService.selectUserByLoginName(username);
if (user == null && maybeMobilePhoneNumber(username))
{
user = userService.selectUserByPhoneNumber(username);
}
if (user == null && maybeEmail(username))
{
user = userService.selectUserByEmail(username);
}
if (user == null || UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists"));
throw new UserNotExistsException();
}
passwordService.validate(user, password);
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark()));
throw new UserBlockedException(user.getRemark());
}
SystemLogUtils.log(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
recordLoginInfo(user);
return user;
}
private boolean maybeEmail(String username)
{
if (!username.matches(UserConstants.EMAIL_PATTERN))
{
return false;
}
return true;
}
private boolean maybeMobilePhoneNumber(String username)
{
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
{
return false;
}
return true;
}
/**
*
*/
public void recordLoginInfo(User user)
{
user.setLoginIp(ShiroUtils.getIp());
user.setLoginDate(DateUtils.getNowDate());
userService.updateUser(user);
}
}

View File

@ -0,0 +1,101 @@
package com.ruoyi.framework.shiro.service;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PostConstruct;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SystemLogUtils;
import com.ruoyi.project.system.user.domain.User;
/**
*
*
* @author ruoyi
*/
@Component
public class PasswordService
{
@Autowired
private CacheManager cacheManager;
private Cache<String, AtomicInteger> loginRecordCache;
@Value(value = "${user.password.maxRetryCount}")
private String maxRetryCount;
@PostConstruct
public void init()
{
loginRecordCache = cacheManager.getCache("loginRecordCache");
}
public void validate(User user, String password)
{
String loginName = user.getLoginName();
AtomicInteger retryCount = loginRecordCache.get(loginName);
if (retryCount == null)
{
retryCount = new AtomicInteger(0);
loginRecordCache.put(loginName, retryCount);
}
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
{
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount));
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
}
if (!matches(user, password))
{
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount, password));
loginRecordCache.put(loginName, retryCount);
throw new UserPasswordNotMatchException();
}
else
{
clearLoginRecordCache(loginName);
}
}
public boolean matches(User user, String newPassword)
{
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
}
public void clearLoginRecordCache(String username)
{
loginRecordCache.remove(username);
}
public String encryptPassword(String username, String password, String salt)
{
return new Md5Hash(username + password + salt).toHex().toString();
}
public static void main(String[] args)
{
//System.out.println(new PasswordService().encryptPassword("admin", "admin123", "111111"));
//System.out.println(new PasswordService().encryptPassword("ry", "admin123", "222222"));
System.out.println(new PasswordService().encryptPassword("ly", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("ce", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("zs", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("ls", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("ww", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("zl", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("sq", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("zb", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("wj", "admin123", "123456"));
System.out.println(new PasswordService().encryptPassword("ys", "admin123", "123456"));
}
}

View File

@ -0,0 +1,31 @@
package com.ruoyi.framework.shiro.service;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Component;
/**
* RuoYi js thymeleaf
*
* @author ruoyi
*/
@Component
public class PermissionService
{
public String hasPermi(String permission)
{
return isPermittedOperator(permission) ? "" : "hidden";
}
private boolean isPermittedOperator(String permission)
{
if (SecurityUtils.getSubject().isPermitted(permission))
{
return true;
}
else
{
return false;
}
}
}

View File

@ -0,0 +1,115 @@
package com.ruoyi.framework.shiro.session;
import java.io.Serializable;
import java.util.Date;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
import com.ruoyi.project.monitor.online.domain.UserOnline;
import com.ruoyi.project.monitor.online.service.IUserOnlineService;
/**
* ShiroSessiondb
*
* @author ruoyi
*/
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
{
/**
* session 1
*/
@Value("${shiro.session.dbSyncPeriod}")
private int dbSyncPeriod;
/**
*
*/
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
@Autowired
private IUserOnlineService onlineService;
@Autowired
private OnlineSessionFactory onlineSessionFactory;
public OnlineSessionDAO()
{
super();
}
public OnlineSessionDAO(long expireTime)
{
super();
}
/**
* ID
*
* @param sessionId ID
* @return ShiroSession
*/
@Override
protected Session doReadSession(Serializable sessionId)
{
UserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
if (userOnline == null)
{
return null;
}
return onlineSessionFactory.createSession(userOnline);
}
/**
* 访///
*/
public void syncToDb(OnlineSession onlineSession)
{
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
if (lastSyncTimestamp != null)
{
boolean needSync = true;
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
if (deltaTime < dbSyncPeriod * 60 * 1000)
{
// 时间差不足 无需同步
needSync = false;
}
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
// session 数据变更了 同步
if (isGuest == false && onlineSession.isAttributeChanged())
{
needSync = true;
}
if (needSync == false)
{
return;
}
}
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
// 更新完后 重置标识
if (onlineSession.isAttributeChanged())
{
onlineSession.resetAttributeChanged();
}
onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession));
}
/**
* /退
*/
@Override
protected void doDelete(Session session)
{
OnlineSession onlineSession = (OnlineSession) session;
if (null == onlineSession)
{
return;
}
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
}
}

View File

@ -0,0 +1,56 @@
package com.ruoyi.framework.shiro.session;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SessionContext;
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.web.session.mgt.WebSessionContext;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.IpUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
import com.ruoyi.project.monitor.online.domain.UserOnline;
import eu.bitwalker.useragentutils.UserAgent;
/**
* sessionFactory
*
* @author ruoyi
*/
@Component
public class OnlineSessionFactory implements SessionFactory
{
public Session createSession(UserOnline userOnline)
{
OnlineSession onlineSession = userOnline.getSession();
if (StringUtils.isNotNull(onlineSession) && onlineSession.getId() == null)
{
onlineSession.setId(userOnline.getSessionId());
}
return userOnline.getSession();
}
@Override
public Session createSession(SessionContext initData)
{
OnlineSession session = new OnlineSession();
if (initData != null && initData instanceof WebSessionContext)
{
WebSessionContext sessionContext = (WebSessionContext) initData;
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
if (request != null)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
session.setHost(IpUtils.getIpAddr(request));
session.setBrowser(browser);
session.setOs(os);
}
}
return session;
}
}

View File

@ -0,0 +1,86 @@
package com.ruoyi.framework.shiro.web.filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SystemLogUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.system.user.domain.User;
/**
* 退
*
* @author ruoyi
*/
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
{
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
/**
* 退
*/
private String loginUrl;
public String getLoginUrl()
{
return loginUrl;
}
public void setLoginUrl(String loginUrl)
{
this.loginUrl = loginUrl;
}
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
{
try
{
Subject subject = getSubject(request, response);
String redirectUrl = getRedirectUrl(request, response, subject);
try
{
User user = (User) ShiroUtils.getSubjct().getPrincipal();
if (StringUtils.isNotNull(user))
{
String loginName = user.getLoginName();
// 记录用户退出日志
SystemLogUtils.log(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success"));
}
// 退出登录
subject.logout();
}
catch (SessionException ise)
{
log.error("logout fail.", ise);
}
issueRedirect(request, response, redirectUrl);
}
catch (Exception e)
{
log.debug("Encountered session exception during logout. This can generally safely be ignored.", e);
}
return false;
}
/**
* 退URL
*/
@Override
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
{
String url = getLoginUrl();
if (StringUtils.isNotEmpty(url))
{
return url;
}
return super.getRedirectUrl(request, response, subject);
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.framework.shiro.web.filter.captcha;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.web.filter.AccessControlFilter;
import com.google.code.kaptcha.Constants;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
/**
*
*
* @author ruoyi
*/
public class CaptchaValidateFilter extends AccessControlFilter
{
/**
*
*/
private boolean captchaEbabled = true;
/**
*
*/
private String captchaType = "math";
public void setCaptchaEbabled(boolean captchaEbabled)
{
this.captchaEbabled = captchaEbabled;
}
public void setCaptchaType(String captchaType)
{
this.captchaType = captchaType;
}
@Override
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
{
request.setAttribute(ShiroConstants.CURRENT_EBABLED, captchaEbabled);
request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType);
return super.onPreHandle(request, response, mappedValue);
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception
{
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 验证码禁用 或不是表单提交 允许访问
if (captchaEbabled == false || !"post".equals(httpServletRequest.getMethod().toLowerCase()))
{
return true;
}
return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE));
}
public boolean validateResponse(HttpServletRequest request, String validateCode)
{
Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
String code = String.valueOf(obj != null ? obj : "");
if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
{
return false;
}
return true;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
{
request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR);
return true;
}
}

View File

@ -0,0 +1,97 @@
package com.ruoyi.framework.shiro.web.filter.online;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
import com.ruoyi.project.system.user.domain.User;
/**
* 访
*
* @author ruoyi
*/
public class OnlineSessionFilter extends AccessControlFilter
{
/**
* 退
*/
@Value("${shiro.user.loginUrl}")
private String loginUrl;
@Autowired
private OnlineSessionDAO onlineSessionDAO;
/**
* 访mappedValue[urls]访truefalse
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception
{
Subject subject = getSubject(request, response);
if (subject == null || subject.getSession() == null)
{
return true;
}
Session session = onlineSessionDAO.readSession(subject.getSession().getId());
if (session != null && session instanceof OnlineSession)
{
OnlineSession onlineSession = (OnlineSession) session;
request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
// 把user对象设置进去
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
if (isGuest == true)
{
User user = ShiroUtils.getUser();
if (user != null)
{
onlineSession.setUserId(user.getUserId());
onlineSession.setLoginName(user.getLoginName());
onlineSession.setDeptName(user.getDept().getDeptName());
onlineSession.markAttributeChanged();
}
}
if (onlineSession.getStatus() == OnlineSession.OnlineStatus.off_line)
{
return false;
}
}
return true;
}
/**
* 访truefalse
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
{
Subject subject = getSubject(request, response);
if (subject != null)
{
subject.logout();
}
saveRequestAndRedirectToLogin(request, response);
return true;
}
// 跳转到登录页
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
{
WebUtils.issueRedirect(request, response, loginUrl);
}
}

View File

@ -0,0 +1,42 @@
package com.ruoyi.framework.shiro.web.filter.sync;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
/**
* SessionDb
*
* @author ruoyi
*/
public class SyncOnlineSessionFilter extends PathMatchingFilter
{
@Autowired
private OnlineSessionDAO onlineSessionDAO;
/**
* DB Shiro
*
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
{
OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
// 如果session stop了 也不同步
// session停止时间如果stopTimestamp不为null则代表已停止
if (session != null && session.getUserId() != null && session.getStopTimestamp() == null)
{
onlineSessionDAO.syncToDb(session);
}
return true;
}
}

View File

@ -0,0 +1,155 @@
package com.ruoyi.framework.shiro.web.session;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
import com.ruoyi.project.monitor.online.domain.UserOnline;
import com.ruoyi.project.monitor.online.service.UserOnlineServiceImpl;
/**
* 便 OnlineSessionDao
*
* @author ruoyi
*/
public class OnlineWebSessionManager extends DefaultWebSessionManager
{
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class);
@Override
public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException
{
super.setAttribute(sessionKey, attributeKey, value);
if (value != null && needMarkAttributeChanged(attributeKey))
{
OnlineSession s = (OnlineSession) doGetSession(sessionKey);
s.markAttributeChanged();
}
}
private boolean needMarkAttributeChanged(Object attributeKey)
{
if (attributeKey == null)
{
return false;
}
String attributeKeyStr = attributeKey.toString();
// 优化 flash属性没必要持久化
if (attributeKeyStr.startsWith("org.springframework"))
{
return false;
}
if (attributeKeyStr.startsWith("javax.servlet"))
{
return false;
}
if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME))
{
return false;
}
return true;
}
@Override
public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException
{
Object removed = super.removeAttribute(sessionKey, attributeKey);
if (removed != null)
{
OnlineSession s = (OnlineSession) doGetSession(sessionKey);
s.markAttributeChanged();
}
return removed;
}
/**
* session session
*/
@Override
public void validateSessions()
{
if (log.isInfoEnabled())
{
log.info("invalidation sessions...");
}
int invalidCount = 0;
int timeout = (int) this.getGlobalSessionTimeout();
Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout);
UserOnlineServiceImpl userOnlineService = SpringUtils.getBean(UserOnlineServiceImpl.class);
List<UserOnline> userOnlineList = userOnlineService.selectOnlineByExpired(expiredDate);
// 批量过期删除
List<String> needOfflineIdList = new ArrayList<String>();
for (UserOnline userOnline : userOnlineList)
{
try
{
SessionKey key = new DefaultSessionKey(userOnline.getSessionId());
Session session = retrieveSession(key);
if (session != null)
{
throw new InvalidSessionException();
}
}
catch (InvalidSessionException e)
{
if (log.isDebugEnabled())
{
boolean expired = (e instanceof ExpiredSessionException);
String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]"
+ (expired ? " (expired)" : " (stopped)");
log.debug(msg);
}
invalidCount++;
needOfflineIdList.add(userOnline.getSessionId());
}
}
if (needOfflineIdList.size() > 0)
{
try
{
userOnlineService.batchDeleteOnline(needOfflineIdList);
}
catch (Exception e)
{
log.error("batch delete db session error.", e);
}
}
if (log.isInfoEnabled())
{
String msg = "Finished invalidation session.";
if (invalidCount > 0)
{
msg += " [" + invalidCount + "] sessions were stopped.";
}
else
{
msg += " No sessions were stopped.";
}
log.info(msg);
}
}
@Override
protected Collection<Session> getActiveSessions()
{
throw new UnsupportedOperationException("getActiveSessions method not supported");
}
}

View File

@ -0,0 +1,141 @@
package com.ruoyi.framework.shiro.web.session;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.ValidatingSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*
* @author ruoyi
*/
public class SpringSessionValidationScheduler implements SessionValidationScheduler
{
private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
/**
*
*/
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private volatile boolean enabled = false;
/**
* The session manager used to validate sessions.
*/
private ValidatingSessionManager sessionManager;
/**
* The session validation interval in milliseconds.
*/
private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
/**
* Default constructor.
*/
public SpringSessionValidationScheduler()
{
}
/**
* Constructor that specifies the session manager that should be used for validating sessions.
*
* @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
*/
public SpringSessionValidationScheduler(ValidatingSessionManager sessionManager)
{
this.sessionManager = sessionManager;
}
public void setSessionManager(ValidatingSessionManager sessionManager)
{
this.sessionManager = sessionManager;
}
@Override
public boolean isEnabled()
{
return this.enabled;
}
/**
* Specifies how frequently (in milliseconds) this Scheduler will call the
* {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
* ValidatingSessionManager#validateSessions()} method.
*
* <p>
* Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
*
* @param sessionValidationInterval
*/
public void setSessionValidationInterval(long sessionValidationInterval)
{
this.sessionValidationInterval = sessionValidationInterval;
}
/**
* Starts session validation by creating a spring PeriodicTrigger.
*/
@Override
public void enableSessionValidation()
{
enabled = true;
if (log.isDebugEnabled())
{
log.debug("Scheduling session validation job using Spring Scheduler with "
+ "session validation interval of [" + sessionValidationInterval + "]ms...");
}
try
{
executorService.scheduleAtFixedRate(new Runnable()
{
@Override
public void run()
{
if (enabled)
{
sessionManager.validateSessions();
}
}
}, 1000, sessionValidationInterval, TimeUnit.MILLISECONDS);
this.enabled = true;
if (log.isDebugEnabled())
{
log.debug("Session validation job successfully scheduled with Spring Scheduler.");
}
}
catch (Exception e)
{
if (log.isErrorEnabled())
{
log.error(
"Error starting the Spring Scheduler session validation job. Session validation may not occur.",
e);
}
}
}
@Override
public void disableSessionValidation()
{
if (log.isDebugEnabled())
{
log.debug("Stopping Spring Scheduler session validation job...");
}
this.enabled = false;
}
}

View File

@ -0,0 +1,131 @@
package com.ruoyi.framework.web.controller;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.PageDomain;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.framework.web.page.TableSupport;
import com.ruoyi.project.system.user.domain.User;
/**
* web
*
* @author ruoyi
*/
public class BaseController
{
/**
* Date
*/
@InitBinder
public void initBinder(WebDataBinder binder)
{
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
/**
*
*/
protected void startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
{
String orderBy = pageDomain.getOrderBy();
PageHelper.startPage(pageNum, pageSize, orderBy);
}
}
/**
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
/**
*
*/
public AjaxResult success()
{
return AjaxResult.success();
}
/**
*
*/
public AjaxResult error()
{
return AjaxResult.error();
}
/**
*
*/
public AjaxResult success(String message)
{
return AjaxResult.success(message);
}
/**
*
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
}
/**
*
*/
public AjaxResult error(int code, String message)
{
return AjaxResult.error(code, message);
}
/**
*
*/
public String redirect(String url)
{
return StringUtils.format("redirect:{}", url);
}
public User getUser()
{
return ShiroUtils.getUser();
}
public void setUser(User user)
{
ShiroUtils.setUser(user);
}
public Long getUserId()
{
return getUser().getUserId();
}
public String getLoginName()
{
return getUser().getLoginName();
}
}

View File

@ -0,0 +1,94 @@
package com.ruoyi.framework.web.domain;
import java.util.HashMap;
/**
*
*
* @author ruoyi
*/
public class AjaxResult extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/**
* Message
*/
public AjaxResult()
{
}
/**
*
*
* @return
*/
public static AjaxResult error()
{
return error(1, "操作失败");
}
/**
*
*
* @param msg
* @return
*/
public static AjaxResult error(String msg)
{
return error(500, msg);
}
/**
*
*
* @param code
* @param msg
* @return
*/
public static AjaxResult error(int code, String msg)
{
AjaxResult json = new AjaxResult();
json.put("code", code);
json.put("msg", msg);
return json;
}
/**
*
*
* @param msg
* @return
*/
public static AjaxResult success(String msg)
{
AjaxResult json = new AjaxResult();
json.put("msg", msg);
json.put("code", 0);
return json;
}
/**
*
*
* @return
*/
public static AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
*
*
* @param key
* @param value
* @return
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
}

View File

@ -0,0 +1,98 @@
package com.ruoyi.framework.web.domain;
import java.io.Serializable;
import java.util.Date;
import com.ruoyi.common.utils.DateUtils;
/**
* Entity
*
* @author ruoyi
*/
public class BaseEntity implements Serializable
{
private static final long serialVersionUID = 1L;
/** 搜索值 */
private String searchValue;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
/** 备注 */
private String remark;
public String getSearchValue()
{
return searchValue;
}
public void setSearchValue(String searchValue)
{
this.searchValue = searchValue;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public String getCreateTimeStr()
{
return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, createTime) : "";
}
public String getCreateDateTimeStr()
{
return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime) : "";
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public String getUpdateTimeStr()
{
return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, updateTime) : "";
}
public String getUpdateDateTimeStr()
{
return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, updateTime) : "";
}
public void setUpdateTime(Date updateTime)
{
this.updateTime = updateTime;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}

View File

@ -0,0 +1,72 @@
package com.ruoyi.framework.web.exception;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.ruoyi.common.exception.DemoModeException;
import com.ruoyi.framework.web.domain.AjaxResult;
/**
*
*
* @author ruoyi
*/
@RestControllerAdvice
public class DefaultExceptionHandler
{
private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
/**
*
*/
@ExceptionHandler(AuthorizationException.class)
public AjaxResult handleAuthorizationException(AuthorizationException e)
{
log.error(e.getMessage(), e);
return AjaxResult.error("您没有数据的权限,请联系管理员添加");
}
/**
*
*/
@ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
public AjaxResult handleException(HttpRequestMethodNotSupportedException e)
{
log.error(e.getMessage(), e);
return AjaxResult.error("不支持' " + e.getMethod() + "'请求");
}
/**
*
*/
@ExceptionHandler(RuntimeException.class)
public AjaxResult notFount(RuntimeException e)
{
log.error("运行时异常:", e);
return AjaxResult.error("运行时异常:" + e.getMessage());
}
/**
*
*/
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e)
{
log.error(e.getMessage(), e);
return AjaxResult.error("服务器错误,请联系管理员");
}
/**
*
*/
@ExceptionHandler(DemoModeException.class)
public AjaxResult demoModeException(DemoModeException e)
{
return AjaxResult.error("演示模式,不允许操作");
}
}

View File

@ -0,0 +1,70 @@
package com.ruoyi.framework.web.page;
import com.ruoyi.common.utils.StringUtils;
/**
*
*
* @author ruoyi
*/
public class PageDomain
{
/** 当前记录起始索引 */
private Integer pageNum;
/** 每页显示记录数 */
private Integer pageSize;
/** 排序列 */
private String orderByColumn;
/** 排序的方向 "desc" 或者 "asc". */
private String isAsc;
public String getOrderBy()
{
if (StringUtils.isEmpty(orderByColumn))
{
return "";
}
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
}
public Integer getPageNum()
{
return pageNum;
}
public void setPageNum(Integer pageNum)
{
this.pageNum = pageNum;
}
public Integer getPageSize()
{
return pageSize;
}
public void setPageSize(Integer pageSize)
{
this.pageSize = pageSize;
}
public String getOrderByColumn()
{
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn)
{
this.orderByColumn = orderByColumn;
}
public String getIsAsc()
{
return isAsc;
}
public void setIsAsc(String isAsc)
{
this.isAsc = isAsc;
}
}

View File

@ -0,0 +1,58 @@
package com.ruoyi.framework.web.page;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author ruoyi
*/
public class TableDataInfo implements Serializable
{
private static final long serialVersionUID = 1L;
/** 总记录数 */
private long total;
/** 列表数据 */
private List<?> rows;
/**
*
*/
public TableDataInfo()
{
}
/**
*
*
* @param list
* @param total
*/
public TableDataInfo(List<?> list, int total)
{
this.rows = list;
this.total = total;
}
public long getTotal()
{
return total;
}
public void setTotal(long total)
{
this.total = total;
}
public List<?> getRows()
{
return rows;
}
public void setRows(List<?> rows)
{
this.rows = rows;
}
}

View File

@ -0,0 +1,31 @@
package com.ruoyi.framework.web.page;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.constant.Constants;
/**
*
*
* @author ruoyi
*/
public class TableSupport
{
/**
*
*/
public static PageDomain getPageDomain()
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(ServletUtils.getParameterToInt(Constants.PAGENUM));
pageDomain.setPageSize(ServletUtils.getParameterToInt(Constants.PAGESIZE));
pageDomain.setOrderByColumn(ServletUtils.getParameter(Constants.ORDERBYCOLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(Constants.ISASC));
return pageDomain;
}
public static PageDomain buildPageRequest()
{
return getPageDomain();
}
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.framework.web.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.project.system.config.service.IConfigService;
/**
* RuoYi html thymeleaf
*
* @author ruoyi
*/
@Component
public class ConfigService
{
@Autowired
private IConfigService configService;
/**
*
*
* @param configName
* @return
*/
public String selectConfigByKey(String configKey)
{
return configService.selectConfigByKey(configKey);
}
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.framework.web.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.project.system.dict.domain.DictData;
import com.ruoyi.project.system.dict.service.IDictDataService;
/**
* RuoYi html thymeleaf
*
* @author ruoyi
*/
@Component
public class DictService
{
@Autowired
private IDictDataService dictDataService;
/**
*
*
* @param dictType
* @return
*/
public List<DictData> selectDictData(String dictType)
{
return dictDataService.selectDictDataByType(dictType);
}
}

View File

@ -0,0 +1,84 @@
package com.ruoyi.project.common;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
/**
*
*
* @author ruoyi
*/
@Controller
public class CommonController
{
@RequestMapping("common/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
try
{
String filePath = ResourceUtils.getURL("classpath:").getPath() + "static/file/" + fileName;
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
File file = new File(filePath);
InputStream inputStream = new FileInputStream(file);
OutputStream os = response.getOutputStream();
byte[] b = new byte[1024];
int length;
while ((length = inputStream.read(b)) > 0)
{
os.write(b, 0, length);
}
os.close();
inputStream.close();
if (delete && file.exists())
{
file.delete();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
{
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE"))
{
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
}
else if (agent.contains("Firefox"))
{
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
}
else if (agent.contains("Chrome"))
{
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
else
{
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.project.monitor.druid;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ruoyi.framework.web.controller.BaseController;
/**
* druid
*
* @author ruoyi
*/
@Controller
@RequestMapping("/monitor/data")
public class DruidController extends BaseController
{
private String prefix = "/monitor/druid";
@RequiresPermissions("monitor:data:view")
@GetMapping()
public String index()
{
return redirect(prefix + "/index");
}
}

View File

@ -0,0 +1,159 @@
package com.ruoyi.project.monitor.job.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.monitor.job.domain.Job;
import com.ruoyi.project.monitor.job.service.IJobService;
/**
*
*
* @author ruoyi
*/
@Controller
@RequestMapping("/monitor/job")
public class JobController extends BaseController
{
private String prefix = "monitor/job";
@Autowired
private IJobService jobService;
@RequiresPermissions("monitor:job:view")
@GetMapping()
public String job()
{
return prefix + "/job";
}
@RequiresPermissions("monitor:job:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(Job job)
{
startPage();
List<Job> list = jobService.selectJobList(job);
return getDataTable(list);
}
@Log(title = "定时任务", action = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(Job job) throws Exception
{
try
{
List<Job> list = jobService.selectJobList(job);
ExcelUtil<Job> util = new ExcelUtil<Job>(Job.class);
return util.exportExcel(list, "job");
}
catch (Exception e)
{
return error("导出Excel失败请联系网站管理员");
}
}
@Log(title = "定时任务", action = BusinessType.DELETE)
@RequiresPermissions("monitor:job:remove")
@PostMapping("/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
try
{
jobService.deleteJobByIds(ids);
return success();
}
catch (Exception e)
{
e.printStackTrace();
return error(e.getMessage());
}
}
/**
*
*/
@Log(title = "定时任务", action = BusinessType.UPDATE)
@RequiresPermissions("monitor:job:changeStatus")
@PostMapping("/changeStatus")
@ResponseBody
public AjaxResult changeStatus(Job job)
{
if (jobService.changeStatus(job) > 0)
{
return success();
}
return error();
}
/**
*
*/
@Log(title = "定时任务", action = BusinessType.UPDATE)
@RequiresPermissions("monitor:job:changeStatus")
@PostMapping("/run")
@ResponseBody
public AjaxResult run(Job job)
{
if (jobService.run(job) > 0)
{
return success();
}
return error();
}
/**
*
*/
@Log(title = "定时任务", action = BusinessType.INSERT)
@RequiresPermissions("monitor:job:add")
@GetMapping("/add")
public String add(Model model)
{
return prefix + "/add";
}
/**
*
*/
@Log(title = "定时任务", action = BusinessType.UPDATE)
@RequiresPermissions("monitor:job:edit")
@GetMapping("/edit/{jobId}")
public String edit(@PathVariable("jobId") Long jobId, Model model)
{
Job job = jobService.selectJobById(jobId);
model.addAttribute("job", job);
return prefix + "/edit";
}
/**
*
*/
@Log(title = "定时任务", action = BusinessType.SAVE)
@RequiresPermissions("monitor:job:save")
@PostMapping("/save")
@ResponseBody
public AjaxResult save(Job job)
{
if (jobService.saveJobCron(job) > 0)
{
return success();
}
return error();
}
}

View File

@ -0,0 +1,85 @@
package com.ruoyi.project.monitor.job.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.monitor.job.domain.JobLog;
import com.ruoyi.project.monitor.job.service.IJobLogService;
/**
*
*
* @author ruoyi
*/
@Controller
@RequestMapping("/monitor/jobLog")
public class JobLogController extends BaseController
{
private String prefix = "monitor/job";
@Autowired
private IJobLogService jobLogService;
@RequiresPermissions("monitor:job:view")
@GetMapping()
public String jobLog()
{
return prefix + "/jobLog";
}
@RequiresPermissions("monitor:job:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(JobLog jobLog)
{
startPage();
List<JobLog> list = jobLogService.selectJobLogList(jobLog);
return getDataTable(list);
}
@Log(title = "调度日志", action = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(JobLog jobLog) throws Exception
{
try
{
List<JobLog> list = jobLogService.selectJobLogList(jobLog);
ExcelUtil<JobLog> util = new ExcelUtil<JobLog>(JobLog.class);
return util.exportExcel(list, "jobLog");
}
catch (Exception e)
{
return error("导出Excel失败请联系网站管理员");
}
}
@Log(title = "调度日志", action = BusinessType.DELETE)
@RequiresPermissions("monitor:job:remove")
@PostMapping("/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
try
{
jobLogService.deleteJobLogByIds(ids);
return success();
}
catch (Exception e)
{
e.printStackTrace();
return error(e.getMessage());
}
}
}

View File

@ -0,0 +1,122 @@
package com.ruoyi.project.monitor.job.domain;
import java.io.Serializable;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.framework.web.domain.BaseEntity;
/**
* sys_job
*
* @author ruoyi
*/
public class Job extends BaseEntity implements Serializable
{
private static final long serialVersionUID = 1L;
/** 任务ID */
@Excel(name = "任务序号", column = "A")
private Long jobId;
/** 任务名称 */
@Excel(name = "任务名称", column = "B")
private String jobName;
/** 任务组名 */
@Excel(name = "任务组名", column = "C")
private String jobGroup;
/** 任务方法 */
@Excel(name = "任务方法", column = "D")
private String methodName;
/** 方法参数 */
@Excel(name = "方法参数", column = "E")
private String params;
/** cron执行表达式 */
@Excel(name = "执行表达式 ", column = "F")
private String cronExpression;
/** 任务状态0正常 1暂停 */
@Excel(name = "任务状态", column = "G")
private String status;
public Long getJobId()
{
return jobId;
}
public void setJobId(Long jobId)
{
this.jobId = jobId;
}
public String getJobName()
{
return jobName;
}
public void setJobName(String jobName)
{
this.jobName = jobName;
}
public String getJobGroup()
{
return jobGroup;
}
public void setJobGroup(String jobGroup)
{
this.jobGroup = jobGroup;
}
public String getMethodName()
{
return methodName;
}
public void setMethodName(String methodName)
{
this.methodName = methodName;
}
public String getParams()
{
return params;
}
public void setParams(String params)
{
this.params = params;
}
public String getCronExpression()
{
return cronExpression;
}
public void setCronExpression(String cronExpression)
{
this.cronExpression = cronExpression;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString()
{
return "Job [jobId=" + jobId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName=" + methodName
+ ", params=" + params + ", cronExpression=" + cronExpression + ", status=" + status + "]";
}
}

View File

@ -0,0 +1,135 @@
package com.ruoyi.project.monitor.job.domain;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.framework.web.domain.BaseEntity;
/**
* sys_job_log
*
* @author ruoyi
*/
public class JobLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** ID */
@Excel(name = "日志序号", column = "A")
private Long jobLogId;
/** 任务名称 */
@Excel(name = "任务名称", column = "B")
private String jobName;
/** 任务组名 */
@Excel(name = "任务组名", column = "C")
private String jobGroup;
/** 任务方法 */
@Excel(name = "任务方法", column = "D")
private String methodName;
/** 方法参数 */
@Excel(name = "方法参数", column = "E")
private String params;
/** 日志信息 */
@Excel(name = "日志信息", column = "F")
private String jobMessage;
/** 执行状态0正常 1失败 */
@Excel(name = "执行状态", column = "G")
private String status;
/** 异常信息 */
@Excel(name = "异常信息", column = "H")
private String exceptionInfo;
public Long getJobLogId()
{
return jobLogId;
}
public void setJobLogId(Long jobLogId)
{
this.jobLogId = jobLogId;
}
public String getJobName()
{
return jobName;
}
public void setJobName(String jobName)
{
this.jobName = jobName;
}
public String getJobGroup()
{
return jobGroup;
}
public void setJobGroup(String jobGroup)
{
this.jobGroup = jobGroup;
}
public String getMethodName()
{
return methodName;
}
public void setMethodName(String methodName)
{
this.methodName = methodName;
}
public String getParams()
{
return params;
}
public void setParams(String params)
{
this.params = params;
}
public String getJobMessage()
{
return jobMessage;
}
public void setJobMessage(String jobMessage)
{
this.jobMessage = jobMessage;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getExceptionInfo()
{
return exceptionInfo;
}
public void setExceptionInfo(String exceptionInfo)
{
this.exceptionInfo = exceptionInfo;
}
@Override
public String toString()
{
return "JobLog [jobLogId=" + jobLogId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName="
+ methodName + ", params=" + params + ", jobMessage=" + jobMessage + ", status=" + status
+ ", exceptionInfo=" + exceptionInfo + "]";
}
}

View File

@ -0,0 +1,54 @@
package com.ruoyi.project.monitor.job.mapper;
import java.util.List;
import com.ruoyi.project.monitor.job.domain.JobLog;
/**
*
*
* @author ruoyi
*/
public interface JobLogMapper
{
/**
* quartz
*
* @param jobLog
* @return
*/
public List<JobLog> selectJobLogList(JobLog jobLog);
/**
* ID
*
* @param jobLogId ID
* @return
*/
public JobLog selectJobLogById(Long jobLogId);
/**
*
*
* @param jobLog
* @return
*/
public int insertJobLog(JobLog jobLog);
/**
*
*
* @param ids ID
* @return
*/
public int deleteJobLogByIds(String[] ids);
/**
*
*
* @param jobId ID
* @return
*/
public int deleteJobLogById(Long jobId);
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.project.monitor.job.mapper;
import java.util.List;
import com.ruoyi.project.monitor.job.domain.Job;
/**
*
*
* @author ruoyi
*/
public interface JobMapper
{
/**
*
*
* @param job
* @return
*/
public List<Job> selectJobList(Job job);
/**
*
*
* @return
*/
public List<Job> selectJobAll();
/**
* ID
*
* @param jobId ID
* @return
*/
public Job selectJobById(Long jobId);
/**
* ID
*
* @param jobId ID
* @return
*/
public int deleteJobById(Job job);
/**
*
*
* @param ids ID
* @return
*/
public int deleteJobLogByIds(Long[] ids);
/**
*
*
* @param job
* @return
*/
public int updateJob(Job job);
/**
*
*
* @param job
* @return
*/
public int insertJob(Job job);
}

View File

@ -0,0 +1,53 @@
package com.ruoyi.project.monitor.job.service;
import java.util.List;
import com.ruoyi.project.monitor.job.domain.JobLog;
/**
*
*
* @author ruoyi
*/
public interface IJobLogService
{
/**
* quartz
*
* @param jobLog
* @return
*/
public List<JobLog> selectJobLogList(JobLog jobLog);
/**
* ID
*
* @param jobLogId ID
* @return
*/
public JobLog selectJobLogById(Long jobLogId);
/**
*
*
* @param jobLog
*/
public void addJobLog(JobLog jobLog);
/**
*
*
* @param ids ID
* @return
*/
public int deleteJobLogByIds(String ids);
/**
*
*
* @param jobId ID
* @return
*/
public int deleteJobLogById(Long jobId);
}

View File

@ -0,0 +1,101 @@
package com.ruoyi.project.monitor.job.service;
import java.util.List;
import com.ruoyi.project.monitor.job.domain.Job;
/**
*
*
* @author ruoyi
*/
public interface IJobService
{
/**
* quartz
*
* @param job
* @return
*/
public List<Job> selectJobList(Job job);
/**
* ID
*
* @param jobId ID
* @return
*/
public Job selectJobById(Long jobId);
/**
*
*
* @param job
* @return
*/
public int pauseJob(Job job);
/**
*
*
* @param job
* @return
*/
public int resumeJob(Job job);
/**
* trigger
*
* @param job
* @return
*/
public int deleteJob(Job job);
/**
*
*
* @param ids ID
* @return
*/
public void deleteJobByIds(String ids);
/**
*
*
* @param job
* @return
*/
public int changeStatus(Job job);
/**
*
*
* @param job
* @return
*/
public int run(Job job);
/**
*
*
* @param job
* @return
*/
public int addJobCron(Job job);
/**
*
*
* @param job
* @return
*/
public int updateJobCron(Job job);
/**
*
*
* @param job
* @return
*/
public int saveJobCron(Job job);
}

View File

@ -0,0 +1,80 @@
package com.ruoyi.project.monitor.job.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.support.Convert;
import com.ruoyi.project.monitor.job.domain.JobLog;
import com.ruoyi.project.monitor.job.mapper.JobLogMapper;
/**
*
*
* @author ruoyi
*/
@Service("jobLogService")
public class JobLogServiceImpl implements IJobLogService
{
@Autowired
private JobLogMapper jobLogMapper;
/**
* quartz
*
* @param jobLog
* @return
*/
@Override
public List<JobLog> selectJobLogList(JobLog jobLog)
{
return jobLogMapper.selectJobLogList(jobLog);
}
/**
* ID
*
* @param jobId ID
* @return
*/
@Override
public JobLog selectJobLogById(Long jobLogId)
{
return jobLogMapper.selectJobLogById(jobLogId);
}
/**
*
*
* @param jobLog
*/
@Override
public void addJobLog(JobLog jobLog)
{
jobLogMapper.insertJobLog(jobLog);
}
/**
*
*
* @param ids ID
* @return
*/
@Override
public int deleteJobLogByIds(String ids)
{
return jobLogMapper.deleteJobLogByIds(Convert.toStrArray(ids));
}
/**
*
*
* @param jobId ID
*/
@Override
public int deleteJobLogById(Long jobId)
{
return jobLogMapper.deleteJobLogById(jobId);
}
}

View File

@ -0,0 +1,236 @@
package com.ruoyi.project.monitor.job.service;
import java.util.List;
import javax.annotation.PostConstruct;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.constant.ScheduleConstants;
import com.ruoyi.common.support.Convert;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.monitor.job.domain.Job;
import com.ruoyi.project.monitor.job.mapper.JobMapper;
import com.ruoyi.project.monitor.job.util.ScheduleUtils;
/**
*
*
* @author ruoyi
*/
@Service("jobService")
public class JobServiceImpl implements IJobService
{
@Autowired
private Scheduler scheduler;
@Autowired
private JobMapper jobMapper;
/**
*
*/
@PostConstruct
public void init()
{
List<Job> jobList = jobMapper.selectJobAll();
for (Job job : jobList)
{
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, job.getJobId());
// 如果不存在,则创建
if (cronTrigger == null)
{
ScheduleUtils.createScheduleJob(scheduler, job);
}
else
{
ScheduleUtils.updateScheduleJob(scheduler, job);
}
}
}
/**
* quartz
*
* @param job
* @return
*/
@Override
public List<Job> selectJobList(Job job)
{
return jobMapper.selectJobList(job);
}
/**
* ID
*
* @param jobId ID
* @return
*/
@Override
public Job selectJobById(Long jobId)
{
return jobMapper.selectJobById(jobId);
}
/**
*
*
* @param job
*/
@Override
public int pauseJob(Job job)
{
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
job.setUpdateBy(ShiroUtils.getLoginName());
int rows = jobMapper.updateJob(job);
if (rows > 0)
{
ScheduleUtils.pauseJob(scheduler, job.getJobId());
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int resumeJob(Job job)
{
job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
job.setUpdateBy(ShiroUtils.getLoginName());
int rows = jobMapper.updateJob(job);
if (rows > 0)
{
ScheduleUtils.resumeJob(scheduler, job.getJobId());
}
return rows;
}
/**
* trigger
*
* @param job
*/
@Override
public int deleteJob(Job job)
{
int rows = jobMapper.deleteJobById(job);
if (rows > 0)
{
ScheduleUtils.deleteScheduleJob(scheduler, job.getJobId());
}
return rows;
}
/**
*
*
* @param ids ID
* @return
*/
@Override
public void deleteJobByIds(String ids)
{
Long[] jobIds = Convert.toLongArray(ids);
for (Long jobId : jobIds)
{
Job job = jobMapper.selectJobById(jobId);
deleteJob(job);
}
}
/**
*
*
* @param job
*/
@Override
public int changeStatus(Job job)
{
int rows = 0;
String status = job.getStatus();
if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
{
rows = resumeJob(job);
}
else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
{
rows = pauseJob(job);
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int run(Job job)
{
return ScheduleUtils.run(scheduler, selectJobById(job.getJobId()));
}
/**
*
*
* @param job
*/
@Override
public int addJobCron(Job job)
{
job.setCreateBy(ShiroUtils.getLoginName());
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
int rows = jobMapper.insertJob(job);
if (rows > 0)
{
ScheduleUtils.createScheduleJob(scheduler, job);
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int updateJobCron(Job job)
{
int rows = jobMapper.updateJob(job);
if (rows > 0)
{
ScheduleUtils.updateScheduleJob(scheduler, job);
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int saveJobCron(Job job)
{
Long jobId = job.getJobId();
int rows = 0;
if (StringUtils.isNotNull(jobId))
{
rows = updateJobCron(job);
}
else
{
rows = addJobCron(job);
}
return rows;
}
}

View File

@ -0,0 +1,24 @@
package com.ruoyi.project.monitor.job.task;
import org.springframework.stereotype.Component;
/**
*
*
* @author ruoyi
*/
@Component("ryTask")
public class RyTask
{
public void ryParams(String params)
{
System.out.println("执行有参方法:" + params);
}
public void ryNoParams()
{
System.out.println("执行无参方法");
}
}

View File

@ -0,0 +1,88 @@
package com.ruoyi.project.monitor.job.util;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.commons.beanutils.PropertyUtils;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ScheduleConstants;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.monitor.job.domain.Job;
import com.ruoyi.project.monitor.job.domain.JobLog;
import com.ruoyi.project.monitor.job.service.IJobLogService;
/**
*
*
* @author ruoyi
*
*/
public class ScheduleJob extends QuartzJobBean
{
private static final Logger log = LoggerFactory.getLogger(ScheduleJob.class);
private ExecutorService service = Executors.newSingleThreadExecutor();
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
{
// Job job = (Job) context.getMergedJobDataMap().get(ScheduleConstants.JOB_PARAM_KEY);
JobDataMap jobDataMap = context.getMergedJobDataMap();
Job job = new Job();
try
{
PropertyUtils.copyProperties(job, jobDataMap.get(ScheduleConstants.JOB_PARAM_KEY));
}
catch (Exception e)
{
log.error("copyProperties执行异常 - ", e);
}
IJobLogService jobLogService = (IJobLogService) SpringUtils.getBean(IJobLogService.class);
JobLog jobLog = new JobLog();
jobLog.setJobName(job.getJobName());
jobLog.setJobGroup(job.getJobGroup());
jobLog.setMethodName(job.getMethodName());
jobLog.setParams(job.getParams());
jobLog.setCreateTime(new Date());
long startTime = System.currentTimeMillis();
try
{
// 执行任务
log.info("任务开始执行 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
ScheduleRunnable task = new ScheduleRunnable(job.getJobName(), job.getMethodName(), job.getParams());
Future<?> future = service.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
// 任务状态 0成功 1失败
jobLog.setStatus(Constants.SUCCESS);
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
log.info("任务执行结束 - 名称:{} 耗时:{} 毫秒", job.getJobName(), times);
}
catch (Exception e)
{
log.info("任务执行失败 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
log.error("任务执行异常 - ", e);
long times = System.currentTimeMillis() - startTime;
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
// 任务状态 0成功 1失败
jobLog.setStatus(Constants.FAIL);
jobLog.setExceptionInfo(e.toString());
}
finally
{
jobLogService.addJobLog(jobLog);
}
}
}

View File

@ -0,0 +1,59 @@
package com.ruoyi.project.monitor.job.util;
import java.lang.reflect.Method;
import org.springframework.util.ReflectionUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
*
*
* @author ruoyi
*
*/
public class ScheduleRunnable implements Runnable
{
private Object target;
private Method method;
private String params;
public ScheduleRunnable(String beanName, String methodName, String params)
throws NoSuchMethodException, SecurityException
{
this.target = SpringUtils.getBean(beanName);
this.params = params;
if (StringUtils.isNotEmpty(params))
{
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
}
else
{
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
@Override
public void run()
{
try
{
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotEmpty(params))
{
method.invoke(target, params);
}
else
{
method.invoke(target);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

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