若依开源1.1.1发布

pull/2/head
RuoYi 2018-04-23 00:00:29 +08:00
commit 262ee25d8e
453 changed files with 66923 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target/

202
LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2018 RuoYi All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

51
README.md Normal file
View File

@ -0,0 +1,51 @@
## 平台简介
一直想做一款后台管理系统看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了若依管理系统。她可以用于所有的Web应用程序如网站管理后台网站会员中心CMSCRMOA。所有前端后台代码封装过后十分精简易上手出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
寓意:你若不离不弃,我必生死相依
## 内置功能
1. 用户管理:用户是系统操作者。
2. 部门管理:配置系统组织机构。
3. 岗位管理:岗位是用户所属职务。
4. 菜单管理:配置系统菜单(支持控制到按钮)。
5. 角色管理:角色菜单权限分配。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 操作日志:系统操作日志记录(含异常)。
8. 登录日志:系统登录情况记录(含异常)。
9. 在线用户:当前系统中活跃用户状态监控。
10. 定时任务:在线添加、修改和删除任务调度(含执行日志)。
11. 代码生成:生成包括 java、html、js、xml、sql
12. 连接池监视监视当期系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
## 系统演示
![登录界面](https://static.oschina.net/uploads/space/2018/0301/160757_fnZP_1438828.png)
![首页](https://static.oschina.net/uploads/space/2018/0301/221159_e9GB_1438828.png)
![操作日志](https://static.oschina.net/uploads/space/2018/0303/011028_xWoa_1438828.png)
![部门管理](https://static.oschina.net/uploads/space/2018/0311/235903_p5W6_1438828.png)
![用户管理](https://static.oschina.net/uploads/space/2018/0315/005844_Qduc_1438828.png)
![用户修改](https://static.oschina.net/uploads/space/2018/0403/234316_tMEP_1438828.png)
![部门选择](https://static.oschina.net/uploads/space/2018/0315/005851_bFzg_1438828.png)
![角色修改](https://static.oschina.net/uploads/space/2018/0310/164644_Jsre_1438828.png)
![菜单修改](https://static.oschina.net/uploads/space/2018/0311/235934_lHXI_1438828.png)
![岗位管理](https://static.oschina.net/uploads/space/2018/0403/234336_BqKh_1438828.png)
![调度日志](https://static.oschina.net/uploads/space/2018/0407/173459_d28s_1438828.png)
![代码生成](https://static.oschina.net/uploads/space/2018/0413/172629_IQ1C_1438828.png)
## 若依交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/QQ群-1389287-blue.svg)](http://shang.qq.com/wpa/qunwpa?idkey=9a7d9f3274e4bfbf7e40e4a485ff6dc2adbeee8086ce39e40667ed4387414f12) 或 [![加入QQ群](https://img.shields.io/badge/QQ群-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ONbr1w),推荐点击按钮入群,当然如果无法成功操作,请自行搜索群号`1389287`进行添加

170
doc/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;

504
doc/ry_20180423.sql Normal file
View File

@ -0,0 +1,504 @@
-- ----------------------------
-- 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(20) default '' comment '联系电话',
email varchar(20) default '' comment '邮箱',
status int(1) default 0 comment '部门状态:0正常,1停用',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp comment '更新时间',
primary key (dept_id)
) engine=innodb auto_increment=200 default charset=utf8 comment = '部门表';
-- ----------------------------
-- 初始化-部门表数据
-- ----------------------------
insert into sys_dept values(100, 0, '若依集团', 0, '马云', '15011112221', 'ry@qq.com', 0, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(101, 100, '研发部门', 1, '马研', '15011112222', 'ry@qq.com', 0, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(102, 100, '市场部门', 2, '马市', '15011112223', 'ry@qq.com', 0, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(103, 100, '测试部门', 3, '马测', '15011112224', 'ry@qq.com', 0, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(104, 100, '财务部门', 4, '马财', '15011112225', 'ry@qq.com', 1, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(105, 100, '运维部门', 5, '马运', '15011112226', 'ry@qq.com', 1, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(106, 101, '研发一部', 1, '马一', '15011112227', 'ry@qq.com', 0, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(107, 101, '研发二部', 2, '马二', '15011112228', 'ry@qq.com', 1, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(108, 102, '市场一部', 1, '马一', '15011112229', 'ry@qq.com', 0, 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_dept values(109, 102, '市场二部', 2, '马二', '15011112210', 'ry@qq.com', 1, 'admin', '2018-03-01', 'ry', '2018-03-01');
-- ----------------------------
-- 2、用户信息表
-- ----------------------------
drop table if exists sys_user;
create table sys_user (
user_id int(11) not null auto_increment comment '用户ID',
dept_id int(20) default null comment '部门ID',
login_name varchar(30) default '' comment '登录账号',
user_name varchar(30) default '' comment '用户昵称',
email varchar(100) default '' comment '用户邮箱',
phonenumber varchar(20) default '' comment '手机号码',
password varchar(100) default '' comment '密码',
salt varchar(100) default '' comment '盐加密',
user_type char(1) default 'N' comment '类型:Y默认用户,N非默认用户',
status int(1) default 0 comment '帐号状态:0正常,1禁用',
refuse_des varchar(500) default '' comment '拒绝登录描述',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp comment '更新时间',
primary key (user_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '用户信息表';
-- ----------------------------
-- 初始化-用户信息表数据
-- ----------------------------
insert into sys_user values(1, 106, 'admin', '若依', 'yzz_ivy@163.com', '15088888888', '29c67a30398638269fe600f73a054934', '111111', 'Y', 0, '维护中', 'admin', '2018-03-01', 'ry', '2018-03-01');
insert into sys_user values(2, 108, 'ry', '若依', 'ry@163.com', '15288888888', '8e6d98b90472783cc73c17047ddccf36', '222222', 'N', 1, '锁定中', 'admin', '2018-03-01', 'ry', '2018-03-01');
-- ----------------------------
-- 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(100) not null comment '岗位名称',
post_sort int(4) not null comment '显示顺序',
status int(1) not null comment '状态0正常 1停用',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp 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-01', 'ry', '2018-03-01', '');
insert into sys_post values(2, 'se', '项目经理', 2, 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_post values(3, 'hr', '人力资源', 3, 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_post values(4, 'user', '普通员工', 4, 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- ----------------------------
-- 4、角色信息表
-- ----------------------------
drop table if exists sys_role;
create table sys_role (
role_id int(10) not null auto_increment comment '角色ID',
role_name varchar(30) not null comment '角色名称',
role_key varchar(100) not null comment '角色权限字符串',
role_sort int(10) not null comment '显示顺序',
status int(1) default 0 comment '角色状态:0正常,1禁用',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp 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-01', 'ry', '2018-03-01', '管理员');
insert into sys_role values('2', '普通角色', 'common', 2, 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '普通角色');
-- ----------------------------
-- 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 int(1) default 0 comment '菜单状态:0显示,1隐藏',
perms varchar(100) default '' comment '权限标识',
icon varchar(100) default '' comment '菜单图标',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp comment '更新时间',
remark varchar(500) default '' comment '备注',
primary key (menu_id)
) engine=innodb auto_increment=1000 default charset=utf8 comment = '菜单权限表';
-- ----------------------------
-- 初始化-菜单信息表数据
-- ----------------------------
-- 一级菜单
insert into sys_menu values('1', '系统管理', '0', '1', '#', 'M', '0', '', 'fa fa-gear', 'admin', '2018-03-01', 'ry', '2018-03-01', '系统管理目录');
insert into sys_menu values('2', '系统监控', '0', '2', '#', 'M', '0', '', 'fa fa-video-camera', 'admin', '2018-03-01', 'ry', '2018-03-01', '系统监控目录');
insert into sys_menu values('3', '系统工具', '0', '3', '#', 'M', '0', '', 'fa fa-bars', 'admin', '2018-03-01', 'ry', '2018-03-01', '系统工具目录');
-- 二级菜单
insert into sys_menu values('4', '用户管理', '1', '1', '/system/user', 'C', '0', 'system:user:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '用户管理菜单');
insert into sys_menu values('5', '角色管理', '1', '2', '/system/role', 'C', '0', 'system:role:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '角色管理菜单');
insert into sys_menu values('6', '菜单管理', '1', '3', '/system/menu', 'C', '0', 'system:menu:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '菜单管理菜单');
insert into sys_menu values('7', '部门管理', '1', '4', '/system/dept', 'C', '0', 'system:dept:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '部门管理菜单');
insert into sys_menu values('8', '岗位管理', '1', '5', '/system/post', 'C', '0', 'system:post:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '岗位管理菜单');
insert into sys_menu values('9', '字典管理', '1', '6', '/system/dict', 'C', '0', 'system:dict:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '字典管理菜单');
insert into sys_menu values('10', '参数设置', '1', '7', '/system/config', 'C', '0', 'system:config:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '参数设置菜单');
insert into sys_menu values('11', '操作日志', '2', '1', '/monitor/operlog', 'C', '0', 'monitor:operlog:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '操作日志菜单');
insert into sys_menu values('12', '登录日志', '2', '2', '/monitor/logininfor', 'C', '0', 'monitor:logininfor:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '登录日志菜单');
insert into sys_menu values('13', '在线用户', '2', '3', '/monitor/online', 'C', '0', 'monitor:online:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '在线用户菜单');
insert into sys_menu values('14', '定时任务', '2', '4', '/monitor/job', 'C', '0', 'monitor:job:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '定时任务菜单');
insert into sys_menu values('15', '数据监控', '2', '5', '/monitor/data', 'C', '0', 'monitor:data:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '数据监控菜单');
insert into sys_menu values('16', '表单构建', '3', '1', '/tool/build', 'C', '0', 'tool:build:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '表单构建菜单');
insert into sys_menu values('17', '代码生成', '3', '2', '/tool/gen', 'C', '0', 'tool:gen:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '代码生成菜单');
-- 用户管理按钮
insert into sys_menu values('18', '用户查询', '4', '1', '#', 'F', '0', 'system:user:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('19', '用户新增', '4', '2', '#', 'F', '0', 'system:user:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('20', '用户修改', '4', '3', '#', 'F', '0', 'system:user:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('21', '用户删除', '4', '4', '#', 'F', '0', 'system:user:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('22', '用户保存', '4', '5', '#', 'F', '0', 'system:user:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('23', '批量删除', '4', '6', '#', 'F', '0', 'system:user:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('24', '重置密码', '4', '7', '#', 'F', '0', 'system:user:resetPwd', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 角色管理按钮
insert into sys_menu values('25', '角色查询', '5', '1', '#', 'F', '0', 'system:role:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('26', '角色新增', '5', '2', '#', 'F', '0', 'system:role:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('27', '角色修改', '5', '3', '#', 'F', '0', 'system:role:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('28', '角色删除', '5', '4', '#', 'F', '0', 'system:role:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('29', '角色保存', '5', '5', '#', 'F', '0', 'system:role:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('30', '批量删除', '5', '6', '#', 'F', '0', 'system:role:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 菜单管理按钮
insert into sys_menu values('31', '菜单查询', '6', '1', '#', 'F', '0', 'system:menu:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('32', '菜单新增', '6', '2', '#', 'F', '0', 'system:menu:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('33', '菜单修改', '6', '3', '#', 'F', '0', 'system:menu:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('34', '菜单删除', '6', '4', '#', 'F', '0', 'system:menu:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('35', '菜单保存', '6', '5', '#', 'F', '0', 'system:menu:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 部门管理按钮
insert into sys_menu values('36', '部门查询', '7', '1', '#', 'F', '0', 'system:dept:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('37', '部门新增', '7', '2', '#', 'F', '0', 'system:dept:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('38', '部门修改', '7', '3', '#', 'F', '0', 'system:dept:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('39', '部门删除', '7', '4', '#', 'F', '0', 'system:dept:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('40', '部门保存', '7', '5', '#', 'F', '0', 'system:dept:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 岗位管理按钮
insert into sys_menu values('41', '岗位查询', '8', '1', '#', 'F', '0', 'system:post:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('42', '岗位新增', '8', '2', '#', 'F', '0', 'system:post:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('43', '岗位修改', '8', '3', '#', 'F', '0', 'system:post:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('44', '岗位删除', '8', '4', '#', 'F', '0', 'system:post:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('45', '岗位保存', '8', '5', '#', 'F', '0', 'system:post:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('46', '批量删除', '8', '6', '#', 'F', '0', 'system:post:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 字典管理按钮
insert into sys_menu values('47', '字典查询', '9', '1', '#', 'F', '0', 'system:dict:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('48', '字典新增', '9', '2', '#', 'F', '0', 'system:dict:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('49', '字典修改', '9', '3', '#', 'F', '0', 'system:dict:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('50', '字典删除', '9', '4', '#', 'F', '0', 'system:dict:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('51', '字典保存', '9', '5', '#', 'F', '0', 'system:dict:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('52', '批量删除', '9', '6', '#', 'F', '0', 'system:dict:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 操作日志按钮
insert into sys_menu values('53', '操作查询', '11', '1', '#', 'F', '0', 'monitor:operlog:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('54', '批量删除', '11', '2', '#', 'F', '0', 'monitor:operlog:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('55', '详细信息', '11', '3', '#', 'F', '0', 'monitor:operlog:detail', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 登录日志按钮
insert into sys_menu values('56', '登录查询', '12', '1', '#', 'F', '0', 'monitor:logininfor:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('57', '批量删除', '12', '2', '#', 'F', '0', 'monitor:logininfor:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 在线用户按钮
insert into sys_menu values('58', '在线查询', '13', '1', '#', 'F', '0', 'monitor:online:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('59', '批量强退', '13', '2', '#', 'F', '0', 'monitor:online:batchForceLogout', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('60', '单条强退', '13', '3', '#', 'F', '0', 'monitor:online:forceLogout', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 定时任务按钮
insert into sys_menu values('61', '任务查询', '14', '1', '#', 'F', '0', 'monitor:job:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('62', '任务新增', '14', '2', '#', 'F', '0', 'monitor:job:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('63', '任务修改', '14', '3', '#', 'F', '0', 'monitor:job:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('64', '任务删除', '14', '4', '#', 'F', '0', 'monitor:job:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('65', '任务保存', '14', '5', '#', 'F', '0', 'monitor:job:save', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('66', '状态修改', '14', '6', '#', 'F', '0', 'monitor:job:changeStatus', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('67', '批量删除', '14', '7', '#', 'F', '0', 'monitor:job:batchRemove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- 代码生成按钮
insert into sys_menu values('68', '生成查询', '16', '1', '#', 'F', '0', 'tool:gen:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_menu values('69', '生成代码', '16', '2', '#', 'F', '0', 'tool:gen:code', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- ----------------------------
-- 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', '4');
insert into sys_role_menu values ('1', '5');
insert into sys_role_menu values ('1', '6');
insert into sys_role_menu values ('1', '7');
insert into sys_role_menu values ('1', '8');
insert into sys_role_menu values ('1', '9');
insert into sys_role_menu values ('1', '10');
insert into sys_role_menu values ('1', '11');
insert into sys_role_menu values ('1', '12');
insert into sys_role_menu values ('1', '13');
insert into sys_role_menu values ('1', '14');
insert into sys_role_menu values ('1', '15');
insert into sys_role_menu values ('1', '16');
insert into sys_role_menu values ('1', '17');
insert into sys_role_menu values ('1', '18');
insert into sys_role_menu values ('1', '19');
insert into sys_role_menu values ('1', '20');
insert into sys_role_menu values ('1', '21');
insert into sys_role_menu values ('1', '22');
insert into sys_role_menu values ('1', '23');
insert into sys_role_menu values ('1', '24');
insert into sys_role_menu values ('1', '25');
insert into sys_role_menu values ('1', '26');
insert into sys_role_menu values ('1', '27');
insert into sys_role_menu values ('1', '28');
insert into sys_role_menu values ('1', '29');
insert into sys_role_menu values ('1', '30');
insert into sys_role_menu values ('1', '31');
insert into sys_role_menu values ('1', '32');
insert into sys_role_menu values ('1', '33');
insert into sys_role_menu values ('1', '34');
insert into sys_role_menu values ('1', '35');
insert into sys_role_menu values ('1', '36');
insert into sys_role_menu values ('1', '37');
insert into sys_role_menu values ('1', '38');
insert into sys_role_menu values ('1', '39');
insert into sys_role_menu values ('1', '40');
insert into sys_role_menu values ('1', '41');
insert into sys_role_menu values ('1', '42');
insert into sys_role_menu values ('1', '43');
insert into sys_role_menu values ('1', '44');
insert into sys_role_menu values ('1', '45');
insert into sys_role_menu values ('1', '46');
insert into sys_role_menu values ('1', '47');
insert into sys_role_menu values ('1', '48');
insert into sys_role_menu values ('1', '49');
insert into sys_role_menu values ('1', '50');
insert into sys_role_menu values ('1', '51');
insert into sys_role_menu values ('1', '52');
insert into sys_role_menu values ('1', '53');
insert into sys_role_menu values ('1', '54');
insert into sys_role_menu values ('1', '55');
insert into sys_role_menu values ('1', '56');
insert into sys_role_menu values ('1', '57');
insert into sys_role_menu values ('1', '58');
insert into sys_role_menu values ('1', '59');
insert into sys_role_menu values ('1', '60');
insert into sys_role_menu values ('1', '61');
insert into sys_role_menu values ('1', '62');
insert into sys_role_menu values ('1', '63');
insert into sys_role_menu values ('1', '64');
insert into sys_role_menu values ('1', '65');
insert into sys_role_menu values ('1', '66');
insert into sys_role_menu values ('1', '67');
insert into sys_role_menu values ('1', '68');
insert into sys_role_menu values ('1', '69');
-- ----------------------------
-- 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 '来源渠道',
login_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_param varchar(255) default '' comment '请求参数',
status int(1) default 0 comment '操作状态 0正常 1异常',
error_msg varchar(2000) default '' comment '错误消息',
oper_time timestamp comment '操作时间',
primary key (oper_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '操作日志记录';
insert into sys_oper_log values(1, '监控管理', '在线用户-强退用户', 'com.ruoyi.project.monitor.online.controller.UserOnlineController()', 'web', 'admin', '研发部门', 'delete.do?id=1', '127.0.0.1', 'JSON参数', 0, '错误描述', '2018-03-01');
-- ----------------------------
-- 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 int(1) default 0 comment '状态0正常 1禁用',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp 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_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '银行数据列表');
insert into sys_dict_type values(2, '支付通道', 'sys_pay_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '支付通道列表');
-- ----------------------------
-- 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 '字典类型',
status int(1) default 0 comment '状态0正常 1禁用',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp 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, '工商银行', '01', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(2, 2, '建设银行', '02', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(3, 3, '农业银行', '03', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(4, 4, '光大银行', '04', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(5, 5, '兴业银行', '05', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(6, 6, '中国银行', '06', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(7, 7, '平安银行', '07', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(8, 8, '招商银行', '08', 'sys_bank_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(9, 1, '微信支付', 'WX', 'sys_pay_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(10, 2, '支付宝', 'ZFB', 'sys_pay_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(11, 3, 'QQ支付', 'JD', 'sys_pay_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
insert into sys_dict_data values(12, 4, '京东支付', 'QQ', 'sys_pay_code', 0, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- ----------------------------
-- 12、系统访问记录
-- ----------------------------
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地址',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
status int(1) default 0 comment '登录状态 0成功 1失败',
msg varchar(255) default '' comment '提示消息',
login_time timestamp comment '访问时间',
primary key (info_id)
) engine=innodb auto_increment=100 default charset=utf8 comment = '系统访问记录';
insert into sys_logininfor values(1, 'admin', '127.0.0.1', 'Chrome 45', 'Windows 7', 0, '登录成功' ,'2018-03-01');
-- ----------------------------
-- 13、在线用户记录
-- ----------------------------
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地址',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
status varchar(10) default '' comment '在线状态on_line在线off_line离线',
start_timestsamp timestamp comment 'session创建时间',
last_access_time timestamp comment 'session最后访问时间',
expire_time int(5) default 0 comment '超时时间,单位为分钟',
primary key (sessionId)
) engine=innodb default charset=utf8 comment = '在线用户记录';
insert into sys_user_online(sessionId, login_name, dept_name, ipaddr, browser, os, status, start_timestsamp, last_access_time)
values('c3b252c3-2229-4be4-a5f7-7aba4b0c314c', 'admin', '研发部门', '127.0.0.1', 'Chrome 45', 'Windows 7', 'on_line', '2018-03-01', '2018-03-01');
-- ----------------------------
-- 14、定时任务调度表
-- ----------------------------
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 int(1) default 0 comment '状态0正常 1暂停',
create_by varchar(64) default '' comment '创建者',
create_time timestamp comment '创建时间',
update_by varchar(64) default '' comment '更新者',
update_time timestamp 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-01', 'ry', '2018-03-01', '');
insert into sys_job values(2, 'ryTask', '系统默认(有参)', 'ryParams', 'ry', '0/20 * * * * ?', 1, 'admin', '2018-03-01', 'ry', '2018-03-01', '');
-- ----------------------------
-- 15、定时任务调度日志表
-- ----------------------------
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 '日志信息',
is_exception int(1) default 0 comment '是否异常',
exception_info text comment '异常信息',
create_time timestamp comment '创建时间',
primary key (job_log_id)
) engine=innodb default charset=utf8 comment = '定时任务调度日志表';

225
pom.xml Normal file
View File

@ -0,0 +1,225 @@
<?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>1.1.1</version>
<packaging>jar</packaging>
<name>RuoYi</name>
<description>若依管理系统</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.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.3.2</shiro.version>
<thymeleaf-extras-shiro.version>1.2.1</thymeleaf-extras-shiro.version>
<mybatis-spring-boot-starter.version>1.1.1</mybatis-spring-boot-starter.version>
<fastjson.version>1.2.31</fastjson.version>
<druid.version>1.0.28</druid.version>
<commons.lang3.version>3.6</commons.lang3.version>
<bitwalker.version>1.19</bitwalker.version>
<lombok.version>1.16.18</lombok.version>
<mybatisplus-spring-boot-starter.version>1.0.4</mybatisplus-spring-boot-starter.version>
<velocity.version>1.7</velocity.version>
<quartz.version>2.3.0</quartz.version>
</properties>
<dependencies>
<!-- SpringBoot 核心包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</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>
<!-- 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>1.2.3</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>
<version>${commons.lang3.version}</version>
</dependency>
<!--io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</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>
<version>${quartz.version}</version>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</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>

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.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
*
*
* @author ruoyi
*/
@SpringBootApplication
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
@MapperScan("com.ruoyi.project.*.*.dao")
public class RuoYiApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.common.constant;
/**
*
*
* @author ruoyi
*/
public class CommonConstant
{
/**
*
*/
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";
}

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", "String");
javaTypeMap.put("datetime", "String");
javaTypeMap.put("timestamp", "String");
}
}

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 int value;
private Status(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
}
}

View File

@ -0,0 +1,40 @@
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";
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.common.constant;
/**
*
*
* @author ruoyi
*/
public class UserConstants
{
/** 正常状态 */
public static final int NORMAL = 0;
/** 异常状态 */
public static final int EXCEPTION = 1;
/** 用户封禁状态 */
public static final int USER_BLOCKED = 1;
/** 角色封禁状态 */
public static final int ROLE_BLOCKED = 1;
/**
*
*/
public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 10;
/** 名称是否唯一的返回结果码 */
public final static String NAME_UNIQUE = "0";
public final static String NAME_NOT_UNIQUE = "1";
/**
*
*/
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
}

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,32 @@
package com.ruoyi.common.exception.base;
/**
* Dao
*
* @author ruoyi
*/
public class DaoException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
*
*/
private String defaultMessage;
public DaoException(String defaultMessage)
{
this.defaultMessage = defaultMessage;
}
public String getDefaultMessage()
{
return defaultMessage;
}
@Override
public String toString()
{
return this.getClass() + "{" + "message='" + getMessage() + '\'' + '}';
}
}

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,65 @@
package com.ruoyi.common.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
*
* @author ruoyi
*/
public class DateUtils
{
public static final String DEFAULT_YYYYMMDD = "yyyyMMddHHmmss";
public static final String DEFAULT_YYYY_MM_DD = "yyyy-MM-dd HH:mm:ss";
/**
* , yyyy-MM-dd
*
* @return String
*/
public static String getDate()
{
return dateTimeNow("yyyy-MM-dd");
}
public static final String dateTimeStr()
{
return dateTimeNow(DEFAULT_YYYY_MM_DD);
}
public static final String dateTimeNow()
{
return dateTimeNow(DEFAULT_YYYYMMDD);
}
public static final String dateTimeNow(final String format)
{
return dateTime(format, new Date());
}
public static final String dateTime(final Date date)
{
return dateTime(DEFAULT_YYYYMMDD, date);
}
public static final String dateTime(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);
}
}
}

View File

@ -0,0 +1,42 @@
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 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,54 @@
package com.ruoyi.common.utils;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
*
*
* @author ruoyi
*/
public class ServletUtils
{
/**
* request
*/
public static HttpServletRequest getHttpServletRequest()
{
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* Ajax
*/
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,301 @@
package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang.text.StrBuilder;
/**
*
*
* @author ruoyi
*/
public class StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
/**
*
*
* @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);
}
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();
}
/**
*
*
* @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.CommonConstant;
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(LogUtils.getBlock(username));
s.append(LogUtils.getBlock(status));
s.append(LogUtils.getBlock(msg));
sys_user_logger.info(s.toString(), args);
if (CommonConstant.LOGIN_SUCCESS.equals(status) || CommonConstant.LOGOUT.equals(status))
{
saveOpLog(username, msg, CommonConstant.SUCCESS);
}
else if (CommonConstant.LOGIN_FAIL.equals(status))
{
saveOpLog(username, msg, CommonConstant.FAIL);
}
}
public static void saveOpLog(String username, String message, String status)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getHttpServletRequest().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.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 praentId)
{
List<Menu> returnList = new ArrayList<Menu>();
for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
{
Menu t = (Menu) iterator.next();
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (t.getParentId() == praentId)
{
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,50 @@
package com.ruoyi.common.utils.security;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import com.ruoyi.project.system.user.domain.User;
/**
* shiro
*
* @author ruoyi
*/
public class ShiroUtils
{
public static Subject getSubjct()
{
return SecurityUtils.getSubject();
}
public static void logout()
{
getSubjct().logout();
}
public static User getUser()
{
return (User) getSubjct().getPrincipal();
}
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,171 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Map;
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.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.UserConstants;
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.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
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);
}
private void handleLog(JoinPoint joinPoint, Exception e)
{
try
{
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// 获取当前的用户
User currentUser = ShiroUtils.getUser();
// *========数据库日志=========*//
OperLog operLog = new OperLog();
operLog.setStatus(UserConstants.NORMAL);
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOperIp(ip);
operLog.setOperUrl(ServletUtils.getHttpServletRequest().getRequestURI());
if (currentUser != null)
{
operLog.setLoginName(currentUser.getLoginName());
operLog.setDeptName(currentUser.getDept().getDeptName());
}
if (e != null)
{
operLog.setStatus(UserConstants.EXCEPTION);
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 static 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 static void setRequestValue(OperLog operLog)
{
Map<String, String[]> map = ServletUtils.getHttpServletRequest().getParameterMap();
String params = JSONObject.toJSONString(map);
operLog.setOperParam(StringUtils.substring(params, 0, 255));
}
/**
*
*/
private static 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,32 @@
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;
/**
*
*
* @author ruoyi
*
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/** 模块 */
String title() default "";
/** 功能 */
String action() default "";
/** 渠道 */
String channel() default "web";
/** 是否保存请求的参数 */
boolean isSaveRequestData() default true;
}

View File

@ -0,0 +1,34 @@
package com.ruoyi.framework.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
*
*
* @author ruoyi
*/
@Configuration
public class BaseConfig extends WebMvcConfigurerAdapter
{
/**
*
*/
@Value("${shiro.user.indexUrl}")
private String indexUrl;
/**
*
*/
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
registry.addViewController("/").setViewName("forward:" + indexUrl);
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers(registry);
}
}

View File

@ -0,0 +1,159 @@
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
*/
@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
*/
@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,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 static void setAuthor(String author)
{
GenConfig.author = author;
}
public static String getPackageName()
{
return packageName;
}
public static void setPackageName(String packageName)
{
GenConfig.packageName = packageName;
}
public static String getAutoRemovePre()
{
return autoRemovePre;
}
public static void setAutoRemovePre(String autoRemovePre)
{
GenConfig.autoRemovePre = autoRemovePre;
}
public static String getTablePrefix()
{
return tablePrefix;
}
public static 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,47 @@
package com.ruoyi.framework.config;
import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
/**
*
*
* @author ruoyi
*/
@Configuration
@Component
public class I18nConfig extends WebMvcConfigurerAdapter
{
@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,52 @@
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;
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;
}
}

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,283 @@
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.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
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.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.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);
// 是否定时检查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);
// 定义要使用的无效的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.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("/js/**", "anon");
filterChainDefinitionMap.put("/ajax/**", "anon");
filterChainDefinitionMap.put("/ruoyi/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
// 不需要拦截的访问
filterChainDefinitionMap.put("/login", "anon");
// 退出 logout地址shiro去清除session
filterChainDefinitionMap.put("/logout", "logout");
// 系统权限列表
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("onlineSession", onlineSessionFilter());
filters.put("syncOnlineSession", syncOnlineSessionFilter());
// 注销成功,则跳转到指定页面
filters.put("logout", logoutFilter());
shiroFilterFactoryBean.setFilters(filters);
// 所有请求需要认证
filterChainDefinitionMap.put("/**", "authc");
// 系统请求记录当前会话
filterChainDefinitionMap.put("/main", "onlineSession,syncOnlineSession");
filterChainDefinitionMap.put("/system/**", "onlineSession,syncOnlineSession");
filterChainDefinitionMap.put("/monitor/**", "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;
}
/**
* 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,265 @@
package com.ruoyi.framework.mybatis;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import javax.xml.bind.PropertyException;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.page.PageUtilEntity;
/**
* SQL
*
* @author ruoyi
*/
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
public class ExecutorPageMethodInterceptor implements Interceptor
{
private static String dialect = ""; // 数据库方言
private static String pageSqlId = ""; // mapper.xml中需要拦截的ID(正则匹配)
@Override
public Object intercept(Invocation ivk) throws Throwable
{
// TODO Auto-generated method stub
if (ivk.getTarget() instanceof RoutingStatementHandler)
{
RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk.getTarget();
BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler,
"delegate");
MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate,
"mappedStatement");
if (mappedStatement.getId().matches(pageSqlId))
{ // 拦截需要分页的SQL
BoundSql boundSql = delegate.getBoundSql();
Object parameterObject = boundSql.getParameterObject();// 分页SQL<select>中parameterType属性对应的实体参数即Mapper接口中执行分页方法的参数,该参数不得为空
if (parameterObject == null)
{
throw new NullPointerException("parameterObject尚未实例化");
}
else
{
Connection connection = (Connection) ivk.getArgs()[0];
String sql = boundSql.getSql();
// String countSql = "select count(0) from (" + sql+ ") as tmp_count"; //记录统计
String countSql = "select count(0) from (" + sql + ") tmp_count"; // 记录统计 == oracle 加 as 报错(SQL
// command not properly ended)
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql,
boundSql.getParameterMappings(), parameterObject);
setParameters(countStmt, mappedStatement, countBS, parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next())
{
count = rs.getInt(1);
}
rs.close();
countStmt.close();
// System.out.println(count);
PageUtilEntity pageUtilEntity = null;
if (parameterObject instanceof PageUtilEntity)
{
// 参数就是Page实体
pageUtilEntity = (PageUtilEntity) parameterObject;
pageUtilEntity.setEntityOrField(true);
pageUtilEntity.setTotalResult(count);
}
else
{
// 参数为某个实体该实体拥有Page属性
Field pageField = ReflectHelper.getFieldByFieldName(parameterObject, "PageUtilEntity");
if (pageField != null)
{
pageUtilEntity = (PageUtilEntity) ReflectHelper.getValueByFieldName(parameterObject, "PageUtilEntity");
if (pageUtilEntity == null)
{
pageUtilEntity = new PageUtilEntity();
}
pageUtilEntity.setEntityOrField(false);
pageUtilEntity.setTotalResult(count);
ReflectHelper.setValueByFieldName(parameterObject, "PageUtilEntity", pageUtilEntity); // 通过反射,对实体对象设置分页对象
}
else
{
throw new NoSuchFieldException(
parameterObject.getClass().getName() + "不存在 pageUtilEntity 属性!");
}
}
String pageSql = generatePageSql(sql, pageUtilEntity);
ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql); // 将分页sql语句反射回BoundSql.
}
}
}
return ivk.proceed();
}
/**
* SQL(?),org.apache.ibatis.executor.parameter.DefaultParameterHandler
*
* @param ps
* @param mappedStatement
* @param boundSql
* @param parameterObject
* @throws SQLException
*/
@SuppressWarnings("unchecked")
private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql,
Object parameterObject) throws SQLException
{
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null)
{
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
for (int i = 0; i < parameterMappings.size(); i++)
{
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT)
{
Object value;
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
if (parameterObject == null)
{
value = null;
}
else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass()))
{
value = parameterObject;
}
else if (boundSql.hasAdditionalParameter(propertyName))
{
value = boundSql.getAdditionalParameter(propertyName);
}
else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX)
&& boundSql.hasAdditionalParameter(prop.getName()))
{
value = boundSql.getAdditionalParameter(prop.getName());
if (value != null)
{
value = configuration.newMetaObject(value)
.getValue(propertyName.substring(prop.getName().length()));
}
}
else
{
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
@SuppressWarnings("rawtypes")
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null)
{
throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName
+ " of statement " + mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
}
/**
* sql
*
* @param sql
* @param page
* @return
*/
private String generatePageSql(String sql, PageUtilEntity pageUtilEntity)
{
if (pageUtilEntity != null && StringUtils.isNotEmpty(dialect))
{
StringBuffer pageSql = new StringBuffer();
if ("mysql".equals(dialect))
{
pageSql.append(sql);
if(StringUtils.isNotEmpty(pageUtilEntity.getOrderByColumn()))
{
pageSql.append(" order by " + pageUtilEntity.getOrderByColumn() + " " + pageUtilEntity.getIsAsc());
}
pageSql.append(" limit " + pageUtilEntity.getPage() + "," + pageUtilEntity.getSize());
}
else if ("oracle".equals(dialect))
{
pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
pageSql.append(sql);
// pageSql.append(") as tmp_tb where ROWNUM<=");
pageSql.append(") tmp_tb where ROWNUM<=");
pageSql.append(pageUtilEntity.getPage() + pageUtilEntity.getSize());
pageSql.append(") where row_id>");
pageSql.append(pageUtilEntity.getPage());
}
return pageSql.toString();
}
else
{
return sql;
}
}
@Override
public Object plugin(Object arg0)
{
return Plugin.wrap(arg0, this);
}
@Override
public void setProperties(Properties p)
{
dialect = p.getProperty("dialect");
if (StringUtils.isEmpty(dialect))
{
try
{
throw new PropertyException("dialect property is not found!");
}
catch (PropertyException e)
{
e.printStackTrace();
}
}
pageSqlId = p.getProperty("pageSqlId");
if (StringUtils.isEmpty(pageSqlId))
{
try
{
throw new PropertyException("pageSqlId property is not found!");
}
catch (PropertyException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,92 @@
package com.ruoyi.framework.mybatis;
import java.lang.reflect.Field;
/**
* SQL
*
* @author ruoyi
*/
public class ReflectHelper
{
/**
* objfieldNameField
*
* @param obj
* @param fieldName
* @return
*/
public static Field getFieldByFieldName(Object obj, String fieldName)
{
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
{
try
{
return superClass.getDeclaredField(fieldName);
}
catch (NoSuchFieldException e)
{
}
}
return null;
}
/**
* objfieldName
*
* @param obj
* @param fieldName
* @return
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static Object getValueByFieldName(Object obj, String fieldName)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
{
Field field = getFieldByFieldName(obj, fieldName);
Object value = null;
if (field != null)
{
if (field.isAccessible())
{
value = field.get(obj);
}
else
{
field.setAccessible(true);
value = field.get(obj);
field.setAccessible(false);
}
}
return value;
}
/**
* objfieldName
*
* @param obj
* @param fieldName
* @param value
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void setValueByFieldName(Object obj, String fieldName, Object value)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
{
Field field = obj.getClass().getDeclaredField(fieldName);
if (field.isAccessible())
{
field.set(obj, value);
}
else
{
field.setAccessible(true);
field.set(obj, value);
field.setAccessible(false);
}
}
}

View File

@ -0,0 +1,111 @@
package com.ruoyi.framework.shiro.realm;
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.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 (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;
}
}

View File

@ -0,0 +1,78 @@
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.CommonConstant;
import com.ruoyi.common.constant.UserConstants;
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.MessageUtils;
import com.ruoyi.common.utils.SystemLogUtils;
import com.ruoyi.project.system.user.domain.User;
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(username) || StringUtils.isEmpty(password))
{
SystemLogUtils.log(username, CommonConstant.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, CommonConstant.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, CommonConstant.LOGIN_FAIL, MessageUtils.message("user.password.not.match"));
throw new UserPasswordNotMatchException();
}
// 查询用户信息
User user = userService.selectUserByName(username);
if (user == null)
{
SystemLogUtils.log(username, CommonConstant.LOGIN_FAIL, MessageUtils.message("user.not.exists"));
throw new UserNotExistsException();
}
passwordService.validate(user, password);
if (UserConstants.USER_BLOCKED == user.getStatus())
{
SystemLogUtils.log(username, CommonConstant.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRefuseDes()));
throw new UserBlockedException(user.getRefuseDes());
}
SystemLogUtils.log(username, CommonConstant.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return user;
}
}

View File

@ -0,0 +1,91 @@
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.CommonConstant;
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, CommonConstant.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount));
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
}
if (!matches(user, password))
{
SystemLogUtils.log(loginName, CommonConstant.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"));
}
}

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,58 @@
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.getHttpServletRequest().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.CommonConstant;
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, CommonConstant.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,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,71 @@
package com.ruoyi.framework.web.controller;
import java.util.List;
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.page.PageDomain;
import com.ruoyi.framework.web.page.PageUtilEntity;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.framework.web.support.TableSupport;
import com.ruoyi.project.system.user.domain.User;
/**
* web
*
* @author ruoyi
*/
public class BaseController
{
/**
*
*/
public PageUtilEntity getPageUtilEntity()
{
PageUtilEntity pageUtilEntity = TableSupport.buildPageRequest();
return pageUtilEntity;
}
/**
*
*/
protected void setPageInfo(Object obj)
{
PageDomain page = (PageDomain) obj;
if (StringUtils.isNotEmpty(page.getPageNum()) && StringUtils.isNotEmpty(page.getPageSize()))
{
int pageNum = Integer.valueOf(page.getPageNum());
int pageSize = Integer.valueOf(page.getPageSize());
String orderBy = page.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 User getUser()
{
return ShiroUtils.getUser();
}
public Long getUserId()
{
return getUser().getUserId();
}
public String getLoginName()
{
return getUser().getLoginName();
}
}

View File

@ -0,0 +1,207 @@
package com.ruoyi.framework.web.dao;
import java.util.List;
import javax.annotation.Resource;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import com.ruoyi.framework.web.page.PageUtilEntity;
import com.ruoyi.framework.web.page.TableDataInfo;
/**
* DAO
*
* @author ruoyi
*/
public class DynamicObjectBaseDao
{
@Resource(name = "sqlSessionTemplate")
private SqlSessionTemplate sqlSessionTemplate;
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int save(String str, Object obj)
{
return sqlSessionTemplate.insert(str, obj);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int batchSave(String str, List<?> objs)
{
return sqlSessionTemplate.insert(str, objs);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int update(String str, Object obj)
{
return sqlSessionTemplate.update(str, obj);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public void batchUpdate(String str, List<?> objs) throws Exception
{
SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
// 批量执行器
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
try
{
if (objs != null)
{
for (int i = 0, size = objs.size(); i < size; i++)
{
sqlSession.update(str, objs.get(i));
}
sqlSession.flushStatements();
sqlSession.commit();
sqlSession.clearCache();
}
}
finally
{
sqlSession.close();
}
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int batchDelete(String str, List<?> objs) throws Exception
{
return sqlSessionTemplate.delete(str, objs);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int batchDelete(String str, Long[] objs)
{
return sqlSessionTemplate.delete(str, objs);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int delete(String str, Object obj)
{
return sqlSessionTemplate.delete(str, obj);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public <T> T findForObject(String str, Object obj)
{
return sqlSessionTemplate.selectOne(str, obj);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public int count(String str, Object obj)
{
return sqlSessionTemplate.selectOne(str, obj);
}
/**
* -
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public <E> List<E> findForList(String str)
{
return sqlSessionTemplate.selectList(str);
}
/**
* -
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public <E> List<E> findForList(String str, Object obj)
{
return sqlSessionTemplate.selectList(str, obj);
}
/**
*
*
* @param str mapper
* @param obj
* @return
* @throws Exception
*/
public TableDataInfo findForList(String str, PageUtilEntity pageUtilEntity)
{
List<?> pageList = sqlSessionTemplate.selectList(str, pageUtilEntity);
TableDataInfo tableDataInfo = new TableDataInfo(pageList, pageUtilEntity.getTotalResult());
return tableDataInfo;
}
public Object findForMap(String str, Object obj, String key, String value) throws Exception
{
return sqlSessionTemplate.selectMap(str, obj, key);
}
}

View File

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

View File

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

View File

@ -0,0 +1,82 @@
package com.ruoyi.framework.web.page;
import com.ruoyi.common.utils.StringUtils;
/**
*
*
* @author ruoyi
*/
public class PageDomain
{
/** 当前记录起始索引 */
private String pageNum;
/** 每页显示记录数 */
private String pageSize;
/** 排序列 */
private String orderByColumn;
/** 排序的方向 "desc" 或者 "asc". */
private String isAsc;
/** 搜索值 */
private String searchValue;
public String getOrderBy()
{
if (StringUtils.isEmpty(orderByColumn))
{
return "";
}
return orderByColumn + " " + isAsc;
}
public String getPageNum()
{
return pageNum;
}
public void setPageNum(String pageNum)
{
this.pageNum = pageNum;
}
public String getPageSize()
{
return pageSize;
}
public void setPageSize(String 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;
}
public String getSearchValue()
{
return searchValue;
}
public void setSearchValue(String searchValue)
{
this.searchValue = searchValue;
}
}

View File

@ -0,0 +1,109 @@
package com.ruoyi.framework.web.page;
import java.util.Map;
/**
*
*
* @author ruoyi
*/
public class PageUtilEntity
{
/** 当前记录起始索引 */
private int page;
/** 每页显示记录数 */
private int size;
/** 排序列 */
private String orderByColumn;
/** 排序的方向 "desc" 或者 "asc". */
private String isAsc;
/** true:需要分页的地方传入的参数就是Page实体false:需要分页的地方传入的参数所代表的实体拥有Page属性 */
private boolean entityOrField;
/** 总记录数 */
private int totalResult;
/** 搜索值 */
private String searchValue;
/** 请求参数 */
protected Map<String, Object> reqMap;
public int getPage()
{
return page;
}
public void setPage(int page)
{
this.page = page;
}
public int getSize()
{
return size;
}
public void setSize(int size)
{
this.size = size;
}
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;
}
public boolean isEntityOrField()
{
return entityOrField;
}
public void setEntityOrField(boolean entityOrField)
{
this.entityOrField = entityOrField;
}
public int getTotalResult()
{
return totalResult;
}
public void setTotalResult(int totalResult)
{
this.totalResult = totalResult;
}
public String getSearchValue()
{
return searchValue;
}
public void setSearchValue(String searchValue)
{
this.searchValue = searchValue;
}
public Map<String, Object> getReqMap()
{
return reqMap;
}
public void setReqMap(Map<String, Object> reqMap)
{
this.reqMap = reqMap;
}
}

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,37 @@
package com.ruoyi.framework.web.support;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.MapDataUtil;
import com.ruoyi.framework.web.page.PageUtilEntity;
/**
*
*
* @author ruoyi
*/
public class TableSupport
{
/**
*
*/
public static PageUtilEntity getPageUtilEntity()
{
HttpServletRequest request = ServletUtils.getHttpServletRequest();
PageUtilEntity pageUtilEntity = new PageUtilEntity();
pageUtilEntity.setPage(Integer.valueOf(request.getParameter("offset")));
pageUtilEntity.setSize(Integer.valueOf(request.getParameter("limit")));
pageUtilEntity.setOrderByColumn(request.getParameter("sort"));
pageUtilEntity.setIsAsc(request.getParameter("order"));
pageUtilEntity.setSearchValue(request.getParameter("search"));
pageUtilEntity.setReqMap(MapDataUtil.convertDataMap(request));
return pageUtilEntity;
}
public static PageUtilEntity buildPageRequest()
{
return getPageUtilEntity();
}
}

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,146 @@
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
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")
@GetMapping("/list")
@ResponseBody
public TableDataInfo list(Job job)
{
setPageInfo(job);
List<Job> list = jobService.selectJobList(job);
return getDataTable(list);
}
/**
*
*/
@Log(title = "监控管理", action = "定时任务-删除调度")
@RequiresPermissions("monitor:job:remove")
@RequestMapping("/remove/{jobId}")
@ResponseBody
public JSON remove(@PathVariable("jobId") Long jobId)
{
Job job = jobService.selectJobById(jobId);
if (job == null)
{
return JSON.error("调度任务不存在");
}
if (jobService.deleteJob(job) > 0)
{
return JSON.ok();
}
return JSON.error();
}
@Log(title = "监控管理", action = "定时任务-批量删除")
@RequiresPermissions("monitor:job:batchRemove")
@PostMapping("/batchRemove")
@ResponseBody
public JSON batchRemove(@RequestParam("ids[]") Long[] ids)
{
try
{
jobService.batchDeleteJob(ids);
return JSON.ok();
}
catch (Exception e)
{
e.printStackTrace();
return JSON.error(e.getMessage());
}
}
/**
*
*/
@Log(title = "监控管理", action = "定时任务-状态修改")
@RequiresPermissions("monitor:job:changeStatus")
@PostMapping("/changeStatus")
@ResponseBody
public JSON changeStatus(Job job)
{
if (jobService.changeStatus(job) > 0)
{
return JSON.ok();
}
return JSON.error();
}
/**
*
*/
@Log(title = "监控管理", action = "定时任务-新增调度")
@RequiresPermissions("monitor:job:add")
@GetMapping("/add")
public String add(Model model)
{
return prefix + "/add";
}
/**
*
*/
@Log(title = "监控管理", action = "定时任务-修改调度")
@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 = "定时任务-保存调度")
@RequiresPermissions("monitor:job:save")
@PostMapping("/save")
@ResponseBody
public JSON save(Job job)
{
if (jobService.saveJobCron(job) > 0)
{
return JSON.ok();
}
return JSON.error();
}
}

View File

@ -0,0 +1,89 @@
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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
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")
@GetMapping("/list")
@ResponseBody
public TableDataInfo list(JobLog jobLog)
{
setPageInfo(jobLog);
List<JobLog> list = jobLogService.selectJobLogList(jobLog);
return getDataTable(list);
}
/**
*
*/
@Log(title = "监控管理", action = "定时任务-删除调度日志")
@RequiresPermissions("monitor:job:remove")
@RequestMapping("/remove/{jobLogId}")
@ResponseBody
public JSON remove(@PathVariable("jobLogId") Long jobLogId)
{
JobLog jobLog = jobLogService.selectJobLogById(jobLogId);
if (jobLog == null)
{
return JSON.error("调度任务不存在");
}
if (jobLogService.deleteJobLogById(jobLogId) > 0)
{
return JSON.ok();
}
return JSON.error();
}
@Log(title = "监控管理", action = "定时任务-批量删除日志")
@RequiresPermissions("monitor:job:batchRemove")
@PostMapping("/batchRemove")
@ResponseBody
public JSON batchRemove(@RequestParam("ids[]") Long[] ids)
{
try
{
jobLogService.batchDeleteJoblog(ids);
return JSON.ok();
}
catch (Exception e)
{
e.printStackTrace();
return JSON.error(e.getMessage());
}
}
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.project.monitor.job.dao;
import java.util.List;
import com.ruoyi.project.monitor.job.domain.Job;
/**
*
*
* @author ruoyi
*/
public interface IJobDao
{
/**
*
*
* @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 batchDeleteJob(Long[] ids);
/**
*
*
* @param job
* @return
*/
public int updateJob(Job job);
/**
*
*
* @param job
* @return
*/
public int insertJob(Job job);
}

View File

@ -0,0 +1,54 @@
package com.ruoyi.project.monitor.job.dao;
import java.util.List;
import com.ruoyi.project.monitor.job.domain.JobLog;
/**
*
*
* @author ruoyi
*/
public interface IJobLogDao
{
/**
* 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 batchDeleteJobLog(Long[] ids);
/**
*
*
* @param jobId ID
* @return
*/
public int deleteJobLogById(Long jobId);
}

View File

@ -0,0 +1,169 @@
package com.ruoyi.project.monitor.job.domain;
import java.io.Serializable;
import com.ruoyi.framework.web.page.PageDomain;
/**
* sys_job
*
* @author ruoyi
*/
public class Job extends PageDomain implements Serializable
{
private static final long serialVersionUID = 1L;
/** 任务ID */
private Long jobId;
/** 任务名称 */
private String jobName;
/** 任务组名 */
private String jobGroup;
/** 任务方法 */
private String methodName;
/** 方法参数 */
private String params;
/** cron执行表达式 */
private String cronExpression;
/** 状态0正常 1暂停 */
private int status;
/** 创建者 */
private String createBy;
/** 创建时间 */
private String createTime;
/** 更新时间 */
private String updateTime;
/** 更新者 */
private String updateBy;
/** 备注 */
private String remark;
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 int getStatus()
{
return status;
}
public void setStatus(int status)
{
this.status = status;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public String getCreateTime()
{
return createTime;
}
public void setCreateTime(String createTime)
{
this.createTime = createTime;
}
public String getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(String updateTime)
{
this.updateTime = updateTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
@Override
public String toString()
{
return "Job [jobId=" + jobId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName=" + methodName
+ ", params=" + params + ", cronExpression=" + cronExpression + ", status=" + status + ", createBy="
+ createBy + ", createTime=" + createTime + ", updateTime=" + updateTime + ", updateBy=" + updateBy
+ ", remark=" + remark + "]";
}
}

View File

@ -0,0 +1,130 @@
package com.ruoyi.project.monitor.job.domain;
import java.util.Date;
import com.ruoyi.framework.web.page.PageDomain;
/**
* sys_job_log
*
* @author ruoyi
*/
public class JobLog extends PageDomain
{
/** ID */
private Integer jobLogId;
/** 任务名称 */
private String jobName;
/** 任务组名 */
private String jobGroup;
/** 任务方法 */
private String methodName;
/** 方法参数 */
private String params;
/** 日志信息 */
private String jobMessage;
/** 是否异常 */
private int isException;
/** 异常信息 */
private String exceptionInfo;
/** 创建时间 */
private Date createTime;
public Integer getJobLogId()
{
return jobLogId;
}
public void setJobLogId(Integer 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 int getIsException()
{
return isException;
}
public void setIsException(int isException)
{
this.isException = isException;
}
public String getExceptionInfo()
{
return exceptionInfo;
}
public void setExceptionInfo(String exceptionInfo)
{
this.exceptionInfo = exceptionInfo;
}
public Date getCreateTime()
{
return createTime;
}
public void setCreateTime(Date createTime)
{
this.createTime = createTime;
}
@Override
public String toString()
{
return "JobLog [jobLogId=" + jobLogId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName="
+ methodName + ", params=" + params + ", jobMessage=" + jobMessage + ", isException=" + isException
+ ", exceptionInfo=" + exceptionInfo + ", createTime=" + createTime + "]";
}
}

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 batchDeleteJoblog(Long[] 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 batchDeleteJob(Long[] ids);
/**
*
*
* @param job
* @return
*/
public int changeStatus(Job job);
/**
*
*
* @param job
* @return
*/
public int triggerJob(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,79 @@
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.project.monitor.job.dao.IJobLogDao;
import com.ruoyi.project.monitor.job.domain.JobLog;
/**
*
*
* @author ruoyi
*/
@Service("jobLogService")
public class JobLogServiceImpl implements IJobLogService
{
@Autowired
private IJobLogDao jobLogDao;
/**
* quartz
*
* @param jobLog
* @return
*/
@Override
public List<JobLog> selectJobLogList(JobLog jobLog)
{
return jobLogDao.selectJobLogList(jobLog);
}
/**
* ID
*
* @param jobId ID
* @return
*/
@Override
public JobLog selectJobLogById(Long jobLogId)
{
return jobLogDao.selectJobLogById(jobLogId);
}
/**
*
*
* @param jobLog
*/
@Override
public void addJobLog(JobLog jobLog)
{
jobLogDao.insertJobLog(jobLog);
}
/**
*
*
* @param ids ID
* @return
*/
@Override
public int batchDeleteJoblog(Long[] ids)
{
return jobLogDao.batchDeleteJobLog(ids);
}
/**
*
*
* @param jobId ID
*/
@Override
public int deleteJobLogById(Long jobId)
{
return jobLogDao.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.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.monitor.job.dao.IJobDao;
import com.ruoyi.project.monitor.job.domain.Job;
import com.ruoyi.project.monitor.job.util.ScheduleUtils;
/**
*
*
* @author ruoyi
*/
@Service("jobService")
public class JobServiceImpl implements IJobService
{
@Autowired
private Scheduler scheduler;
@Autowired
private IJobDao jobDao;
/**
*
*/
@PostConstruct
public void init()
{
List<Job> jobList = jobDao.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 jobDao.selectJobList(job);
}
/**
* ID
*
* @param jobId ID
* @return
*/
@Override
public Job selectJobById(Long jobId)
{
return jobDao.selectJobById(jobId);
}
/**
*
*
* @param job
*/
@Override
public int pauseJob(Job job)
{
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
job.setUpdateBy(ShiroUtils.getLoginName());
int rows = jobDao.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 = jobDao.updateJob(job);
if (rows > 0)
{
ScheduleUtils.resumeJob(scheduler, job.getJobId());
}
return rows;
}
/**
* trigger
*
* @param job
*/
@Override
public int deleteJob(Job job)
{
int rows = jobDao.deleteJobById(job);
if (rows > 0)
{
ScheduleUtils.deleteScheduleJob(scheduler, job.getJobId());
}
return rows;
}
/**
*
*
* @param ids ID
* @return
*/
@Override
public void batchDeleteJob(Long[] ids)
{
for (Long jobId : ids)
{
Job job = jobDao.selectJobById(jobId);
deleteJob(job);
}
}
/**
*
*
* @param job
*/
@Override
public int changeStatus(Job job)
{
int rows = 0;
int status = job.getStatus();
if (status == 0)
{
rows = resumeJob(job);
}
else if (status == 1)
{
rows = pauseJob(job);
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int triggerJob(Job job)
{
int rows = jobDao.updateJob(job);
if (rows > 0)
{
ScheduleUtils.run(scheduler, job);
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int addJobCron(Job job)
{
job.setCreateBy(ShiroUtils.getLoginName());
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
int rows = jobDao.insertJob(job);
if (rows > 0)
{
ScheduleUtils.createScheduleJob(scheduler, job);
}
return rows;
}
/**
*
*
* @param job
*/
@Override
public int updateJobCron(Job job)
{
int rows = jobDao.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,75 @@
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.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.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);
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.setIsException(0);
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.setIsException(1);
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();
}
}
}

View File

@ -0,0 +1,193 @@
package com.ruoyi.project.monitor.job.util;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.ScheduleConstants;
import com.ruoyi.project.monitor.job.domain.Job;
/**
*
*
* @author ruoyi
*
*/
public class ScheduleUtils
{
private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class);
private final static String JOB_NAME = "TASK_";
/**
* key
*/
public static TriggerKey getTriggerKey(Long jobId)
{
return TriggerKey.triggerKey(JOB_NAME + jobId);
}
/**
* jobKey
*/
public static JobKey getJobKey(Long jobId)
{
return JobKey.jobKey(JOB_NAME + jobId);
}
/**
*
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId)
{
try
{
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
return null;
}
/**
*
*/
public static void createScheduleJob(Scheduler scheduler, Job job)
{
try
{
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build();
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId())).withSchedule(scheduleBuilder).build();
// 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.JOB_PARAM_KEY, job);
scheduler.scheduleJob(jobDetail, trigger);
// 暂停任务
if (job.getStatus() == ScheduleConstants.Status.PAUSE.getValue())
{
pauseJob(scheduler, job.getJobId());
}
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
}
/**
*
*/
public static void updateScheduleJob(Scheduler scheduler, Job job)
{
try
{
TriggerKey triggerKey = getTriggerKey(job.getJobId());
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
CronTrigger trigger = getCronTrigger(scheduler, job.getJobId());
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 参数
trigger.getJobDataMap().put(ScheduleConstants.JOB_PARAM_KEY, job);
scheduler.rescheduleJob(triggerKey, trigger);
// 暂停任务
if (job.getStatus() == ScheduleConstants.Status.PAUSE.getValue())
{
pauseJob(scheduler, job.getJobId());
}
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
}
/**
*
*/
public static void run(Scheduler scheduler, Job job)
{
try
{
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.JOB_PARAM_KEY, job);
scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
}
/**
*
*/
public static void pauseJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.pauseJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
}
/**
*
*/
public static void resumeJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.resumeJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
}
/**
*
*/
public static void deleteScheduleJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.deleteJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error(e.getMessage());
}
}
}

View File

@ -0,0 +1,63 @@
package com.ruoyi.project.monitor.logininfor.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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
import com.ruoyi.project.monitor.logininfor.service.ILogininforService;
/**
* 访
*
* @author ruoyi
*/
@Controller
@RequestMapping("/monitor/logininfor")
public class LogininforController extends BaseController
{
private String prefix = "monitor/logininfor";
@Autowired
private ILogininforService logininforService;
@RequiresPermissions("monitor:logininfor:view")
@GetMapping()
public String logininfor()
{
return prefix + "/logininfor";
}
@RequiresPermissions("monitor:logininfor:list")
@GetMapping("/list")
@ResponseBody
public TableDataInfo list(Logininfor logininfor)
{
setPageInfo(logininfor);
List<Logininfor> list = logininforService.selectLogininforList(logininfor);
return getDataTable(list);
}
@RequiresPermissions("monitor:logininfor:batchRemove")
@Log(title = "监控管理", action = "登录日志-批量删除")
@PostMapping("/batchRemove")
@ResponseBody
public JSON batchRemove(@RequestParam("ids[]") Long[] ids)
{
int rows = logininforService.batchDeleteLogininfor(ids);
if (rows > 0)
{
return JSON.ok();
}
return JSON.error();
}
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.project.monitor.logininfor.dao;
import java.util.List;
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
/**
* 访
*
* @author ruoyi
*/
public interface ILogininforDao
{
/**
*
*
* @param logininfor 访
*/
public void insertLogininfor(Logininfor logininfor);
/**
*
*
* @param logininfor 访
* @return
*/
public List<Logininfor> selectLogininforList(Logininfor logininfor);
/**
*
*
* @param ids
* @return
*/
public int batchDeleteLogininfor(Long[] ids);
}

View File

@ -0,0 +1,117 @@
package com.ruoyi.project.monitor.logininfor.domain;
import java.util.Date;
import com.ruoyi.framework.web.page.PageDomain;
/**
* 访 sys_logininfor
*
* @author ruoyi
*/
public class Logininfor extends PageDomain
{
/** ID */
private Integer infoId;
/** 用户账号 */
private String loginName;
/** 登录状态 0成功 1失败 */
private String status;
/** 登录IP地址 */
private String ipaddr;
/** 浏览器类型 */
private String browser;
/** 操作系统 */
private String os;
/** 提示消息 */
private String msg;
/** 访问时间 */
private Date loginTime;
public Integer getInfoId()
{
return infoId;
}
public void setInfoId(Integer infoId)
{
this.infoId = infoId;
}
public String getLoginName()
{
return loginName;
}
public void setLoginName(String loginName)
{
this.loginName = loginName;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getIpaddr()
{
return ipaddr;
}
public void setIpaddr(String ipaddr)
{
this.ipaddr = ipaddr;
}
public String getBrowser()
{
return browser;
}
public void setBrowser(String browser)
{
this.browser = browser;
}
public String getOs()
{
return os;
}
public void setOs(String os)
{
this.os = os;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
public Date getLoginTime()
{
return loginTime;
}
public void setLoginTime(Date loginTime)
{
this.loginTime = loginTime;
}
@Override
public String toString()
{
return "Logininfor [infoId=" + infoId + ", loginName=" + loginName + ", status=" + status + ", ipaddr=" + ipaddr
+ ", browser=" + browser + ", os=" + os + ", msg=" + msg + ", loginTime=" + loginTime + "]";
}
}

View File

@ -0,0 +1,36 @@
package com.ruoyi.project.monitor.logininfor.service;
import java.util.List;
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
/**
* 访
*
* @author ruoyi
*/
public interface ILogininforService
{
/**
*
*
* @param logininfor 访
*/
public void insertLogininfor(Logininfor logininfor);
/**
*
*
* @param logininfor 访
* @return
*/
public List<Logininfor> selectLogininforList(Logininfor logininfor);
/**
*
*
* @param ids
* @return
*/
public int batchDeleteLogininfor(Long[] ids);
}

View File

@ -0,0 +1,55 @@
package com.ruoyi.project.monitor.logininfor.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.project.monitor.logininfor.dao.ILogininforDao;
import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
/**
* 访
*
* @author ruoyi
*/
@Service("logininforService")
public class LogininforServiceImpl implements ILogininforService
{
@Autowired
private ILogininforDao logininforDao;
/**
*
*
* @param logininfor 访
*/
@Override
public void insertLogininfor(Logininfor logininfor)
{
logininforDao.insertLogininfor(logininfor);
}
/**
*
*
* @param logininfor 访
* @return
*/
@Override
public List<Logininfor> selectLogininforList(Logininfor logininfor)
{
return logininforDao.selectLogininforList(logininfor);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int batchDeleteLogininfor(Long[] ids)
{
return logininforDao.batchDeleteLogininfor(ids);
}
}

View File

@ -0,0 +1,103 @@
package com.ruoyi.project.monitor.online.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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
import com.ruoyi.project.monitor.online.domain.UserOnline;
import com.ruoyi.project.monitor.online.service.IUserOnlineService;
/**
* 线
*
* @author ruoyi
*/
@Controller
@RequestMapping("/monitor/online")
public class UserOnlineController extends BaseController
{
private String prefix = "monitor/online";
@Autowired
private IUserOnlineService userOnlineService;
@Autowired
private OnlineSessionDAO onlineSessionDAO;
@RequiresPermissions("monitor:online:view")
@GetMapping()
public String online()
{
return prefix + "/online";
}
@RequiresPermissions("monitor:online:list")
@GetMapping("/list")
@ResponseBody
public TableDataInfo list(UserOnline userOnline)
{
setPageInfo(userOnline);
List<UserOnline> list = userOnlineService.selectUserOnlineList(userOnline);
return getDataTable(list);
}
@RequiresPermissions("monitor:online:batchForceLogout")
@Log(title = "监控管理", action = "在线用户-批量强退用户")
@PostMapping("/batchForceLogout")
@ResponseBody
public JSON batchForceLogout(@RequestParam("ids[]") String[] ids)
{
for (String sessionId : ids)
{
UserOnline online = userOnlineService.selectOnlineById(sessionId);
if (online == null)
{
return JSON.error("用户已下线");
}
OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
if (onlineSession == null)
{
return JSON.error("用户已下线");
}
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
online.setStatus(OnlineSession.OnlineStatus.off_line);
userOnlineService.saveOnline(online);
}
return JSON.ok();
}
@RequiresPermissions("monitor:online:forceLogout")
@Log(title = "监控管理", action = "在线用户-强退用户")
@RequestMapping("/forceLogout/{sessionId}")
@ResponseBody
public JSON forceLogout(@PathVariable("sessionId") String sessionId)
{
UserOnline online = userOnlineService.selectOnlineById(sessionId);
if (online == null)
{
return JSON.error("用户已下线");
}
OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
if (onlineSession == null)
{
return JSON.error("用户已下线");
}
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
online.setStatus(OnlineSession.OnlineStatus.off_line);
userOnlineService.saveOnline(online);
return JSON.ok();
}
}

View File

@ -0,0 +1,52 @@
package com.ruoyi.project.monitor.online.dao;
import java.util.List;
import com.ruoyi.project.monitor.online.domain.UserOnline;
/**
* 线
*
* @author ruoyi
*/
public interface IUserOnlineDao
{
/**
*
*
* @param sessionId ID
* @return 线
*/
public UserOnline selectOnlineById(String sessionId);
/**
*
*
* @param sessionId ID
* @return 线
*/
public int deleteOnlineById(String sessionId);
/**
*
*
* @param online
* @return
*/
public int saveOnline(UserOnline online);
/**
*
*
* @param userOnline
* @return
*/
public List<UserOnline> selectUserOnlineList(UserOnline userOnline);
/**
*
*
* @param lastAccessTime
* @return
*/
public List<UserOnline> selectOnlineByExpired(String lastAccessTime);
}

View File

@ -0,0 +1,155 @@
package com.ruoyi.project.monitor.online.domain;
import org.apache.shiro.session.mgt.SimpleSession;
/**
* 线
*
* @author ruoyi
*/
public class OnlineSession extends SimpleSession
{
private static final long serialVersionUID = 1L;
/** 用户ID */
private Long userId;
/** 用户名称 */
private String loginName;
/** 部门名称 */
private String deptName;
/** 登录IP地址 */
private String host;
/** 浏览器类型 */
private String browser;
/** 操作系统 */
private String os;
/** 在线状态 */
private OnlineStatus status = OnlineStatus.on_line;
/** 属性是否改变 优化session数据同步 */
private transient boolean attributeChanged = false;
@Override
public String getHost()
{
return host;
}
@Override
public void setHost(String host)
{
this.host = host;
}
public String getBrowser()
{
return browser;
}
public void setBrowser(String browser)
{
this.browser = browser;
}
public String getOs()
{
return os;
}
public void setOs(String os)
{
this.os = os;
}
public Long getUserId()
{
return userId;
}
public void setUserId(Long userId)
{
this.userId = userId;
}
public String getLoginName()
{
return loginName;
}
public void setLoginName(String loginName)
{
this.loginName = loginName;
}
public String getDeptName()
{
return deptName;
}
public void setDeptName(String deptName)
{
this.deptName = deptName;
}
public OnlineStatus getStatus()
{
return status;
}
public void setStatus(OnlineStatus status)
{
this.status = status;
}
public void markAttributeChanged()
{
this.attributeChanged = true;
}
public void resetAttributeChanged()
{
this.attributeChanged = false;
}
public boolean isAttributeChanged()
{
return attributeChanged;
}
@Override
public void setAttribute(Object key, Object value)
{
super.setAttribute(key, value);
}
@Override
public Object removeAttribute(Object key)
{
return super.removeAttribute(key);
}
public static enum OnlineStatus
{
/** 用户状态 */
on_line("在线"), off_line("离线");
private final String info;
private OnlineStatus(String info)
{
this.info = info;
}
public String getInfo()
{
return info;
}
}
}

View File

@ -0,0 +1,186 @@
package com.ruoyi.project.monitor.online.domain;
import java.util.Date;
import com.ruoyi.framework.web.page.PageDomain;
import com.ruoyi.project.monitor.online.domain.OnlineSession.OnlineStatus;
/**
* 线 sys_user_online
*
* @author ruoyi
*/
public class UserOnline extends PageDomain
{
/** 用户会话id */
private String sessionId;
/** 部门名称 */
private String deptName;
/** 登录名称 */
private String loginName;
/** 登录IP地址 */
private String ipaddr;
/** 浏览器类型 */
private String browser;
/** 操作系统 */
private String os;
/** session创建时间 */
private Date startTimestamp;
/** session最后访问时间 */
private Date lastAccessTime;
/** 超时时间,单位为分钟 */
private Long expireTime;
/** 在线状态 */
private OnlineStatus status = OnlineStatus.on_line;
/** 备份的当前用户会话 */
private OnlineSession session;
/**
* session
*/
public static final UserOnline fromOnlineSession(OnlineSession session)
{
UserOnline online = new UserOnline();
online.setSessionId(String.valueOf(session.getId()));
online.setDeptName(session.getDeptName());
online.setLoginName(session.getLoginName());
online.setStartTimestamp(session.getStartTimestamp());
online.setLastAccessTime(session.getLastAccessTime());
online.setExpireTime(session.getTimeout());
online.setIpaddr(session.getHost());
online.setBrowser(session.getBrowser());
online.setOs(session.getOs());
online.setStatus(session.getStatus());
online.setSession(session);
return online;
}
public String getSessionId()
{
return sessionId;
}
public void setSessionId(String sessionId)
{
this.sessionId = sessionId;
}
public String getDeptName()
{
return deptName;
}
public void setDeptName(String deptName)
{
this.deptName = deptName;
}
public String getLoginName()
{
return loginName;
}
public void setLoginName(String loginName)
{
this.loginName = loginName;
}
public String getIpaddr()
{
return ipaddr;
}
public void setIpaddr(String ipaddr)
{
this.ipaddr = ipaddr;
}
public String getBrowser()
{
return browser;
}
public void setBrowser(String browser)
{
this.browser = browser;
}
public String getOs()
{
return os;
}
public void setOs(String os)
{
this.os = os;
}
public Date getStartTimestamp()
{
return startTimestamp;
}
public void setStartTimestamp(Date startTimestamp)
{
this.startTimestamp = startTimestamp;
}
public Date getLastAccessTime()
{
return lastAccessTime;
}
public void setLastAccessTime(Date lastAccessTime)
{
this.lastAccessTime = lastAccessTime;
}
public Long getExpireTime()
{
return expireTime;
}
public void setExpireTime(Long expireTime)
{
this.expireTime = expireTime;
}
public OnlineStatus getStatus()
{
return status;
}
public void setStatus(OnlineStatus status)
{
this.status = status;
}
public OnlineSession getSession()
{
return session;
}
public void setSession(OnlineSession session)
{
this.session = session;
}
@Override
public String toString()
{
return "UserOnline [sessionId=" + sessionId + ", deptName=" + deptName + ", loginName=" + loginName
+ ", ipaddr=" + ipaddr + ", browser=" + browser + ", os=" + os + ", startTimestamp=" + startTimestamp
+ ", lastAccessTime=" + lastAccessTime + ", expireTime=" + expireTime + ", status=" + status
+ ", session=" + session + "]";
}
}

View File

@ -0,0 +1,67 @@
package com.ruoyi.project.monitor.online.service;
import java.util.Date;
import java.util.List;
import com.ruoyi.project.monitor.online.domain.UserOnline;
/**
* 线
*
* @author ruoyi
*/
public interface IUserOnlineService
{
/**
*
*
* @param sessionId ID
* @return 线
*/
public UserOnline selectOnlineById(String sessionId);
/**
*
*
* @param sessionId ID
* @return 线
*/
public void deleteOnlineById(String sessionId);
/**
*
*
* @param sessions ID
* @return 线
*/
public void batchDeleteOnline(List<String> sessions);
/**
*
*
* @param online
*/
public void saveOnline(UserOnline online);
/**
*
*
* @param userOnline
* @return
*/
public List<UserOnline> selectUserOnlineList(UserOnline userOnline);
/**
* 退
*
* @param sessionId ID
*/
public void forceLogout(String sessionId);
/**
*
*
* @param expiredDate
* @return
*/
public List<UserOnline> selectOnlineByExpired(Date expiredDate);
}

View File

@ -0,0 +1,124 @@
package com.ruoyi.project.monitor.online.service;
import java.util.Date;
import java.util.List;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.project.monitor.online.dao.IUserOnlineDao;
import com.ruoyi.project.monitor.online.domain.UserOnline;
/**
* 线
*
* @author ruoyi
*/
@Service("userOnlineService")
public class UserOnlineServiceImpl implements IUserOnlineService
{
@Autowired
private IUserOnlineDao userOnlineDao;
@Autowired
private OnlineSessionDAO onlineSessionDAO;
/**
*
*
* @param sessionId ID
* @return 线
*/
@Override
public UserOnline selectOnlineById(String sessionId)
{
return userOnlineDao.selectOnlineById(sessionId);
}
/**
*
*
* @param sessionId ID
* @return 线
*/
@Override
public void deleteOnlineById(String sessionId)
{
UserOnline userOnline = selectOnlineById(sessionId);
if (userOnline != null)
{
userOnlineDao.deleteOnlineById(sessionId);
}
}
/**
*
*
* @param sessions ID
* @return 线
*/
@Override
public void batchDeleteOnline(List<String> sessions)
{
for (String sessionId : sessions)
{
UserOnline userOnline = selectOnlineById(sessionId);
if (userOnline != null)
{
userOnlineDao.deleteOnlineById(sessionId);
}
}
}
/**
*
*
* @param online
*/
@Override
public void saveOnline(UserOnline online)
{
userOnlineDao.saveOnline(online);
}
/**
*
*
* @param pageUtilEntity
*/
@Override
public List<UserOnline> selectUserOnlineList(UserOnline userOnline)
{
return userOnlineDao.selectUserOnlineList(userOnline);
}
/**
* 退
*
* @param sessionId ID
*/
@Override
public void forceLogout(String sessionId)
{
Session session = onlineSessionDAO.readSession(sessionId);
if (session == null)
{
return;
}
session.setTimeout(1000);
userOnlineDao.deleteOnlineById(sessionId);
}
/**
*
*
* @param online
*/
@Override
public List<UserOnline> selectOnlineByExpired(Date expiredDate)
{
String lastAccessTime = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", expiredDate);
return userOnlineDao.selectOnlineByExpired(lastAccessTime);
}
}

View File

@ -0,0 +1,74 @@
package com.ruoyi.project.monitor.operlog.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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
import com.ruoyi.project.monitor.operlog.service.IOperLogService;
/**
*
*
* @author ruoyi
*/
@Controller
@RequestMapping("/monitor/operlog")
public class OperlogController extends BaseController
{
private String prefix = "monitor/operlog";
@Autowired
private IOperLogService operLogService;
@RequiresPermissions("monitor:operlog:view")
@GetMapping()
public String operlog()
{
return prefix + "/operlog";
}
@RequiresPermissions("monitor:operlog:list")
@GetMapping("/list")
@ResponseBody
public TableDataInfo list(OperLog operLog)
{
setPageInfo(operLog);
List<OperLog> list = operLogService.selectOperLogList(operLog);
return getDataTable(list);
}
@RequiresPermissions("monitor:operlog:batchRemove")
@Log(title = "监控管理", action = "操作日志-批量删除")
@PostMapping("/batchRemove")
@ResponseBody
public JSON batchRemove(@RequestParam("ids[]") Long[] ids)
{
int rows = operLogService.batchDeleteOperLog(ids);
if (rows > 0)
{
return JSON.ok();
}
return JSON.error();
}
@RequiresPermissions("monitor:operlog:detail")
@GetMapping("/detail/{operId}")
public String detail(@PathVariable("operId") Long deptId, Model model)
{
OperLog operLog = operLogService.selectOperLogById(deptId);
model.addAttribute("operLog", operLog);
return prefix + "/detail";
}
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.project.monitor.operlog.dao;
import java.util.List;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
/**
*
*
* @author ruoyi
*/
public interface IOperLogDao
{
/**
*
*
* @param operLog
*/
public void insertOperlog(OperLog operLog);
/**
*
*
* @param operLog
* @return
*/
public List<OperLog> selectOperLogList(OperLog operLog);
/**
*
*
* @param ids
* @return
*/
public int batchDeleteOperLog(Long[] ids);
/**
*
*
* @param operId ID
* @return
*/
public OperLog selectOperLogById(Long operId);
}

View File

@ -0,0 +1,179 @@
package com.ruoyi.project.monitor.operlog.domain;
import java.util.Date;
import com.ruoyi.framework.web.page.PageDomain;
/**
* oper_log
*
* @author ruoyi
*/
public class OperLog extends PageDomain
{
/** 日志主键 */
private Integer operId;
/** 模块标题 */
private String title;
/** 功能请求 */
private String action;
/** 请求方法 */
private String method;
/** 来源渠道 */
private String channel;
/** 操作员名称 */
private String loginName;
/** 部门名称 */
private String deptName;
/** 请求url */
private String operUrl;
/** 操作地址 */
private String operIp;
/** 请求参数 */
private String operParam;
/** 状态0正常 1异常 */
private int status;
/** 错误消息 */
private String errorMsg;
/** 操作时间 */
private Date operTime;
public Integer getOperId()
{
return operId;
}
public void setOperId(Integer operId)
{
this.operId = operId;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getAction()
{
return action;
}
public void setAction(String action)
{
this.action = action;
}
public String getMethod()
{
return method;
}
public void setMethod(String method)
{
this.method = method;
}
public String getChannel()
{
return channel;
}
public void setChannel(String channel)
{
this.channel = channel;
}
public String getLoginName()
{
return loginName;
}
public void setLoginName(String loginName)
{
this.loginName = loginName;
}
public String getDeptName()
{
return deptName;
}
public void setDeptName(String deptName)
{
this.deptName = deptName;
}
public String getOperUrl()
{
return operUrl;
}
public void setOperUrl(String operUrl)
{
this.operUrl = operUrl;
}
public String getOperIp()
{
return operIp;
}
public void setOperIp(String operIp)
{
this.operIp = operIp;
}
public String getOperParam()
{
return operParam;
}
public void setOperParam(String operParam)
{
this.operParam = operParam;
}
public int getStatus()
{
return status;
}
public void setStatus(int status)
{
this.status = status;
}
public String getErrorMsg()
{
return errorMsg;
}
public void setErrorMsg(String errorMsg)
{
this.errorMsg = errorMsg;
}
public Date getOperTime()
{
return operTime;
}
public void setOperTime(Date operTime)
{
this.operTime = operTime;
}
@Override
public String toString()
{
return "OperLog [operId=" + operId + ", title=" + title + ", action=" + action + ", method=" + method
+ ", channel=" + channel + ", loginName=" + loginName + ", deptName=" + deptName + ", operUrl="
+ operUrl + ", operIp=" + operIp + ", operParam=" + operParam + ", status=" + status + ", errorMsg="
+ errorMsg + ", operTime=" + operTime + "]";
}
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.project.monitor.operlog.service;
import java.util.List;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
/**
*
*
* @author ruoyi
*/
public interface IOperLogService
{
/**
*
*
* @param operLog
*/
public void insertOperlog(OperLog operLog);
/**
*
*
* @param operLog
* @return
*/
public List<OperLog> selectOperLogList(OperLog operLog);
/**
*
*
* @param ids
* @return
*/
public int batchDeleteOperLog(Long[] ids);
/**
*
*
* @param operId ID
* @return
*/
public OperLog selectOperLogById(Long operId);
}

View File

@ -0,0 +1,66 @@
package com.ruoyi.project.monitor.operlog.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.project.monitor.operlog.dao.IOperLogDao;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
/**
*
*
* @author ruoyi
*/
@Service("operLogService")
public class OperLogServiceImpl implements IOperLogService
{
@Autowired
private IOperLogDao operLogDao;
/**
*
*
* @param operLog
*/
@Override
public void insertOperlog(OperLog operLog)
{
operLogDao.insertOperlog(operLog);
}
/**
*
*
* @param operLog
* @return
*/
@Override
public List<OperLog> selectOperLogList(OperLog operLog)
{
return operLogDao.selectOperLogList(operLog);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int batchDeleteOperLog(Long[] ids)
{
return operLogDao.batchDeleteOperLog(ids);
}
/**
*
*
* @param operId ID
* @return
*/
@Override
public OperLog selectOperLogById(Long operId)
{
return operLogDao.selectOperLogById(operId);
}
}

View File

@ -0,0 +1,151 @@
package com.ruoyi.project.system.dept.controller;
import java.util.List;
import java.util.Map;
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.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.domain.JSON;
import com.ruoyi.project.system.dept.domain.Dept;
import com.ruoyi.project.system.dept.service.IDeptService;
/**
*
*
* @author ruoyi
*/
@Controller
@RequestMapping("/system/dept")
public class DeptController
{
private String prefix = "system/dept";
@Autowired
private IDeptService deptService;
@RequiresPermissions("system:dept:view")
@GetMapping()
public String dept()
{
return prefix + "/dept";
}
@RequiresPermissions("system:dept:list")
@GetMapping("/list")
@ResponseBody
public List<Dept> list()
{
List<Dept> deptList = deptService.selectDeptAll();
return deptList;
}
/**
*
*/
@Log(title = "系统管理", action = "部门管理-修改部门")
@RequiresPermissions("system:dept:edit")
@GetMapping("/edit/{deptId}")
public String edit(@PathVariable("deptId") Long deptId, Model model)
{
Dept dept = deptService.selectDeptById(deptId);
model.addAttribute("dept", dept);
return prefix + "/edit";
}
/**
*
*/
@Log(title = "系统管理", action = "部门管理-新增部门")
@RequiresPermissions("system:dept:add")
@GetMapping("/add/{parentId}")
public String add(@PathVariable("parentId") Long parentId, Model model)
{
Dept dept = deptService.selectDeptById(parentId);
model.addAttribute("dept", dept);
return prefix + "/add";
}
/**
*
*/
@Log(title = "系统管理", action = "部门管理-保存部门")
@RequiresPermissions("system:dept:save")
@PostMapping("/save")
@ResponseBody
public JSON save(Dept dept)
{
if (deptService.saveDept(dept) > 0)
{
return JSON.ok();
}
return JSON.error();
}
/**
*
*/
@Log(title = "系统管理", action = "部门管理-删除部门")
@RequiresPermissions("system:dept:remove")
@GetMapping("/remove/{deptId}")
@ResponseBody
public JSON remove(@PathVariable("deptId") Long deptId)
{
if (deptService.selectDeptCount(deptId) > 0)
{
return JSON.error(1, "存在下级部门,不允许删除");
}
if (deptService.checkDeptExistUser(deptId))
{
return JSON.error(1, "部门存在用户,不允许删除");
}
if (deptService.deleteDeptById(deptId) > 0)
{
return JSON.ok();
}
return JSON.error();
}
/**
*
*/
@PostMapping("/checkDeptNameUnique")
@ResponseBody
public String checkDeptNameUnique(Dept dept)
{
String uniqueFlag = "0";
if (dept != null)
{
uniqueFlag = deptService.checkDeptNameUnique(dept);
}
return uniqueFlag;
}
/**
*
*/
@GetMapping("/selectDeptTree/{deptId}")
public String selectDeptTree(@PathVariable("deptId") Long deptId, Model model)
{
model.addAttribute("treeName", deptService.selectDeptById(deptId).getDeptName());
return prefix + "/tree";
}
/**
*
*/
@GetMapping("/treeData")
@ResponseBody
public List<Map<String, Object>> treeData()
{
List<Map<String, Object>> tree = deptService.selectDeptTree();
return tree;
}
}

View File

@ -0,0 +1,75 @@
package com.ruoyi.project.system.dept.dao;
import java.util.List;
import com.ruoyi.project.system.dept.domain.Dept;
/**
*
*
* @author ruoyi
*/
public interface IDeptDao
{
/**
*
*
* @param dept
* @return
*/
public int selectDeptCount(Dept dept);
/**
*
*
* @param deptId ID
* @return
*/
public int checkDeptExistUser(Long deptId);
/**
*
*
* @return
*/
public List<Dept> selectDeptAll();
/**
*
*
* @param deptId ID
* @return
*/
public int deleteDeptById(Long deptId);
/**
*
*
* @param dept
* @return
*/
public int insertDept(Dept dept);
/**
*
*
* @param dept
* @return
*/
public int updateDept(Dept dept);
/**
* ID
*
* @param deptId ID
* @return
*/
public Dept selectDeptById(Long deptId);
/**
*
*
* @param deptName
* @return
*/
public Dept checkDeptNameUnique(String deptName);
}

View File

@ -0,0 +1,176 @@
package com.ruoyi.project.system.dept.domain;
/**
* sys_dept
*
* @author ruoyi
*/
public class Dept
{
/** 部门ID */
private Long deptId;
/** 父部门ID */
private Long parentId;
/** 部门名称 */
private String deptName;
/** 显示顺序 */
private String orderNum;
/** 负责人 */
private String leader;
/** 联系电话 */
private String phone;
/** 邮箱 */
private String email;
/** 部门状态:0正常,1停用 */
private int status;
/** 父部门名称 */
private String parentName;
/** 创建者 */
private String createBy;
/** 创建时间 */
private String createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private String updateTime;
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public Long getParentId()
{
return parentId;
}
public void setParentId(Long parentId)
{
this.parentId = parentId;
}
public String getDeptName()
{
return deptName;
}
public void setDeptName(String deptName)
{
this.deptName = deptName;
}
public String getOrderNum()
{
return orderNum;
}
public void setOrderNum(String orderNum)
{
this.orderNum = orderNum;
}
public String getLeader()
{
return leader;
}
public void setLeader(String leader)
{
this.leader = leader;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
public int getStatus()
{
return status;
}
public void setStatus(int status)
{
this.status = status;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public String getCreateBy()
{
return createBy;
}
public void setCreateBy(String createBy)
{
this.createBy = createBy;
}
public String getCreateTime()
{
return createTime;
}
public void setCreateTime(String createTime)
{
this.createTime = createTime;
}
public String getUpdateBy()
{
return updateBy;
}
public void setUpdateBy(String updateBy)
{
this.updateBy = updateBy;
}
public String getUpdateTime()
{
return updateTime;
}
public void setUpdateTime(String updateTime)
{
this.updateTime = updateTime;
}
@Override
public String toString()
{
return "Dept [deptId=" + deptId + ", parentId=" + parentId + ", deptName=" + deptName + ", orderNum=" + orderNum
+ ", leader=" + leader + ", phone=" + phone + ", email=" + email + ", status=" + status
+ ", parentName=" + parentName + ", createBy=" + createBy + ", createTime=" + createTime + ", updateBy="
+ updateBy + ", updateTime=" + updateTime + "]";
}
}

View File

@ -0,0 +1,150 @@
package com.ruoyi.project.system.dept.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.system.dept.dao.IDeptDao;
import com.ruoyi.project.system.dept.domain.Dept;
/**
*
*
* @author ruoyi
*/
@Repository("deptService")
public class DeptServiceImpl implements IDeptService
{
@Autowired
private IDeptDao deptDao;
/**
*
*
* @return
*/
@Override
public List<Dept> selectDeptAll()
{
return deptDao.selectDeptAll();
}
/**
*
*
* @return
*/
@Override
public List<Map<String, Object>> selectDeptTree()
{
List<Map<String, Object>> trees = new ArrayList<Map<String, Object>>();
List<Dept> deptList = deptDao.selectDeptAll();
for (Dept dept : deptList)
{
Map<String, Object> deptMap = new HashMap<String, Object>();
deptMap.put("id", dept.getDeptId());
deptMap.put("pId", dept.getParentId());
deptMap.put("name", dept.getDeptName());
trees.add(deptMap);
}
return trees;
}
/**
*
*
* @param parentId ID
* @return
*/
@Override
public int selectDeptCount(Long parentId)
{
Dept dept = new Dept();
dept.setParentId(parentId);
return deptDao.selectDeptCount(dept);
}
/**
*
*
* @param deptId ID
* @return true false
*/
@Override
public boolean checkDeptExistUser(Long deptId)
{
int result = deptDao.checkDeptExistUser(deptId);
return result > 0 ? true : false;
}
/**
*
*
* @param deptId ID
* @return
*/
@Override
public int deleteDeptById(Long deptId)
{
return deptDao.deleteDeptById(deptId);
}
/**
*
*
* @param dept
* @return
*/
@Override
public int saveDept(Dept dept)
{
if (StringUtils.isNotNull(dept.getDeptId()))
{
dept.setUpdateBy(ShiroUtils.getLoginName());
return deptDao.updateDept(dept);
}
else
{
dept.setCreateBy(ShiroUtils.getLoginName());
return deptDao.insertDept(dept);
}
}
/**
* ID
*
* @param deptId ID
* @return
*/
@Override
public Dept selectDeptById(Long deptId)
{
return deptDao.selectDeptById(deptId);
}
/**
*
*
* @param dept
* @return
*/
@Override
public String checkDeptNameUnique(Dept dept)
{
Long deptId = dept.getDeptId();
Dept info = deptDao.checkDeptNameUnique(dept.getDeptName());
if (StringUtils.isNotNull(info) && StringUtils.isNotNull(info.getDeptId())
&& info.getDeptId().longValue() != deptId.longValue())
{
return UserConstants.NAME_NOT_UNIQUE;
}
return UserConstants.NAME_UNIQUE;
}
}

View File

@ -0,0 +1,77 @@
package com.ruoyi.project.system.dept.service;
import java.util.List;
import java.util.Map;
import com.ruoyi.project.system.dept.domain.Dept;
/**
*
*
* @author ruoyi
*/
public interface IDeptService
{
/**
*
*
* @return
*/
public List<Dept> selectDeptAll();
/**
*
*
* @return
*/
public List<Map<String, Object>> selectDeptTree();
/**
*
*
* @param parentId ID
* @return
*/
public int selectDeptCount(Long parentId);
/**
*
*
* @param deptId ID
* @return true false
*/
public boolean checkDeptExistUser(Long deptId);
/**
*
*
* @param deptId ID
* @return
*/
public int deleteDeptById(Long deptId);
/**
*
*
* @param dept
* @return
*/
public int saveDept(Dept dept);
/**
* ID
*
* @param deptId ID
* @return
*/
public Dept selectDeptById(Long deptId);
/**
*
*
* @param dept
* @return
*/
public String checkDeptNameUnique(Dept dept);
}

View File

@ -0,0 +1,127 @@
package com.ruoyi.project.system.dict.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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.system.dict.domain.DictData;
import com.ruoyi.project.system.dict.service.IDictDataService;
/**
*
*
* @author ruoyi
*/
@Controller
@RequestMapping("/system/dict/data")
public class DictDataController extends BaseController
{
private String prefix = "system/dict/data";
@Autowired
private IDictDataService dictDataService;
@RequiresPermissions("system:dict:view")
@GetMapping()
public String dictData()
{
return prefix + "/data";
}
@GetMapping("/list")
@RequiresPermissions("system:dict:list")
@ResponseBody
public TableDataInfo list(DictData dictData)
{
setPageInfo(dictData);
List<DictData> list = dictDataService.selectDictDataList(dictData);
return getDataTable(list);
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-修改字典数据")
@RequiresPermissions("system:dict:edit")
@GetMapping("/edit/{dictCode}")
public String edit(@PathVariable("dictCode") Long dictCode, Model model)
{
DictData dict = dictDataService.selectDictDataById(dictCode);
model.addAttribute("dict", dict);
return prefix + "/edit";
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-新增字典数据")
@RequiresPermissions("system:dict:add")
@GetMapping("/add/{dictType}")
public String add(@PathVariable("dictType") String dictType, Model model)
{
model.addAttribute("dictType", dictType);
return prefix + "/add";
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-保存字典数据")
@RequiresPermissions("system:dict:save")
@PostMapping("/save")
@ResponseBody
public JSON save(DictData dict)
{
if (dictDataService.saveDictData(dict) > 0)
{
return JSON.ok();
}
return JSON.error();
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-删除字典数据")
@RequiresPermissions("system:dict:remove")
@RequestMapping("/remove/{dictCode}")
@ResponseBody
public JSON remove(@PathVariable("dictCode") Long dictCode)
{
DictData dictData = dictDataService.selectDictDataById(dictCode);
if (dictData == null)
{
return JSON.error("字典数据不存在");
}
if (dictDataService.deleteDictDataById(dictCode) > 0)
{
return JSON.ok();
}
return JSON.error();
}
@Log(title = "系统管理", action = "字典类型-批量删除")
@RequiresPermissions("system:dict:batchRemove")
@PostMapping("/batchRemove")
@ResponseBody
public JSON batchRemove(@RequestParam("ids[]") Long[] ids)
{
int rows = dictDataService.batchDeleteDictData(ids);
if (rows > 0)
{
return JSON.ok();
}
return JSON.error();
}
}

View File

@ -0,0 +1,156 @@
package com.ruoyi.project.system.dict.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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.JSON;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.system.dict.domain.DictType;
import com.ruoyi.project.system.dict.service.IDictTypeService;
/**
*
*
* @author ruoyi
*/
@Controller
@RequestMapping("/system/dict")
public class DictTypeController extends BaseController
{
private String prefix = "system/dict/type";
@Autowired
private IDictTypeService dictTypeService;
@RequiresPermissions("system:dict:view")
@GetMapping()
public String dictType()
{
return prefix + "/type";
}
@GetMapping("/list")
@RequiresPermissions("system:dict:list")
@ResponseBody
public TableDataInfo list(DictType dictType)
{
setPageInfo(dictType);
List<DictType> list = dictTypeService.selectDictTypeList(dictType);
return getDataTable(list);
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-修改字典类型")
@RequiresPermissions("system:dict:edit")
@GetMapping("/edit/{dictId}")
public String edit(@PathVariable("dictId") Long dictId, Model model)
{
DictType dict = dictTypeService.selectDictTypeById(dictId);
model.addAttribute("dict", dict);
return prefix + "/edit";
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-新增字典类型")
@RequiresPermissions("system:dict:add")
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-保存字典类型")
@RequiresPermissions("system:dict:save")
@PostMapping("/save")
@ResponseBody
public JSON save(DictType dict)
{
if (dictTypeService.saveDictType(dict) > 0)
{
return JSON.ok();
}
return JSON.error();
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-删除字典类型")
@RequiresPermissions("system:dict:remove")
@RequestMapping("/remove/{dictId}")
@ResponseBody
public JSON remove(@PathVariable("dictId") Long dictId)
{
DictType dictType = dictTypeService.selectDictTypeById(dictId);
if (dictType == null)
{
return JSON.error("字典不存在");
}
if (dictTypeService.deleteDictTypeById(dictId) > 0)
{
return JSON.ok();
}
return JSON.error();
}
@Log(title = "系统管理", action = "字典类型-批量删除")
@RequiresPermissions("system:dict:batchRemove")
@PostMapping("/batchRemove")
@ResponseBody
public JSON batchRemove(@RequestParam("ids[]") Long[] ids)
{
int rows = dictTypeService.batchDeleteDictType(ids);
if (rows > 0)
{
return JSON.ok();
}
return JSON.error();
}
/**
*
*/
@Log(title = "系统管理", action = "字典管理-查询字典数据")
@RequiresPermissions("system:dict:list")
@GetMapping("/detail/{dictId}")
public String detail(@PathVariable("dictId") Long dictId, Model model)
{
DictType dict = dictTypeService.selectDictTypeById(dictId);
model.addAttribute("dict", dict);
return "system/dict/data/data";
}
/**
*
*/
@PostMapping("/checkDictTypeUnique")
@ResponseBody
public String checkDictTypeUnique(DictType dictType)
{
String uniqueFlag = "0";
if (dictType != null)
{
uniqueFlag = dictTypeService.checkDictTypeUnique(dictType);
}
return uniqueFlag;
}
}

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