renren-fast模块

main
lsrong 2 years ago
parent 7055a2fde2
commit 76b64dc45b

@ -16,5 +16,6 @@
<module>mall-coupon</module>
<module>mall-order</module>
<module>mall-product</module>
<module>renren-fast-master</module>
</modules>
</project>

@ -0,0 +1,25 @@
# Compiled class file
*.class
target
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
*.iml
.idea
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

@ -0,0 +1,7 @@
FROM java:8
EXPOSE 8080
VOLUME /tmp
ADD renren-fast.jar /app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-jar","/app.jar"]

@ -0,0 +1,191 @@
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:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
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
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 2019 人人开源
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.

@ -0,0 +1,116 @@
**项目说明**
- renren-fast是一个轻量级的前后端分离的Java快速开发平台能快速开发项目并交付【接私活利器】
- 支持MySQL、Oracle、SQL Server、PostgreSQL等主流数据库
- 前端地址https://gitee.com/renrenio/renren-fast-vue
- 代码生成器https://gitee.com/renrenio/renren-generator
<br>
**具有如下特点**
- 友好的代码结构及注释,便于阅读及二次开发
- 实现前后端分离通过token进行数据交互前端再也不用关注后端技术
- 灵活的权限控制,可控制到页面或按钮,满足绝大部分的权限需求
- 页面交互使用Vue2.x极大的提高了开发效率
- 完善的代码生成机制可在线生成entity、xml、dao、service、vue、sql代码减少70%以上的开发任务
- 引入quartz定时任务可动态完成任务的添加、修改、删除、暂停、恢复及日志查看等功能
- 引入API模板根据token作为登录令牌极大的方便了APP接口开发
- 引入Hibernate Validator校验框架轻松实现后端校验
- 引入云存储服务,已支持:七牛云、阿里云、腾讯云等
- 引入swagger文档支持方便编写API接口文档
<br>
**项目结构**
```
renren-fast
├─db 项目SQL语句
├─common 公共模块
│ ├─aspect 系统日志
│ ├─exception 异常处理
│ ├─validator 后台校验
│ └─xss XSS过滤
├─config 配置信息
├─modules 功能模块
│ ├─app API接口模块(APP调用)
│ ├─job 定时任务模块
│ ├─oss 文件服务模块
│ └─sys 权限模块
├─RenrenApplication 项目启动类
├──resources
│ ├─mapper SQL对应的XML文件
│ └─static 静态资源
```
<br>
**如何交流、反馈、参与贡献?**
- 开发文档https://www.renren.io/guide
- Git仓库https://gitee.com/renrenio/renren-fast
- [人人开源社区](https://www.renren.io/community)https://www.renren.io/community
- 官方QQ群324780204、145799952
- 技术讨论、二次开发等咨询、问题和建议,请移步到人人开源社区,我会在第一时间进行解答和回复!
- 如需关注项目最新动态请Watch、Star项目同时也是对项目最好的支持
- 微信扫码并关注【人人开源】,获得项目最新动态及更新提醒
<br>
![输入图片说明](https://images.gitee.com/uploads/images/2019/0307/090140_260d672d_63154.jpeg "在这里输入图片标题")
<br>
**技术选型:**
- 核心框架Spring Boot 2.1
- 安全框架Apache Shiro 1.4
- 视图框架Spring MVC 5.0
- 持久层框架MyBatis 3.3
- 定时器Quartz 2.3
- 数据库连接池Druid 1.0
- 日志管理SLF4J 1.7、Log4j
- 页面交互Vue2.x
<br>
**后端部署**
- 通过git下载源码
- idea、eclipse需安装lombok插件不然会提示找不到entity的get set方法
- 创建数据库renren_fast数据库编码为UTF-8
- 执行db/mysql.sql文件初始化数据
- 修改application-dev.yml更新MySQL账号和密码
- Eclipse、IDEA运行RenrenApplication.java则可启动项目
- Swagger文档路径http://localhost:8080/renren-fast/swagger/index.html
- Swagger注解路径http://localhost:8080/renren-fast/swagger-ui.html
<br>
**前端部署**
- 本项目是前后端分离的,还需要部署前端,才能运行起来
- 前端下载地址https://gitee.com/renrenio/renren-fast-vue
- 前端部署文档https://gitee.com/renrenio/renren-fast-vue/wikis/Home
- 前端部署完毕就可以访问项目了账号admin密码admin
<br>
**项目演示**
- 演示地址http://demo.open.renren.io/renren-fast
- 账号密码admin/admin
<br>
**接口文档效果图:**
![输入图片说明](https://images.gitee.com/uploads/images/2018/0728/145341_73ba6f75_63154.jpeg "在这里输入图片标题")
<br> <br> <br>
**效果图:**
![输入图片说明](https://gitee.com/uploads/images/2018/0505/173115_d3c045ef_63154.jpeg "在这里输入图片标题")
![输入图片说明](https://gitee.com/uploads/images/2018/0624/225728_b06f72b3_63154.jpeg "在这里输入图片标题")
![输入图片说明](https://gitee.com/uploads/images/2018/0505/173140_79928d91_63154.jpeg "在这里输入图片标题")
![输入图片说明](https://gitee.com/uploads/images/2018/0505/173151_12d065db_63154.jpeg "在这里输入图片标题")
<br>

@ -0,0 +1,356 @@
-- 菜单
CREATE TABLE `sys_menu` (
`menu_id` bigint NOT NULL AUTO_INCREMENT,
`parent_id` bigint COMMENT '父菜单ID一级菜单为0',
`name` varchar(50) COMMENT '菜单名称',
`url` varchar(200) COMMENT '菜单URL',
`perms` varchar(500) COMMENT '授权(多个用逗号分隔user:list,user:create)',
`type` int COMMENT '类型 0目录 1菜单 2按钮',
`icon` varchar(50) COMMENT '菜单图标',
`order_num` int COMMENT '排序',
PRIMARY KEY (`menu_id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='菜单管理';
-- 系统用户
CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(100) COMMENT '密码',
`salt` varchar(20) COMMENT '',
`email` varchar(100) COMMENT '邮箱',
`mobile` varchar(100) COMMENT '手机号',
`status` tinyint COMMENT '状态 0禁用 1正常',
`create_user_id` bigint(20) COMMENT '创建者ID',
`create_time` datetime COMMENT '创建时间',
PRIMARY KEY (`user_id`),
UNIQUE INDEX (`username`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统用户';
-- 系统用户Token
CREATE TABLE `sys_user_token` (
`user_id` bigint(20) NOT NULL,
`token` varchar(100) NOT NULL COMMENT 'token',
`expire_time` datetime DEFAULT NULL COMMENT '过期时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`user_id`),
UNIQUE KEY `token` (`token`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统用户Token';
-- 系统验证码
CREATE TABLE `sys_captcha` (
`uuid` char(36) NOT NULL COMMENT 'uuid',
`code` varchar(6) NOT NULL COMMENT '验证码',
`expire_time` datetime DEFAULT NULL COMMENT '过期时间',
PRIMARY KEY (`uuid`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统验证码';
-- 角色
CREATE TABLE `sys_role` (
`role_id` bigint NOT NULL AUTO_INCREMENT,
`role_name` varchar(100) COMMENT '角色名称',
`remark` varchar(100) COMMENT '备注',
`create_user_id` bigint(20) COMMENT '创建者ID',
`create_time` datetime COMMENT '创建时间',
PRIMARY KEY (`role_id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='角色';
-- 用户与角色对应关系
CREATE TABLE `sys_user_role` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint COMMENT '用户ID',
`role_id` bigint COMMENT '角色ID',
PRIMARY KEY (`id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='用户与角色对应关系';
-- 角色与菜单对应关系
CREATE TABLE `sys_role_menu` (
`id` bigint NOT NULL AUTO_INCREMENT,
`role_id` bigint COMMENT '角色ID',
`menu_id` bigint COMMENT '菜单ID',
PRIMARY KEY (`id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='角色与菜单对应关系';
-- 系统配置信息
CREATE TABLE `sys_config` (
`id` bigint NOT NULL AUTO_INCREMENT,
`param_key` varchar(50) COMMENT 'key',
`param_value` varchar(2000) COMMENT 'value',
`status` tinyint DEFAULT 1 COMMENT '状态 0隐藏 1显示',
`remark` varchar(500) COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE INDEX (`param_key`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统配置信息表';
-- 系统日志
CREATE TABLE `sys_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) COMMENT '用户名',
`operation` varchar(50) COMMENT '用户操作',
`method` varchar(200) COMMENT '请求方法',
`params` varchar(5000) COMMENT '请求参数',
`time` bigint NOT NULL COMMENT '执行时长(毫秒)',
`ip` varchar(64) COMMENT 'IP地址',
`create_date` datetime COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='系统日志';
-- 文件上传
CREATE TABLE `sys_oss` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`url` varchar(200) COMMENT 'URL地址',
`create_date` datetime COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='文件上传';
-- 定时任务
CREATE TABLE `schedule_job` (
`job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务id',
`bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名称',
`params` varchar(2000) DEFAULT NULL COMMENT '参数',
`cron_expression` varchar(100) DEFAULT NULL COMMENT 'cron表达式',
`status` tinyint(4) DEFAULT NULL COMMENT '任务状态 0正常 1暂停',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`job_id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='定时任务';
-- 定时任务日志
CREATE TABLE `schedule_job_log` (
`log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务日志id',
`job_id` bigint(20) NOT NULL COMMENT '任务id',
`bean_name` varchar(200) DEFAULT NULL COMMENT 'spring bean名称',
`params` varchar(2000) DEFAULT NULL COMMENT '参数',
`status` tinyint(4) NOT NULL COMMENT '任务状态 0成功 1失败',
`error` varchar(2000) DEFAULT NULL COMMENT '失败信息',
`times` int(11) NOT NULL COMMENT '耗时(单位:毫秒)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`log_id`),
KEY `job_id` (`job_id`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='定时任务日志';
-- 用户表
CREATE TABLE `tb_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`mobile` varchar(20) NOT NULL COMMENT '手机号',
`password` varchar(64) COMMENT '密码',
`create_time` datetime COMMENT '创建时间',
PRIMARY KEY (`user_id`),
UNIQUE INDEX (`username`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='用户';
-- 初始数据
INSERT INTO `sys_user` (`user_id`, `username`, `password`, `salt`, `email`, `mobile`, `status`, `create_user_id`, `create_time`) VALUES ('1', 'admin', '9ec9750e709431dad22365cabc5c625482e574c74adaebba7dd02f1129e4ce1d', 'YzcmCZNvbXocrsz9dm8e', 'root@renren.io', '13612345678', '1', '1', '2016-11-11 11:11:11');
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (1, 0, '系统管理', NULL, NULL, 0, 'system', 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (2, 1, '管理员列表', 'sys/user', NULL, 1, 'admin', 1);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (3, 1, '角色管理', 'sys/role', NULL, 1, 'role', 2);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (4, 1, '菜单管理', 'sys/menu', NULL, 1, 'menu', 3);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (5, 1, 'SQL监控', 'http://localhost:8080/renren-fast/druid/sql.html', NULL, 1, 'sql', 4);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (6, 1, '定时任务', 'job/schedule', NULL, 1, 'job', 5);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (7, 6, '查看', NULL, 'sys:schedule:list,sys:schedule:info', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (8, 6, '新增', NULL, 'sys:schedule:save', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (9, 6, '修改', NULL, 'sys:schedule:update', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (10, 6, '删除', NULL, 'sys:schedule:delete', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (11, 6, '暂停', NULL, 'sys:schedule:pause', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (12, 6, '恢复', NULL, 'sys:schedule:resume', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (13, 6, '立即执行', NULL, 'sys:schedule:run', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (14, 6, '日志列表', NULL, 'sys:schedule:log', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (15, 2, '查看', NULL, 'sys:user:list,sys:user:info', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (16, 2, '新增', NULL, 'sys:user:save,sys:role:select', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (17, 2, '修改', NULL, 'sys:user:update,sys:role:select', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (18, 2, '删除', NULL, 'sys:user:delete', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (19, 3, '查看', NULL, 'sys:role:list,sys:role:info', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (20, 3, '新增', NULL, 'sys:role:save,sys:menu:list', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (21, 3, '修改', NULL, 'sys:role:update,sys:menu:list', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (22, 3, '删除', NULL, 'sys:role:delete', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (23, 4, '查看', NULL, 'sys:menu:list,sys:menu:info', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (24, 4, '新增', NULL, 'sys:menu:save,sys:menu:select', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (25, 4, '修改', NULL, 'sys:menu:update,sys:menu:select', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (26, 4, '删除', NULL, 'sys:menu:delete', 2, NULL, 0);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (27, 1, '参数管理', 'sys/config', 'sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete', 1, 'config', 6);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (29, 1, '系统日志', 'sys/log', 'sys:log:list', 1, 'log', 7);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`) VALUES (30, 1, '文件上传', 'oss/oss', 'sys:oss:all', 1, 'oss', 6);
INSERT INTO `sys_config` (`param_key`, `param_value`, `status`, `remark`) VALUES ('CLOUD_STORAGE_CONFIG_KEY', '{\"aliyunAccessKeyId\":\"\",\"aliyunAccessKeySecret\":\"\",\"aliyunBucketName\":\"\",\"aliyunDomain\":\"\",\"aliyunEndPoint\":\"\",\"aliyunPrefix\":\"\",\"qcloudBucketName\":\"\",\"qcloudDomain\":\"\",\"qcloudPrefix\":\"\",\"qcloudSecretId\":\"\",\"qcloudSecretKey\":\"\",\"qiniuAccessKey\":\"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ\",\"qiniuBucketName\":\"ios-app\",\"qiniuDomain\":\"http://7xqbwh.dl1.z0.glb.clouddn.com\",\"qiniuPrefix\":\"upload\",\"qiniuSecretKey\":\"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV\",\"type\":1}', '0', '云存储配置信息');
INSERT INTO `schedule_job` (`bean_name`, `params`, `cron_expression`, `status`, `remark`, `create_time`) VALUES ('testTask', 'renren', '0 0/30 * * * ?', '0', '参数测试', now());
-- 账号13612345678 密码admin
INSERT INTO `tb_user` (`username`, `mobile`, `password`, `create_time`) VALUES ('mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', '2017-03-23 22:37:41');
-- quartz自带表结构
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;
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;
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;
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(120) 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;
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;
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),
INDEX (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;
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;
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;
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;
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;
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;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);

@ -0,0 +1,346 @@
-- 菜单
CREATE TABLE sys_menu (
menu_id NUMBER(20, 0) NOT NULL,
parent_id NUMBER(20, 0) NOT NULL,
name varchar2(50),
url varchar2(200),
perms varchar2(500),
type NUMBER(2, 0),
icon varchar2(50),
order_num NUMBER(8, 0),
PRIMARY KEY (menu_id)
);
-- 系统用户
CREATE TABLE sys_user (
user_id NUMBER(20, 0) NOT NULL,
username varchar2(50) NOT NULL,
password varchar2(100),
salt varchar2(20),
email varchar2(100),
mobile varchar2(100),
status NUMBER(2, 0) NOT NULL,
create_user_id NUMBER(20, 0) NOT NULL,
create_time timestamp,
PRIMARY KEY (user_id)
);
CREATE UNIQUE INDEX index_sys_user_username on sys_user(username);
-- 系统用户Token
CREATE TABLE sys_user_token (
user_id NUMBER(20, 0) NOT NULL,
token varchar2(100) NOT NULL,
expire_time timestamp,
update_time timestamp,
PRIMARY KEY (user_id)
);
CREATE UNIQUE INDEX index_token on sys_user_token(token);
-- 系统验证码
CREATE TABLE sys_captcha (
uuid varchar2(36) NOT NULL,
code varchar2(6) NOT NULL,
expire_time timestamp,
PRIMARY KEY (uuid)
);
-- 角色
CREATE TABLE sys_role (
role_id NUMBER(20, 0) NOT NULL,
role_name varchar2(100),
remark varchar2(100),
create_user_id NUMBER(20, 0) NOT NULL,
create_time timestamp,
PRIMARY KEY (role_id)
);
-- 用户与角色对应关系
CREATE TABLE sys_user_role (
id NUMBER(20, 0) NOT NULL,
user_id NUMBER(20, 0) NOT NULL,
role_id NUMBER(20, 0) NOT NULL,
PRIMARY KEY (id)
);
-- 角色与菜单对应关系
CREATE TABLE sys_role_menu (
id NUMBER(20, 0) NOT NULL,
role_id NUMBER(20, 0) NOT NULL,
menu_id NUMBER(20, 0) NOT NULL,
PRIMARY KEY (id)
);
-- 系统配置信息
CREATE TABLE sys_config (
id NUMBER(20, 0) NOT NULL,
param_key varchar2(50),
param_value varchar2(4000),
status NUMBER(2, 0) DEFAULT 1 NOT NULL,
remark varchar2(500),
PRIMARY KEY (id)
);
CREATE UNIQUE INDEX index_param_key on sys_config(param_key);
-- 系统日志
CREATE TABLE sys_log (
id NUMBER(20, 0) NOT NULL,
username varchar2(50),
operation varchar2(50),
method varchar2(200),
params clob,
time NUMBER(20, 0) NOT NULL,
ip varchar2(64),
create_date timestamp,
PRIMARY KEY (id)
);
-- 文件上传
CREATE TABLE sys_oss (
id NUMBER(20, 0) NOT NULL,
url varchar2(200),
create_date timestamp,
PRIMARY KEY (id)
);
-- 定时任务
CREATE TABLE schedule_job (
job_id NUMBER(20, 0) NOT NULL,
bean_name varchar2(200),
params varchar2(2000),
cron_expression varchar2(100),
status NUMBER(2, 0) NOT NULL,
remark varchar2(255),
create_time timestamp,
PRIMARY KEY (job_id)
);
-- 定时任务日志
CREATE TABLE schedule_job_log (
log_id NUMBER(20, 0) NOT NULL,
job_id NUMBER(20, 0) NOT NULL,
bean_name varchar2(200),
params varchar2(2000),
status NUMBER(2, 0) NOT NULL,
error varchar2(2000),
times NUMBER(10, 0) NOT NULL,
create_time timestamp,
PRIMARY KEY (log_id)
);
CREATE INDEX index_job_id on schedule_job_log(job_id);
-- 用户表
CREATE TABLE tb_user (
user_id NUMBER(20, 0) NOT NULL,
username varchar2(50) NOT NULL,
mobile varchar2(20) NOT NULL,
password varchar2(64),
create_time timestamp,
PRIMARY KEY (user_id)
);
CREATE UNIQUE INDEX index_tb_user_username on tb_user(username);
INSERT INTO sys_user (user_id, username, password, salt, email, mobile, status, create_user_id, create_time) VALUES ('1', 'admin', '9ec9750e709431dad22365cabc5c625482e574c74adaebba7dd02f1129e4ce1d', 'YzcmCZNvbXocrsz9dm8e', 'root@renren.io', '13612345678', '1', '1', CURRENT_DATE);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (1, 0, '系统管理', NULL, NULL, 0, 'system', 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (2, 1, '管理员列表', 'sys/user', NULL, 1, 'admin', 1);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (3, 1, '角色管理', 'sys/role', NULL, 1, 'role', 2);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (4, 1, '菜单管理', 'sys/menu', NULL, 1, 'menu', 3);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (5, 1, 'SQL监控', 'http://localhost:8080/renren-fast/druid/sql.html', NULL, 1, 'sql', 4);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (6, 1, '定时任务', 'job/schedule', NULL, 1, 'job', 5);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (7, 6, '查看', NULL, 'sys:schedule:list,sys:schedule:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (8, 6, '新增', NULL, 'sys:schedule:save', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (9, 6, '修改', NULL, 'sys:schedule:update', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (10, 6, '删除', NULL, 'sys:schedule:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (11, 6, '暂停', NULL, 'sys:schedule:pause', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (12, 6, '恢复', NULL, 'sys:schedule:resume', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (13, 6, '立即执行', NULL, 'sys:schedule:run', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (14, 6, '日志列表', NULL, 'sys:schedule:log', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (15, 2, '查看', NULL, 'sys:user:list,sys:user:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (16, 2, '新增', NULL, 'sys:user:save,sys:role:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (17, 2, '修改', NULL, 'sys:user:update,sys:role:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (18, 2, '删除', NULL, 'sys:user:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (19, 3, '查看', NULL, 'sys:role:list,sys:role:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (20, 3, '新增', NULL, 'sys:role:save,sys:menu:list', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (21, 3, '修改', NULL, 'sys:role:update,sys:menu:list', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (22, 3, '删除', NULL, 'sys:role:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (23, 4, '查看', NULL, 'sys:menu:list,sys:menu:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (24, 4, '新增', NULL, 'sys:menu:save,sys:menu:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (25, 4, '修改', NULL, 'sys:menu:update,sys:menu:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (26, 4, '删除', NULL, 'sys:menu:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (27, 1, '参数管理', 'sys/config', 'sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete', 1, 'config', 6);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (29, 1, '系统日志', 'sys/log', 'sys:log:list', 1, 'log', 7);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (30, 1, '文件上传', 'oss/oss', 'sys:oss:all', 1, 'oss', 6);
INSERT INTO sys_config (id, param_key, param_value, status, remark) VALUES (1, 'CLOUD_STORAGE_CONFIG_KEY', '{"aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","aliyunDomain":"","aliyunEndPoint":"","aliyunPrefix":"","qcloudBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuBucketName":"ios-app","qiniuDomain":"http://7xlij2.com1.z0.glb.clouddn.com","qiniuPrefix":"upload","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","type":1}', '0', '云存储配置信息');
INSERT INTO schedule_job (job_id, bean_name, params, cron_expression, status, remark, create_time) VALUES (1, 'testTask', 'renren', '0 0/30 * * * ?', '0', '参数测试', CURRENT_DATE);
-- 账号13612345678 密码admin
INSERT INTO tb_user (user_id, username, mobile, password, create_time) VALUES (1, 'mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', CURRENT_DATE);
-- quartz自带表结构
CREATE TABLE qrtz_job_details
(
SCHED_NAME VARCHAR2(120) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
JOB_CLASS_NAME VARCHAR2(250) NOT NULL,
IS_DURABLE VARCHAR2(1) NOT NULL,
IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE qrtz_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
NEXT_FIRE_TIME NUMBER(13) NULL,
PREV_FIRE_TIME NUMBER(13) NULL,
PRIORITY NUMBER(13) NULL,
TRIGGER_STATE VARCHAR2(16) NOT NULL,
TRIGGER_TYPE VARCHAR2(8) NOT NULL,
START_TIME NUMBER(13) NOT NULL,
END_TIME NUMBER(13) NULL,
CALENDAR_NAME VARCHAR2(200) NULL,
MISFIRE_INSTR NUMBER(2) NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE qrtz_simple_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
REPEAT_COUNT NUMBER(7) NOT NULL,
REPEAT_INTERVAL NUMBER(12) NOT NULL,
TIMES_TRIGGERED NUMBER(10) NOT NULL,
CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_cron_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CRON_EXPRESSION VARCHAR2(120) NOT NULL,
TIME_ZONE_ID VARCHAR2(80),
CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_simprop_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
STR_PROP_1 VARCHAR2(512) NULL,
STR_PROP_2 VARCHAR2(512) NULL,
STR_PROP_3 VARCHAR2(512) NULL,
INT_PROP_1 NUMBER(10) NULL,
INT_PROP_2 NUMBER(10) NULL,
LONG_PROP_1 NUMBER(13) NULL,
LONG_PROP_2 NUMBER(13) NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR2(1) NULL,
BOOL_PROP_2 VARCHAR2(1) NULL,
CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_blob_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
BLOB_DATA BLOB NULL,
CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_calendars
(
SCHED_NAME VARCHAR2(120) NOT NULL,
CALENDAR_NAME VARCHAR2(200) NOT NULL,
CALENDAR BLOB NOT NULL,
CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE qrtz_paused_trigger_grps
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_fired_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
ENTRY_ID VARCHAR2(95) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
FIRED_TIME NUMBER(13) NOT NULL,
SCHED_TIME NUMBER(13) NOT NULL,
PRIORITY NUMBER(13) NOT NULL,
STATE VARCHAR2(16) NOT NULL,
JOB_NAME VARCHAR2(200) NULL,
JOB_GROUP VARCHAR2(200) NULL,
IS_NONCONCURRENT VARCHAR2(1) NULL,
REQUESTS_RECOVERY VARCHAR2(1) NULL,
CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE qrtz_scheduler_state
(
SCHED_NAME VARCHAR2(120) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
LAST_CHECKIN_TIME NUMBER(13) NOT NULL,
CHECKIN_INTERVAL NUMBER(13) NOT NULL,
CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE qrtz_locks
(
SCHED_NAME VARCHAR2(120) NOT NULL,
LOCK_NAME VARCHAR2(40) NOT NULL,
CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);

@ -0,0 +1,364 @@
-- 菜单
CREATE TABLE sys_menu (
menu_id bigserial,
parent_id int8,
name varchar(50),
url varchar(200),
perms varchar(500),
type int,
icon varchar(50),
order_num int,
PRIMARY KEY (menu_id)
);
-- 系统用户
CREATE TABLE sys_user (
user_id bigserial,
username varchar(50) NOT NULL,
password varchar(100),
salt varchar(20),
email varchar(100),
mobile varchar(100),
status int,
create_user_id int8,
create_time timestamp,
PRIMARY KEY (user_id),
UNIQUE (username)
);
-- 系统用户Token
CREATE TABLE sys_user_token (
user_id bigserial,
token varchar(100) NOT NULL,
expire_time timestamp,
update_time timestamp,
PRIMARY KEY (user_id),
UNIQUE (token)
);
-- 系统验证码
CREATE TABLE sys_captcha (
uuid varchar(36) NOT NULL,
code varchar(6) NOT NULL,
expire_time timestamp,
PRIMARY KEY (uuid)
);
-- 角色
CREATE TABLE sys_role (
role_id bigserial,
role_name varchar(100),
remark varchar(100),
create_user_id int8,
create_time timestamp,
PRIMARY KEY (role_id)
);
-- 用户与角色对应关系
CREATE TABLE sys_user_role (
id bigserial,
user_id int8,
role_id int8,
PRIMARY KEY (id)
);
-- 角色与菜单对应关系
CREATE TABLE sys_role_menu (
id bigserial,
role_id int8,
menu_id int8,
PRIMARY KEY (id)
);
-- 系统配置信息
CREATE TABLE sys_config (
id bigserial,
param_key varchar(50),
param_value varchar(2000),
status int DEFAULT 1,
remark varchar(500),
PRIMARY KEY (id),
UNIQUE (param_key)
);
-- 系统日志
CREATE TABLE sys_log (
id bigserial,
username varchar(50),
operation varchar(50),
method varchar(200),
params varchar(5000),
time int8 NOT NULL,
ip varchar(64),
create_date timestamp,
PRIMARY KEY (id)
);
-- 文件上传
CREATE TABLE sys_oss (
id bigserial,
url varchar(200),
create_date timestamp,
PRIMARY KEY (id)
);
-- 定时任务
CREATE TABLE schedule_job (
job_id bigserial,
bean_name varchar(200),
params varchar(2000),
cron_expression varchar(100),
status int,
remark varchar(255),
create_time timestamp,
PRIMARY KEY (job_id)
);
-- 定时任务日志
CREATE TABLE schedule_job_log (
log_id bigserial,
job_id int8 NOT NULL,
bean_name varchar(200),
params varchar(2000),
status int NOT NULL,
error varchar(2000),
times int NOT NULL,
create_time timestamp,
PRIMARY KEY (log_id)
);
CREATE INDEX index_job_id on schedule_job_log(job_id);
-- 用户表
CREATE TABLE tb_user (
user_id bigserial,
username varchar(50) NOT NULL,
mobile varchar(20) NOT NULL,
password varchar(64),
create_time timestamp,
PRIMARY KEY (user_id),
UNIQUE (username)
);
INSERT INTO sys_user (user_id, username, password, salt, email, mobile, status, create_user_id, create_time) VALUES ('1', 'admin', '9ec9750e709431dad22365cabc5c625482e574c74adaebba7dd02f1129e4ce1d', 'YzcmCZNvbXocrsz9dm8e', 'root@renren.io', '13612345678', '1', '1', '2016-11-11 11:11:11');
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (1, 0, '系统管理', NULL, NULL, 0, 'system', 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (2, 1, '管理员列表', 'sys/user', NULL, 1, 'admin', 1);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (3, 1, '角色管理', 'sys/role', NULL, 1, 'role', 2);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (4, 1, '菜单管理', 'sys/menu', NULL, 1, 'menu', 3);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (5, 1, 'SQL监控', 'http://localhost:8080/renren-fast/druid/sql.html', NULL, 1, 'sql', 4);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (6, 1, '定时任务', 'job/schedule', NULL, 1, 'job', 5);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (7, 6, '查看', NULL, 'sys:schedule:list,sys:schedule:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (8, 6, '新增', NULL, 'sys:schedule:save', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (9, 6, '修改', NULL, 'sys:schedule:update', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (10, 6, '删除', NULL, 'sys:schedule:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (11, 6, '暂停', NULL, 'sys:schedule:pause', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (12, 6, '恢复', NULL, 'sys:schedule:resume', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (13, 6, '立即执行', NULL, 'sys:schedule:run', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (14, 6, '日志列表', NULL, 'sys:schedule:log', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (15, 2, '查看', NULL, 'sys:user:list,sys:user:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (16, 2, '新增', NULL, 'sys:user:save,sys:role:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (17, 2, '修改', NULL, 'sys:user:update,sys:role:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (18, 2, '删除', NULL, 'sys:user:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (19, 3, '查看', NULL, 'sys:role:list,sys:role:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (20, 3, '新增', NULL, 'sys:role:save,sys:menu:list', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (21, 3, '修改', NULL, 'sys:role:update,sys:menu:list', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (22, 3, '删除', NULL, 'sys:role:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (23, 4, '查看', NULL, 'sys:menu:list,sys:menu:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (24, 4, '新增', NULL, 'sys:menu:save,sys:menu:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (25, 4, '修改', NULL, 'sys:menu:update,sys:menu:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (26, 4, '删除', NULL, 'sys:menu:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (27, 1, '参数管理', 'sys/config', 'sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete', 1, 'config', 6);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (29, 1, '系统日志', 'sys/log', 'sys:log:list', 1, 'log', 7);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (30, 1, '文件上传', 'oss/oss', 'sys:oss:all', 1, 'oss', 6);
INSERT INTO sys_config (param_key, param_value, status, remark) VALUES ('CLOUD_STORAGE_CONFIG_KEY', '{"aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","aliyunDomain":"","aliyunEndPoint":"","aliyunPrefix":"","qcloudBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuBucketName":"ios-app","qiniuDomain":"http://7xlij2.com1.z0.glb.clouddn.com","qiniuPrefix":"upload","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","type":1}', '0', '云存储配置信息');
INSERT INTO schedule_job (bean_name, params, cron_expression, status, remark, create_time) VALUES ('testTask', 'renren', '0 0/30 * * * ?', '0', '参数测试', '2016-12-01 23:16:46');
-- 账号13612345678 密码admin
INSERT INTO tb_user (username, mobile, password, create_time) VALUES ('mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', '2017-03-23 22:37:41');
alter sequence sys_menu_menu_id_seq restart with 31;
alter sequence sys_user_user_id_seq restart with 2;
-- quartz自带表结构
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 BOOL NOT NULL,
IS_NONCONCURRENT BOOL NOT NULL,
IS_UPDATE_DATA BOOL NOT NULL,
REQUESTS_RECOVERY BOOL NOT NULL,
JOB_DATA BYTEA NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
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 NULL,
PREV_FIRE_TIME BIGINT NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT NOT NULL,
END_TIME BIGINT NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT NULL,
JOB_DATA BYTEA 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)
);
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 NOT NULL,
REPEAT_INTERVAL BIGINT NOT NULL,
TIMES_TRIGGERED BIGINT 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)
);
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(120) 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)
);
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 BOOL NULL,
BOOL_PROP_2 BOOL 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)
);
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 BYTEA 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)
);
CREATE TABLE qrtz_calendars
(
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BYTEA NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE qrtz_paused_trigger_grps
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
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 NOT NULL,
SCHED_TIME BIGINT NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT BOOL NULL,
REQUESTS_RECOVERY BOOL NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE qrtz_scheduler_state
(
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT NOT NULL,
CHECKIN_INTERVAL BIGINT NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE qrtz_locks
(
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
commit;

@ -0,0 +1,512 @@
-- 菜单
CREATE TABLE sys_menu (
menu_id bigint NOT NULL IDENTITY(1,1),
parent_id bigint,
name varchar(50),
url varchar(200),
perms varchar(500),
type int,
icon varchar(50),
order_num int,
PRIMARY KEY (menu_id)
);
-- 系统用户
CREATE TABLE sys_user (
user_id bigint NOT NULL IDENTITY(1,1),
username varchar(50) NOT NULL,
password varchar(100),
salt varchar(20),
email varchar(100),
mobile varchar(100),
status tinyint,
create_user_id bigint,
create_time datetime,
PRIMARY KEY (user_id),
UNIQUE (username)
);
-- 系统用户Token
CREATE TABLE sys_user_token (
user_id bigint NOT NULL,
token varchar(100) NOT NULL,
expire_time datetime,
update_time datetime,
PRIMARY KEY (user_id),
UNIQUE (token)
);
-- 系统验证码
CREATE TABLE sys_captcha (
uuid varchar(36) NOT NULL,
code varchar(6) NOT NULL,
expire_time datetime,
PRIMARY KEY (uuid)
);
-- 角色
CREATE TABLE sys_role (
role_id bigint NOT NULL IDENTITY(1,1),
role_name varchar(100),
remark varchar(100),
create_user_id bigint,
create_time datetime,
PRIMARY KEY (role_id)
);
-- 用户与角色对应关系
CREATE TABLE sys_user_role (
id bigint NOT NULL IDENTITY(1,1),
user_id bigint,
role_id bigint,
PRIMARY KEY (id)
);
-- 角色与菜单对应关系
CREATE TABLE sys_role_menu (
id bigint NOT NULL IDENTITY(1,1),
role_id bigint,
menu_id bigint,
PRIMARY KEY (id)
);
-- 系统配置信息
CREATE TABLE sys_config (
id bigint NOT NULL IDENTITY(1,1),
param_key varchar(50),
param_value varchar(2000),
status tinyint DEFAULT 1,
remark varchar(500),
PRIMARY KEY (id),
UNIQUE (param_key)
);
-- 系统日志
CREATE TABLE sys_log (
id bigint NOT NULL IDENTITY(1,1),
username varchar(50),
operation varchar(50),
method varchar(200),
params varchar(5000),
time bigint NOT NULL,
ip varchar(64),
create_date datetime,
PRIMARY KEY (id)
);
-- 文件上传
CREATE TABLE sys_oss (
id bigint NOT NULL IDENTITY(1,1),
url varchar(200),
create_date datetime,
PRIMARY KEY (id)
);
-- 定时任务
CREATE TABLE schedule_job (
job_id bigint NOT NULL IDENTITY(1,1),
bean_name varchar(200),
params varchar(2000),
cron_expression varchar(100),
status tinyint,
remark varchar(255),
create_time datetime,
PRIMARY KEY (job_id)
);
-- 定时任务日志
CREATE TABLE schedule_job_log (
log_id bigint NOT NULL IDENTITY(1,1),
job_id bigint NOT NULL,
bean_name varchar(200),
params varchar(2000),
status tinyint NOT NULL,
error varchar(2000),
times int NOT NULL,
create_time datetime,
PRIMARY KEY (log_id),
INDEX job_id (job_id)
);
-- 用户表
CREATE TABLE tb_user (
user_id bigint NOT NULL IDENTITY(1,1),
username varchar(50) NOT NULL,
mobile varchar(20) NOT NULL,
password varchar(64),
create_time datetime,
PRIMARY KEY (user_id),
UNIQUE (username)
);
SET IDENTITY_INSERT sys_user ON;
INSERT INTO sys_user (user_id, username, password, salt, email, mobile, status, create_user_id, create_time) VALUES ('1', 'admin', '9ec9750e709431dad22365cabc5c625482e574c74adaebba7dd02f1129e4ce1d', 'YzcmCZNvbXocrsz9dm8e', 'root@renren.io', '13612345678', '1', '1', '2016-11-11 11:11:11');
SET IDENTITY_INSERT sys_user OFF;
SET IDENTITY_INSERT sys_menu ON;
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (1, 0, '系统管理', NULL, NULL, 0, 'system', 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (2, 1, '管理员列表', 'sys/user', NULL, 1, 'admin', 1);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (3, 1, '角色管理', 'sys/role', NULL, 1, 'role', 2);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (4, 1, '菜单管理', 'sys/menu', NULL, 1, 'menu', 3);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (5, 1, 'SQL监控', 'http://localhost:8080/renren-fast/druid/sql.html', NULL, 1, 'sql', 4);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (6, 1, '定时任务', 'job/schedule', NULL, 1, 'job', 5);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (7, 6, '查看', NULL, 'sys:schedule:list,sys:schedule:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (8, 6, '新增', NULL, 'sys:schedule:save', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (9, 6, '修改', NULL, 'sys:schedule:update', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (10, 6, '删除', NULL, 'sys:schedule:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (11, 6, '暂停', NULL, 'sys:schedule:pause', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (12, 6, '恢复', NULL, 'sys:schedule:resume', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (13, 6, '立即执行', NULL, 'sys:schedule:run', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (14, 6, '日志列表', NULL, 'sys:schedule:log', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (15, 2, '查看', NULL, 'sys:user:list,sys:user:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (16, 2, '新增', NULL, 'sys:user:save,sys:role:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (17, 2, '修改', NULL, 'sys:user:update,sys:role:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (18, 2, '删除', NULL, 'sys:user:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (19, 3, '查看', NULL, 'sys:role:list,sys:role:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (20, 3, '新增', NULL, 'sys:role:save,sys:menu:list', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (21, 3, '修改', NULL, 'sys:role:update,sys:menu:list', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (22, 3, '删除', NULL, 'sys:role:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (23, 4, '查看', NULL, 'sys:menu:list,sys:menu:info', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (24, 4, '新增', NULL, 'sys:menu:save,sys:menu:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (25, 4, '修改', NULL, 'sys:menu:update,sys:menu:select', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (26, 4, '删除', NULL, 'sys:menu:delete', 2, NULL, 0);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (27, 1, '参数管理', 'sys/config', 'sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete', 1, 'config', 6);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (29, 1, '系统日志', 'sys/log', 'sys:log:list', 1, 'log', 7);
INSERT INTO sys_menu(menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (30, 1, '文件上传', 'oss/oss', 'sys:oss:all', 1, 'oss', 6);
SET IDENTITY_INSERT sys_menu OFF;
INSERT INTO sys_config (param_key, param_value, status, remark) VALUES ('CLOUD_STORAGE_CONFIG_KEY', '{"aliyunAccessKeyId":"","aliyunAccessKeySecret":"","aliyunBucketName":"","aliyunDomain":"","aliyunEndPoint":"","aliyunPrefix":"","qcloudBucketName":"","qcloudDomain":"","qcloudPrefix":"","qcloudSecretId":"","qcloudSecretKey":"","qiniuAccessKey":"NrgMfABZxWLo5B-YYSjoE8-AZ1EISdi1Z3ubLOeZ","qiniuBucketName":"ios-app","qiniuDomain":"http://7xlij2.com1.z0.glb.clouddn.com","qiniuPrefix":"upload","qiniuSecretKey":"uIwJHevMRWU0VLxFvgy0tAcOdGqasdtVlJkdy6vV","type":1}', '0', '云存储配置信息');
INSERT INTO schedule_job (bean_name, params, cron_expression, status, remark, create_time) VALUES ('testTask', 'renren', '0 0/30 * * * ?', '0', '参数测试', '2016-12-01 23:16:46');
-- 账号13612345678 密码admin
INSERT INTO tb_user (username, mobile, password, create_time) VALUES ('mark', '13612345678', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', '2017-03-23 22:37:41');
-- quartz自带表结构
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_CALENDARS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_LOCKS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_JOB_DETAILS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS]
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
DROP TABLE [dbo].[QRTZ_TRIGGERS]
GO
CREATE TABLE [dbo].[QRTZ_CALENDARS] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[CALENDAR_NAME] [VARCHAR] (200) NOT NULL ,
[CALENDAR] [IMAGE] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [VARCHAR] (200) NOT NULL ,
[TRIGGER_GROUP] [VARCHAR] (200) NOT NULL ,
[CRON_EXPRESSION] [VARCHAR] (120) NOT NULL ,
[TIME_ZONE_ID] [VARCHAR] (80)
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[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] NOT NULL ,
[SCHED_TIME] [BIGINT] 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
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[TRIGGER_GROUP] [VARCHAR] (200) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[INSTANCE_NAME] [VARCHAR] (200) NOT NULL ,
[LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
[CHECKIN_INTERVAL] [BIGINT] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[QRTZ_LOCKS] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[LOCK_NAME] [VARCHAR] (40) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[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] [IMAGE] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [VARCHAR] (200) NOT NULL ,
[TRIGGER_GROUP] [VARCHAR] (200) NOT NULL ,
[REPEAT_COUNT] [BIGINT] NOT NULL ,
[REPEAT_INTERVAL] [BIGINT] NOT NULL ,
[TIMES_TRIGGERED] [BIGINT] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[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,
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
[SCHED_NAME] [VARCHAR] (120) NOT NULL ,
[TRIGGER_NAME] [VARCHAR] (200) NOT NULL ,
[TRIGGER_GROUP] [VARCHAR] (200) NOT NULL ,
[BLOB_DATA] [IMAGE] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[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] NULL ,
[PREV_FIRE_TIME] [BIGINT] NULL ,
[PRIORITY] [INTEGER] NULL ,
[TRIGGER_STATE] [VARCHAR] (16) NOT NULL ,
[TRIGGER_TYPE] [VARCHAR] (8) NOT NULL ,
[START_TIME] [BIGINT] NOT NULL ,
[END_TIME] [BIGINT] NULL ,
[CALENDAR_NAME] [VARCHAR] (200) NULL ,
[MISFIRE_INSTR] [SMALLINT] NULL ,
[JOB_DATA] [IMAGE] NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[CALENDAR_NAME]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[ENTRY_ID]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_GROUP]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[INSTANCE_NAME]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[LOCK_NAME]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE
GO
ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE
GO
ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[QRTZ_TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE
GO
ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
(
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
)
GO

@ -0,0 +1,8 @@
version: '2'
services:
renren-fast:
image: renren/fast
ports:
- "8080:8080"
environment:
- spring.profiles.active=dev

@ -0,0 +1,338 @@
<?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>io.renren</groupId>
<artifactId>renren-fast</artifactId>
<version>3.0.0</version>
<packaging>jar</packaging>
<description>renren-fast</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatisplus.version>3.3.1</mybatisplus.version>
<mysql.version>8.0.28</mysql.version>
<mssql.version>4.0</mssql.version>
<oracle.version>11.2.0.3</oracle.version>
<druid.version>1.1.13</druid.version>
<quartz.version>2.3.0</quartz.version>
<commons.lang.version>2.6</commons.lang.version>
<commons.fileupload.version>1.2.2</commons.fileupload.version>
<commons.io.version>2.5</commons.io.version>
<commons.codec.version>1.10</commons.codec.version>
<commons.configuration.version>1.10</commons.configuration.version>
<shiro.version>1.9.0</shiro.version>
<jwt.version>0.7.0</jwt.version>
<kaptcha.version>0.0.9</kaptcha.version>
<qiniu.version>7.2.23</qiniu.version>
<aliyun.oss.version>2.8.3</aliyun.oss.version>
<qcloud.cos.version>4.4</qcloud.cos.version>
<swagger.version>2.7.0</swagger.version>
<joda.time.version>2.9.9</joda.time.version>
<gson.version>2.8.5</gson.version>
<fastjson.version>1.2.79</fastjson.version>
<hutool.version>4.1.1</hutool.version>
<lombok.version>1.18.4</lombok.version>
<!--wagon plugin 配置-->
<service-path>/work/renren</service-path>
<pack-name>${project.artifactId}-${project.version}.jar</pack-name>
<remote-addr>192.168.1.10:22</remote-addr>
<remote-username>root</remote-username>
<remote-passwd>123456</remote-passwd>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-devtools</artifactId>-->
<!--<optional>true</optional>-->
<!--</dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--oracle驱动-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>${oracle.version}</version>
</dependency>
<!--mssql驱动-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>${mssql.version}</version>
</dependency>
<!--postgresql驱动-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</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>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons.codec.version}</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>${commons.configuration.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>${qiniu.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun.oss.version}</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>${qcloud.cos.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda.time.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<!-- 跳过单元测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<fromFile>target/${pack-name}</fromFile>
<url><![CDATA[scp://${remote-username}:${remote-passwd}@${remote-addr}${service-path}]]></url>
<commands>
<!-- Kill Old Process -->
<command>kill -9 `ps -ef |grep ${project.artifactId}.jar|grep -v "grep" |awk '{print $2}'`</command>
<!-- Restart jar packagewrite result into renren.log -->
<command><![CDATA[nohup java -jar ${service-path}/${pack-name} --spring.profiles.active=test > ${service-path}/renren.log 2>&1 & ]]></command>
<command><![CDATA[netstat -nptl]]></command>
<command><![CDATA[ps -ef | grep java | grep -v grep]]></command>
</commands>
<!-- 运行命令 mvn clean package wagon:upload-single wagon:sshexec-->
<displayCommandOutputs>true</displayCommandOutputs>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.14</version>
<!--<executions>-->
<!--<execution>-->
<!--<phase>package</phase>-->
<!--<goals>-->
<!--<goal>build</goal>-->
<!--</goals>-->
<!--</execution>-->
<!--</executions>-->
<configuration>
<imageName>renren/fast</imageName>
<dockerDirectory>${project.basedir}</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
<!-- 运行命令 mvn clean package docker:build 打包并生成docker镜像 -->
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

@ -0,0 +1,22 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RenrenApplication {
public static void main(String[] args) {
SpringApplication.run(RenrenApplication.class, args);
}
}

@ -0,0 +1,28 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}

@ -0,0 +1,46 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.aspect;
import io.renren.common.exception.RRException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* Redis
*
* @author Mark sunlightcs@gmail.com
*/
@Aspect
@Configuration
public class RedisAspect {
private Logger logger = LoggerFactory.getLogger(getClass());
//是否开启redis缓存 true开启 false关闭
@Value("${spring.redis.open: false}")
private boolean open;
@Around("execution(* io.renren.common.utils.RedisUtils.*(..))")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object result = null;
if(open){
try{
result = point.proceed();
}catch (Exception e){
logger.error("redis error", e);
throw new RRException("Redis服务异常");
}
}
return result;
}
}

@ -0,0 +1,101 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.aspect;
import com.google.gson.Gson;
import io.renren.common.annotation.SysLog;
import io.renren.common.utils.HttpContextUtils;
import io.renren.common.utils.IPUtils;
import io.renren.modules.sys.entity.SysLogEntity;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.sys.service.SysLogService;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Aspect
@Component
public class SysLogAspect {
@Autowired
private SysLogService sysLogService;
@Pointcut("@annotation(io.renren.common.annotation.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLogEntity sysLog = new SysLogEntity();
SysLog syslog = method.getAnnotation(SysLog.class);
if(syslog != null){
//注解上的描述
sysLog.setOperation(syslog.value());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//请求的参数
Object[] args = joinPoint.getArgs();
try{
String params = new Gson().toJson(args);
sysLog.setParams(params);
}catch (Exception e){
}
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
//用户名
String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
sysLog.setUsername(username);
sysLog.setTime(time);
sysLog.setCreateDate(new Date());
//保存系统日志
sysLogService.save(sysLog);
}
}

@ -0,0 +1,61 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.exception;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RRException(String msg) {
super(msg);
this.msg = msg;
}
public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.exception;
import io.renren.common.utils.R;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@RestControllerAdvice
public class RRExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
*
*/
@ExceptionHandler(RRException.class)
public R handleRRException(RRException e){
R r = new R();
r.put("code", e.getCode());
r.put("msg", e.getMessage());
return r;
}
@ExceptionHandler(NoHandlerFoundException.class)
public R handlerNoFoundException(Exception e) {
logger.error(e.getMessage(), e);
return R.error(404, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(DuplicateKeyException.class)
public R handleDuplicateKeyException(DuplicateKeyException e){
logger.error(e.getMessage(), e);
return R.error("数据库中已存在该记录");
}
@ExceptionHandler(AuthorizationException.class)
public R handleAuthorizationException(AuthorizationException e){
logger.error(e.getMessage(), e);
return R.error("没有权限,请联系管理员授权");
}
@ExceptionHandler(Exception.class)
public R handleException(Exception e){
logger.error(e.getMessage(), e);
return R.error();
}
}

@ -0,0 +1,21 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
/**
* Key
*
* @author Mark sunlightcs@gmail.com
*/
public class ConfigConstant {
/**
* KEY
*/
public final static String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
}

@ -0,0 +1,152 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
* <p>
* https://www.renren.io
* <p>
*
*/
package io.renren.common.utils;
import io.renren.common.validator.group.AliyunGroup;
import io.renren.common.validator.group.QcloudGroup;
import io.renren.common.validator.group.QiniuGroup;
import java.util.Optional;
import java.util.stream.Stream;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class Constant {
/**
* ID
*/
public static final int SUPER_ADMIN = 1;
/**
*
*/
public static final String PAGE = "page";
/**
*
*/
public static final String LIMIT = "limit";
/**
*
*/
public static final String ORDER_FIELD = "sidx";
/**
*
*/
public static final String ORDER = "order";
/**
*
*/
public static final String ASC = "asc";
/**
*
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 20161115 1:24:29
*/
public enum MenuType {
/**
*
*/
CATALOG(0),
/**
*
*/
MENU(1),
/**
*
*/
BUTTON(2);
private int value;
MenuType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
*
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016123 12:07:22
*/
public enum ScheduleStatus {
/**
*
*/
NORMAL(0),
/**
*
*/
PAUSE(1);
private int value;
ScheduleStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
*
*/
public enum CloudService {
/**
*
*/
QINIU(1, QiniuGroup.class),
/**
*
*/
ALIYUN(2, AliyunGroup.class),
/**
*
*/
QCLOUD(3, QcloudGroup.class);
private int value;
private Class<?> validatorGroupClass;
CloudService(int value, Class<?> validatorGroupClass) {
this.value = value;
this.validatorGroupClass = validatorGroupClass;
}
public int getValue() {
return value;
}
public Class<?> getValidatorGroupClass() {
return this.validatorGroupClass;
}
public static CloudService getByValue(Integer value) {
Optional<CloudService> first = Stream.of(CloudService.values()).filter(cs -> value.equals(cs.value)).findFirst();
if (!first.isPresent()) {
throw new IllegalArgumentException("非法的枚举值:" + value);
}
return first.get();
}
}
}

@ -0,0 +1,166 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class DateUtils {
/** 时间格式(yyyy-MM-dd) */
public final static String DATE_PATTERN = "yyyy-MM-dd";
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* yyyy-MM-dd
* @param date
* @return yyyy-MM-dd
*/
public static String format(Date date) {
return format(date, DATE_PATTERN);
}
/**
* yyyy-MM-dd
* @param date
* @param pattern DateUtils.DATE_TIME_PATTERN
* @return yyyy-MM-dd
*/
public static String format(Date date, String pattern) {
if(date != null){
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
/**
*
* @param strDate
* @param pattern DateUtils.DATE_TIME_PATTERN
*/
public static Date stringToDate(String strDate, String pattern) {
if (StringUtils.isBlank(strDate)){
return null;
}
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
return fmt.parseLocalDateTime(strDate).toDate();
}
/**
*
* @param week 0-1-212
* @return date[0]date[1]
*/
public static Date[] getWeekStartAndEnd(int week) {
DateTime dateTime = new DateTime();
LocalDate date = new LocalDate(dateTime.plusWeeks(week));
date = date.dayOfWeek().withMinimumValue();
Date beginDate = date.toDate();
Date endDate = date.plusDays(6).toDate();
return new Date[]{beginDate, endDate};
}
/**
* /
*
* @param date
* @param seconds
* @return /
*/
public static Date addDateSeconds(Date date, int seconds) {
DateTime dateTime = new DateTime(date);
return dateTime.plusSeconds(seconds).toDate();
}
/**
* /
*
* @param date
* @param minutes
* @return /
*/
public static Date addDateMinutes(Date date, int minutes) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMinutes(minutes).toDate();
}
/**
* /
*
* @param date
* @param hours
* @return /
*/
public static Date addDateHours(Date date, int hours) {
DateTime dateTime = new DateTime(date);
return dateTime.plusHours(hours).toDate();
}
/**
* /
*
* @param date
* @param days
* @return /
*/
public static Date addDateDays(Date date, int days) {
DateTime dateTime = new DateTime(date);
return dateTime.plusDays(days).toDate();
}
/**
* /
*
* @param date
* @param weeks
* @return /
*/
public static Date addDateWeeks(Date date, int weeks) {
DateTime dateTime = new DateTime(date);
return dateTime.plusWeeks(weeks).toDate();
}
/**
* /
*
* @param date
* @param months
* @return /
*/
public static Date addDateMonths(Date date, int months) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMonths(months).toDate();
}
/**
* /
*
* @param date
* @param years
* @return /
*/
public static Date addDateYears(Date date, int years) {
DateTime dateTime = new DateTime(date);
return dateTime.plusYears(years).toDate();
}
}

@ -0,0 +1,32 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
public static String getDomain(){
HttpServletRequest request = getHttpServletRequest();
StringBuffer url = request.getRequestURL();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
}
public static String getOrigin(){
HttpServletRequest request = getHttpServletRequest();
return request.getHeader("Origin");
}
}

@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import com.alibaba.druid.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
/**
* IP
*
* @author Mark sunlightcs@gmail.com
*/
public class IPUtils {
private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
/**
* IP
*
* 使Nginx request.getRemoteAddr()IP
* 使X-Forwarded-ForIPX-Forwarded-ForunknownIPIP
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
// //使用代理则获取第一个IP地址
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
// if(ip.indexOf(",") > 0) {
// ip = ip.substring(0, ip.indexOf(","));
// }
// }
return ip;
}
}

@ -0,0 +1,26 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import java.util.HashMap;
/**
* Map
*
* @author Mark sunlightcs@gmail.com
*/
public class MapUtils extends HashMap<String, Object> {
@Override
public MapUtils put(String key, Object value) {
super.put(key, value);
return this;
}
}

@ -0,0 +1,110 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class PageUtils implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private int totalCount;
/**
*
*/
private int pageSize;
/**
*
*/
private int totalPage;
/**
*
*/
private int currPage;
/**
*
*/
private List<?> list;
/**
*
* @param list
* @param totalCount
* @param pageSize
* @param currPage
*/
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
this.list = list;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currPage = currPage;
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
}
/**
*
*/
public PageUtils(IPage<?> page) {
this.list = page.getRecords();
this.totalCount = (int)page.getTotal();
this.pageSize = (int)page.getSize();
this.currPage = (int)page.getCurrent();
this.totalPage = (int)page.getPages();
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrPage() {
return currPage;
}
public void setCurrPage(int currPage) {
this.currPage = currPage;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
}

@ -0,0 +1,77 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.renren.common.xss.SQLFilter;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class Query<T> {
public IPage<T> getPage(Map<String, Object> params) {
return this.getPage(params, null, false);
}
public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
//分页参数
long curPage = 1;
long limit = 10;
if(params.get(Constant.PAGE) != null){
curPage = Long.parseLong((String)params.get(Constant.PAGE));
}
if(params.get(Constant.LIMIT) != null){
limit = Long.parseLong((String)params.get(Constant.LIMIT));
}
//分页对象
Page<T> page = new Page<>(curPage, limit);
//分页参数
params.put(Constant.PAGE, page);
//排序字段
//防止SQL注入因为sidx、order是通过拼接SQL实现排序的会有SQL注入风险
String orderField = SQLFilter.sqlInject((String)params.get(Constant.ORDER_FIELD));
String order = (String)params.get(Constant.ORDER);
//前端字段排序
if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){
if(Constant.ASC.equalsIgnoreCase(order)) {
return page.addOrder(OrderItem.asc(orderField));
}else {
return page.addOrder(OrderItem.desc(orderField));
}
}
//没有排序字段,则不排序
if(StringUtils.isBlank(defaultOrderField)){
return page;
}
//默认排序
if(isAsc) {
page.addOrder(OrderItem.asc(defaultOrderField));
}else {
page.addOrder(OrderItem.desc(defaultOrderField));
}
return page;
}
}

@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}

@ -0,0 +1,21 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
/**
* RedisKeys
*
* @author Mark sunlightcs@gmail.com
*/
public class RedisKeys {
public static String getSysConfigKey(String key){
return "sys:config:" + key;
}
}

@ -0,0 +1,99 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* Redis
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ValueOperations<String, String> valueOperations;
@Autowired
private HashOperations<String, String, Object> hashOperations;
@Autowired
private ListOperations<String, Object> listOperations;
@Autowired
private SetOperations<String, Object> setOperations;
@Autowired
private ZSetOperations<String, Object> zSetOperations;
/** 默认过期时长,单位:秒 */
public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
/** 不设置过期时长 */
public final static long NOT_EXPIRE = -1;
private final static Gson gson = new Gson();
public void set(String key, Object value, long expire){
valueOperations.set(key, toJson(value));
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
}
public void set(String key, Object value){
set(key, value, DEFAULT_EXPIRE);
}
public <T> T get(String key, Class<T> clazz, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value == null ? null : fromJson(value, clazz);
}
public <T> T get(String key, Class<T> clazz) {
return get(key, clazz, NOT_EXPIRE);
}
public String get(String key, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value;
}
public String get(String key) {
return get(key, NOT_EXPIRE);
}
public void delete(String key) {
redisTemplate.delete(key);
}
/**
* ObjectJSON
*/
private String toJson(Object object){
if(object instanceof Integer || object instanceof Long || object instanceof Float ||
object instanceof Double || object instanceof Boolean || object instanceof String){
return String.valueOf(object);
}
return gson.toJson(object);
}
/**
* JSONObject
*/
private <T> T fromJson(String json, Class<T> clazz){
return gson.fromJson(json, clazz);
}
}

@ -0,0 +1,61 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import io.renren.common.exception.RRException;
import io.renren.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
/**
* Shiro
*
* @author Mark sunlightcs@gmail.com
*/
public class ShiroUtils {
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
public static SysUserEntity getUserEntity() {
return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
}
public static Long getUserId() {
return getUserEntity().getUserId();
}
public static void setSessionAttribute(Object key, Object value) {
getSession().setAttribute(key, value);
}
public static Object getSessionAttribute(Object key) {
return getSession().getAttribute(key);
}
public static boolean isLogin() {
return SecurityUtils.getSubject().getPrincipal() != null;
}
public static String getKaptcha(String key) {
Object kaptcha = getSessionAttribute(key);
if(kaptcha == null){
throw new RRException("验证码已失效");
}
getSession().removeAttribute(key);
return kaptcha.toString();
}
}

@ -0,0 +1,51 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring Context
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
public static Class<? extends Object> getType(String name) {
return applicationContext.getType(name);
}
}

@ -0,0 +1,32 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator;
import io.renren.common.exception.RRException;
import org.apache.commons.lang.StringUtils;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public abstract class Assert {
public static void isBlank(String str, String message) {
if (StringUtils.isBlank(str)) {
throw new RRException(message);
}
}
public static void isNull(Object object, String message) {
if (object == null) {
throw new RRException(message);
}
}
}

@ -0,0 +1,54 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
* <p>
* https://www.renren.io
* <p>
*
*/
package io.renren.common.validator;
import io.renren.common.exception.RRException;
import io.renren.common.utils.Constant;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
/**
* hibernate-validator
*
* http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/
*
* @author Mark sunlightcs@gmail.com
*/
public class ValidatorUtils {
private static Validator validator;
static {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
/**
*
* @param object
* @param groups
* @throws RRException RRException
*/
public static void validateEntity(Object object, Class<?>... groups)
throws RRException {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
StringBuilder msg = new StringBuilder();
for (ConstraintViolation<Object> constraint : constraintViolations) {
msg.append(constraint.getMessage()).append("<br>");
}
throw new RRException(msg.toString());
}
}
public static void validateEntity(Object object, Constant.CloudService type) {
validateEntity(object, type.getValidatorGroupClass());
}
}

@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator.group;
/**
* Group
*
* @author Mark sunlightcs@gmail.com
*/
public interface AddGroup {
}

@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator.group;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface AliyunGroup {
}

@ -0,0 +1,21 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator.group;
import javax.validation.GroupSequence;
/**
* AddGroupUpdateGroup
*
* @author Mark sunlightcs@gmail.com
*/
@GroupSequence({AddGroup.class, UpdateGroup.class})
public interface Group {
}

@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator.group;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface QcloudGroup {
}

@ -0,0 +1,17 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator.group;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface QiniuGroup {
}

@ -0,0 +1,19 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.validator.group;
/**
* Group
*
* @author Mark sunlightcs@gmail.com
*/
public interface UpdateGroup {
}

@ -0,0 +1,530 @@
package io.renren.common.xss;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* HTML filtering utility for protecting against XSS (Cross Site Scripting).
*
* This code is licensed LGPLv3
*
* This code is a Java port of the original work in PHP by Cal Hendersen.
* http://code.iamcal.com/php/lib_filter/
*
* The trickiest part of the translation was handling the differences in regex handling
* between PHP and Java. These resources were helpful in the process:
*
* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
* http://www.regular-expressions.info/modifiers.html
*
* A note on naming conventions: instance variables are prefixed with a "v"; global
* constants are in all caps.
*
* Sample use:
* String input = ...
* String clean = new HTMLFilter().filter( input );
*
* The class is not thread safe. Create a new instance if in doubt.
*
* If you find bugs or have suggestions on improvement (especially regarding
* performance), please contact us. The latest version of this
* source, and our contact details, can be found at http://xss-html-filter.sf.net
*
* @author Joseph O'Connell
* @author Cal Hendersen
* @author Michael Semb Wever
*/
public final class HTMLFilter {
/** regex flag union representing /si modifiers in php **/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("<");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String,Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();
private static final ConcurrentMap<String,Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();
/** set of allowed html elements, along with allowed attributes for each element **/
private final Map<String, List<String>> vAllowed;
/** counts of open tags for each (allowable) html element **/
private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();
/** html elements which must always be self-closing (e.g. "<img />") **/
private final String[] vSelfClosingTags;
/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/
private final String[] vNeedClosingTags;
/** set of disallowed html elements **/
private final String[] vDisallowed;
/** attributes which should be checked for valid protocols **/
private final String[] vProtocolAtts;
/** allowed protocols **/
private final String[] vAllowedProtocols;
/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/
private final String[] vRemoveBlanks;
/** entities allowed within html markup **/
private final String[] vAllowedEntities;
/** flag determining whether comments are allowed in input String. */
private final boolean stripComment;
private final boolean encodeQuotes;
private boolean vDebug = false;
/**
* flag determining whether to try to make tags when presented with "unbalanced"
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false,
* unbalanced angle brackets will be html escaped.
*/
private final boolean alwaysMakeTags;
/** Default constructor.
*
*/
public HTMLFilter() {
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<String>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<String>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<String>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[]{"img"};
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
vDisallowed = new String[]{};
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
vProtocolAtts = new String[]{"src", "href"};
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = true;
}
/** Set debug flag to true. Otherwise use default settings. See the default constructor.
*
* @param debug turn debug on with a true argument
*/
public HTMLFilter(final boolean debug) {
this();
vDebug = debug;
}
/** Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
public HTMLFilter(final Map<String,Object> conf) {
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset() {
vTagCounts.clear();
}
private void debug(final String msg) {
if (vDebug) {
Logger.getAnonymousLogger().info(msg);
}
}
//---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal) {
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s) {
String result = s;
result = regexReplace(P_AMP, "&amp;", result);
result = regexReplace(P_QUOTE, "&quot;", result);
result = regexReplace(P_LEFT_ARROW, "&lt;", result);
result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
return result;
}
//---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted
* html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input) {
reset();
String s = input;
debug("************************************************");
debug(" INPUT: " + input);
s = escapeComments(s);
debug(" escapeComments: " + s);
s = balanceHTML(s);
debug(" balanceHTML: " + s);
s = checkTags(s);
debug(" checkTags: " + s);
s = processRemoveBlanks(s);
debug("processRemoveBlanks: " + s);
s = validateEntities(s);
debug(" validateEntites: " + s);
debug("************************************************\n\n");
return s;
}
public boolean isAlwaysMakeTags(){
return alwaysMakeTags;
}
public boolean isStripComments(){
return stripComment;
}
private String escapeComments(final String s) {
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find()) {
final String match = m.group(1); //(.*?)
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s) {
if (alwaysMakeTags) {
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
} else {
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s) {
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find()) {
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
s = buf.toString();
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
for (String key : vTagCounts.keySet()) {
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
s += "</" + key + ">";
}
}
return s;
}
private String processRemoveBlanks(final String s) {
String result = s;
for (String tag : vRemoveBlanks) {
if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s) {
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
if (allowed(name)) {
if (!inArray(name, vSelfClosingTags)) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name)) {
String params = "";
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<String>();
final List<String> paramValues = new ArrayList<String>();
while (m2.find()) {
paramNames.add(m2.group(1)); //([a-z0-9]+)
paramValues.add(m2.group(3)); //(.*?)
}
while (m3.find()) {
paramNames.add(m3.group(1)); //([a-z0-9]+)
paramValues.add(m3.group(3)); //([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++) {
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName)) {
if (inArray(paramName, vProtocolAtts)) {
paramValue = processParamProtocol(paramValue);
}
params += " " + paramName + "=\"" + paramValue + "\"";
}
}
if (inArray(name, vSelfClosingTags)) {
ending = " /";
}
if (inArray(name, vNeedClosingTags)) {
ending = "";
}
if (ending == null || ending.length() < 1) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) + 1);
} else {
vTagCounts.put(name, 1);
}
} else {
ending = " /";
}
return "<" + name + params + ending + ">";
} else {
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find()) {
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s) {
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find()) {
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols)) {
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1, s.length());
if (s.startsWith("#//")) {
s = "#" + s.substring(3, s.length());
}
}
}
return s;
}
private String decodeEntities(String s) {
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.decode(match).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s) {
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find()) {
final String one = m.group(1); //([^&;]*)
final String two = m.group(2); //(?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s){
if(encodeQuotes){
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find()) {
final String one = m.group(1); //(>|^)
final String two = m.group(2); //([^<]+?)
final String three = m.group(3); //(<|$)
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, "&quot;", two) + three));
}
m.appendTail(buf);
return buf.toString();
}else{
return s;
}
}
private String checkEntity(final String preamble, final String term) {
return ";".equals(term) && isValidEntity(preamble)
? '&' + preamble
: "&amp;" + preamble;
}
private boolean isValidEntity(final String entity) {
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array) {
for (String item : array) {
if (item != null && item.equals(s)) {
return true;
}
}
return false;
}
private boolean allowed(final String name) {
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName) {
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}

@ -0,0 +1,50 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.xss;
import io.renren.common.exception.RRException;
import org.apache.commons.lang.StringUtils;
/**
* SQL
*
* @author Mark sunlightcs@gmail.com
*/
public class SQLFilter {
/**
* SQL
* @param str
*/
public static String sqlInject(String str){
if(StringUtils.isBlank(str)){
return null;
}
//去掉'|"|;|\字符
str = StringUtils.replace(str, "'", "");
str = StringUtils.replace(str, "\"", "");
str = StringUtils.replace(str, ";", "");
str = StringUtils.replace(str, "\\", "");
//转换成小写
str = str.toLowerCase();
//非法字符
String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};
//判断是否包含非法字符
for(String keyword : keywords){
if(str.indexOf(keyword) != -1){
throw new RRException("包含非法字符");
}
}
return str;
}
}

@ -0,0 +1,37 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.xss;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* XSS
*
* @author Mark sunlightcs@gmail.com
*/
public class XssFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
(HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
@Override
public void destroy() {
}
}

@ -0,0 +1,147 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.common.xss;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* XSS
*
* @author Mark sunlightcs@gmail.com
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
//没被包装过的HttpServletRequest特殊场景需要自己过滤
HttpServletRequest orgRequest;
//html过滤
private final static HTMLFilter htmlFilter = new HTMLFilter();
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
orgRequest = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
//非json类型直接返回
if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){
return super.getInputStream();
}
//为空,直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (StringUtils.isBlank(json)) {
return super.getInputStream();
}
//xss过滤
json = xssEncode(json);
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bis.read();
}
};
}
@Override
public String getParameter(String name) {
String value = super.getParameter(xssEncode(name));
if (StringUtils.isNotBlank(value)) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] parameters = super.getParameterValues(name);
if (parameters == null || parameters.length == 0) {
return null;
}
for (int i = 0; i < parameters.length; i++) {
parameters[i] = xssEncode(parameters[i]);
}
return parameters;
}
@Override
public Map<String,String[]> getParameterMap() {
Map<String,String[]> map = new LinkedHashMap<>();
Map<String,String[]> parameters = super.getParameterMap();
for (String key : parameters.keySet()) {
String[] values = parameters.get(key);
for (int i = 0; i < values.length; i++) {
values[i] = xssEncode(values[i]);
}
map.put(key, values);
}
return map;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(xssEncode(name));
if (StringUtils.isNotBlank(value)) {
value = xssEncode(value);
}
return value;
}
private String xssEncode(String input) {
return htmlFilter.filter(input);
}
/**
* request
*/
public HttpServletRequest getOrgRequest() {
return orgRequest;
}
/**
* request
*/
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
if (request instanceof XssHttpServletRequestWrapper) {
return ((XssHttpServletRequestWrapper) request).getOrgRequest();
}
return request;
}
}

@ -0,0 +1,26 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}

@ -0,0 +1,49 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import io.renren.common.xss.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.DispatcherType;
/**
* Filter
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean shiroFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
//该值缺省为false表示生命周期由SpringApplicationContext管理设置为true则表示由ServletContainer管理
registration.addInitParameter("targetFilterLifecycle", "true");
registration.setEnabled(true);
registration.setOrder(Integer.MAX_VALUE - 1);
registration.addUrlPatterns("/*");
return registration;
}
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
}

@ -0,0 +1,39 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha producer() {
Properties properties = new Properties();
properties.put("kaptcha.border", "no");
properties.put("kaptcha.textproducer.font.color", "black");
properties.put("kaptcha.textproducer.char.space", "5");
properties.put("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

@ -0,0 +1,31 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mybatis-plus
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class MybatisPlusConfig {
/**
*
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}

@ -0,0 +1,63 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory factory;
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}

@ -0,0 +1,81 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import io.renren.modules.sys.oauth2.OAuth2Filter;
import io.renren.modules.sys.oauth2.OAuth2Realm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Shiro
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class ShiroConfig {
@Bean("securityManager")
public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(oAuth2Realm);
securityManager.setRememberMeManager(null);
return securityManager;
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
//oauth过滤
Map<String, Filter> filters = new HashMap<>();
filters.put("oauth2", new OAuth2Filter());
shiroFilter.setFilters(filters);
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/webjars/**", "anon");
filterMap.put("/druid/**", "anon");
filterMap.put("/app/**", "anon");
filterMap.put("/sys/login", "anon");
filterMap.put("/swagger/**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/captcha.jpg", "anon");
filterMap.put("/aaa.txt", "anon");
filterMap.put("/**", "oauth2");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}

@ -0,0 +1,61 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
@Configuration
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//加了ApiOperation注解的类才生成接口文档
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//包下的类,才生成接口文档
//.apis(RequestHandlerSelectors.basePackage("io.renren.controller"))
.paths(PathSelectors.any())
.build()
.securitySchemes(security());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("人人开源")
.description("renren-fast文档")
.termsOfServiceUrl("https://www.renren.io")
.version("3.0.0")
.build();
}
private List<ApiKey> security() {
return newArrayList(
new ApiKey("token", "token", "header")
);
}
}

@ -0,0 +1,24 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.annotation;
import java.lang.annotation.*;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource {
String value() default "";
}

@ -0,0 +1,71 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.aspect;
import io.renren.datasource.annotation.DataSource;
import io.renren.datasource.config.DynamicContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
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.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DataSourceAspect {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(io.renren.datasource.annotation.DataSource) " +
"|| @within(io.renren.datasource.annotation.DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Class targetClass = point.getTarget().getClass();
Method method = signature.getMethod();
DataSource targetDataSource = (DataSource)targetClass.getAnnotation(DataSource.class);
DataSource methodDataSource = method.getAnnotation(DataSource.class);
if(targetDataSource != null || methodDataSource != null){
String value;
if(methodDataSource != null){
value = methodDataSource.value();
}else {
value = targetDataSource.value();
}
DynamicContextHolder.push(value);
logger.debug("set datasource is {}", value);
}
try {
return point.proceed();
} finally {
DynamicContextHolder.poll();
logger.debug("clean datasource");
}
}
}

@ -0,0 +1,57 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.config;
import java.util.ArrayDeque;
import java.util.Deque;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class DynamicContextHolder {
@SuppressWarnings("unchecked")
private static final ThreadLocal<Deque<String>> CONTEXT_HOLDER = new ThreadLocal() {
@Override
protected Object initialValue() {
return new ArrayDeque();
}
};
/**
* 线
*
* @return
*/
public static String peek() {
return CONTEXT_HOLDER.get().peek();
}
/**
* 线
*
* @param dataSource
*/
public static void push(String dataSource) {
CONTEXT_HOLDER.get().push(dataSource);
}
/**
* 线
*/
public static void poll() {
Deque<String> deque = CONTEXT_HOLDER.get();
deque.poll();
if (deque.isEmpty()) {
CONTEXT_HOLDER.remove();
}
}
}

@ -0,0 +1,25 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicContextHolder.peek();
}
}

@ -0,0 +1,63 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.renren.datasource.properties.DataSourceProperties;
import io.renren.datasource.properties.DynamicDataSourceProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
public class DynamicDataSourceConfig {
@Autowired
private DynamicDataSourceProperties properties;
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DynamicDataSource dynamicDataSource(DataSourceProperties dataSourceProperties) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(getDynamicDataSource());
//默认数据源
DruidDataSource defaultDataSource = DynamicDataSourceFactory.buildDruidDataSource(dataSourceProperties);
dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);
return dynamicDataSource;
}
private Map<Object, Object> getDynamicDataSource(){
Map<String, DataSourceProperties> dataSourcePropertiesMap = properties.getDatasource();
Map<Object, Object> targetDataSources = new HashMap<>(dataSourcePropertiesMap.size());
dataSourcePropertiesMap.forEach((k, v) -> {
DruidDataSource druidDataSource = DynamicDataSourceFactory.buildDruidDataSource(v);
targetDataSources.put(k, druidDataSource);
});
return targetDataSources;
}
}

@ -0,0 +1,54 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.renren.datasource.properties.DataSourceProperties;
import java.sql.SQLException;
/**
* DruidDataSource
*
* @author Mark sunlightcs@gmail.com
* @since 1.0.0
*/
public class DynamicDataSourceFactory {
public static DruidDataSource buildDruidDataSource(DataSourceProperties properties) {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(properties.getDriverClassName());
druidDataSource.setUrl(properties.getUrl());
druidDataSource.setUsername(properties.getUsername());
druidDataSource.setPassword(properties.getPassword());
druidDataSource.setInitialSize(properties.getInitialSize());
druidDataSource.setMaxActive(properties.getMaxActive());
druidDataSource.setMinIdle(properties.getMinIdle());
druidDataSource.setMaxWait(properties.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
druidDataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(properties.getValidationQuery());
druidDataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout());
druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
druidDataSource.setTestOnReturn(properties.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
druidDataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements());
druidDataSource.setSharePreparedStatements(properties.isSharePreparedStatements());
try {
druidDataSource.setFilters(properties.getFilters());
druidDataSource.init();
} catch (SQLException e) {
e.printStackTrace();
}
return druidDataSource;
}
}

@ -0,0 +1,202 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.properties;
/**
*
*
* @author Mark sunlightcs@gmail.com
* @since 1.0.0
*/
public class DataSourceProperties {
private String driverClassName;
private String url;
private String username;
private String password;
/**
* Druid
*/
private int initialSize = 2;
private int maxActive = 10;
private int minIdle = -1;
private long maxWait = 60 * 1000L;
private long timeBetweenEvictionRunsMillis = 60 * 1000L;
private long minEvictableIdleTimeMillis = 1000L * 60L * 30L;
private long maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7;
private String validationQuery = "select 1";
private int validationQueryTimeout = -1;
private boolean testOnBorrow = false;
private boolean testOnReturn = false;
private boolean testWhileIdle = true;
private boolean poolPreparedStatements = false;
private int maxOpenPreparedStatements = -1;
private boolean sharePreparedStatements = false;
private String filters = "stat,wall";
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getInitialSize() {
return initialSize;
}
public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public long getMaxWait() {
return maxWait;
}
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
public long getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
public long getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
public long getMaxEvictableIdleTimeMillis() {
return maxEvictableIdleTimeMillis;
}
public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
}
public String getValidationQuery() {
return validationQuery;
}
public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
}
public int getValidationQueryTimeout() {
return validationQueryTimeout;
}
public void setValidationQueryTimeout(int validationQueryTimeout) {
this.validationQueryTimeout = validationQueryTimeout;
}
public boolean isTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
public boolean isTestOnReturn() {
return testOnReturn;
}
public void setTestOnReturn(boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
public boolean isTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
public boolean isPoolPreparedStatements() {
return poolPreparedStatements;
}
public void setPoolPreparedStatements(boolean poolPreparedStatements) {
this.poolPreparedStatements = poolPreparedStatements;
}
public int getMaxOpenPreparedStatements() {
return maxOpenPreparedStatements;
}
public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) {
this.maxOpenPreparedStatements = maxOpenPreparedStatements;
}
public boolean isSharePreparedStatements() {
return sharePreparedStatements;
}
public void setSharePreparedStatements(boolean sharePreparedStatements) {
this.sharePreparedStatements = sharePreparedStatements;
}
public String getFilters() {
return filters;
}
public void setFilters(String filters) {
this.filters = filters;
}
}

@ -0,0 +1,33 @@
/**
* Copyright (c) 2018 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.datasource.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.LinkedHashMap;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
* @since 1.0.0
*/
@ConfigurationProperties(prefix = "dynamic")
public class DynamicDataSourceProperties {
private Map<String, DataSourceProperties> datasource = new LinkedHashMap<>();
public Map<String, DataSourceProperties> getDatasource() {
return datasource;
}
public void setDatasource(Map<String, DataSourceProperties> datasource) {
this.datasource = datasource;
}
}

@ -0,0 +1,22 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.annotation;
import java.lang.annotation.*;
/**
* app
*
* @author Mark sunlightcs@gmail.com
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Login {
}

@ -0,0 +1,25 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}

@ -0,0 +1,42 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.config;
import io.renren.modules.app.interceptor.AuthorizationInterceptor;
import io.renren.modules.app.resolver.LoginUserHandlerMethodArgumentResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* MVC
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AuthorizationInterceptor authorizationInterceptor;
@Autowired
private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authorizationInterceptor).addPathPatterns("/app/**");
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
}
}

@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.controller;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.modules.app.form.LoginForm;
import io.renren.modules.app.service.UserService;
import io.renren.modules.app.utils.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* APP
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("/app")
@Api("APP登录接口")
public class AppLoginController {
@Autowired
private UserService userService;
@Autowired
private JwtUtils jwtUtils;
/**
*
*/
@PostMapping("login")
@ApiOperation("登录")
public R login(@RequestBody LoginForm form){
//表单校验
ValidatorUtils.validateEntity(form);
//用户登录
long userId = userService.login(form);
//生成token
String token = jwtUtils.generateToken(userId);
Map<String, Object> map = new HashMap<>();
map.put("token", token);
map.put("expire", jwtUtils.getExpire());
return R.ok(map);
}
}

@ -0,0 +1,55 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.controller;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.modules.app.entity.UserEntity;
import io.renren.modules.app.form.RegisterForm;
import io.renren.modules.app.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("/app")
@Api("APP注册接口")
public class AppRegisterController {
@Autowired
private UserService userService;
@PostMapping("register")
@ApiOperation("注册")
public R register(@RequestBody RegisterForm form){
//表单校验
ValidatorUtils.validateEntity(form);
UserEntity user = new UserEntity();
user.setMobile(form.getMobile());
user.setUsername(form.getMobile());
user.setPassword(DigestUtils.sha256Hex(form.getPassword()));
user.setCreateTime(new Date());
userService.save(user);
return R.ok();
}
}

@ -0,0 +1,53 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.controller;
import io.renren.common.utils.R;
import io.renren.modules.app.annotation.Login;
import io.renren.modules.app.annotation.LoginUser;
import io.renren.modules.app.entity.UserEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* APP
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("/app")
@Api("APP测试接口")
public class AppTestController {
@Login
@GetMapping("userInfo")
@ApiOperation("获取用户信息")
public R userInfo(@LoginUser UserEntity user){
return R.ok().put("user", user);
}
@Login
@GetMapping("userId")
@ApiOperation("获取用户ID")
public R userInfo(@RequestAttribute("userId") Integer userId){
return R.ok().put("userId", userId);
}
@GetMapping("notToken")
@ApiOperation("忽略Token验证测试")
public R notToken(){
return R.ok().put("msg", "无需token也能访问。。。");
}
}

@ -0,0 +1,23 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.renren.modules.app.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Mapper
public interface UserDao extends BaseMapper<UserEntity> {
}

@ -0,0 +1,51 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
@TableName("tb_user")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId
private Long userId;
/**
*
*/
private String username;
/**
*
*/
private String mobile;
/**
*
*/
private String password;
/**
*
*/
private Date createTime;
}

@ -0,0 +1,33 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.form;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
@ApiModel(value = "登录表单")
public class LoginForm {
@ApiModelProperty(value = "手机号")
@NotBlank(message="手机号不能为空")
private String mobile;
@ApiModelProperty(value = "密码")
@NotBlank(message="密码不能为空")
private String password;
}

@ -0,0 +1,33 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.form;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
@ApiModel(value = "注册表单")
public class RegisterForm {
@ApiModelProperty(value = "手机号")
@NotBlank(message="手机号不能为空")
private String mobile;
@ApiModelProperty(value = "密码")
@NotBlank(message="密码不能为空")
private String password;
}

@ -0,0 +1,72 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.interceptor;
import io.jsonwebtoken.Claims;
import io.renren.common.exception.RRException;
import io.renren.modules.app.utils.JwtUtils;
import io.renren.modules.app.annotation.Login;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* (Token)
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
@Autowired
private JwtUtils jwtUtils;
public static final String USER_KEY = "userId";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Login annotation;
if(handler instanceof HandlerMethod) {
annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
}else{
return true;
}
if(annotation == null){
return true;
}
//获取用户凭证
String token = request.getHeader(jwtUtils.getHeader());
if(StringUtils.isBlank(token)){
token = request.getParameter(jwtUtils.getHeader());
}
//凭证为空
if(StringUtils.isBlank(token)){
throw new RRException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value());
}
Claims claims = jwtUtils.getClaimByToken(token);
if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
throw new RRException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
//设置userId到request里后续根据userId获取用户信息
request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject()));
return true;
}
}

@ -0,0 +1,53 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.resolver;
import io.renren.modules.app.annotation.LoginUser;
import io.renren.modules.app.entity.UserEntity;
import io.renren.modules.app.interceptor.AuthorizationInterceptor;
import io.renren.modules.app.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* @LoginUser
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
//获取用户ID
Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
if(object == null){
return null;
}
//获取用户信息
UserEntity user = userService.getById((Long)object);
return user;
}
}

@ -0,0 +1,31 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.service;
import com.baomidou.mybatisplus.extension.service.IService;
import io.renren.modules.app.entity.UserEntity;
import io.renren.modules.app.form.LoginForm;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface UserService extends IService<UserEntity> {
UserEntity queryByMobile(String mobile);
/**
*
* @param form
* @return ID
*/
long login(LoginForm form);
}

@ -0,0 +1,44 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.exception.RRException;
import io.renren.common.validator.Assert;
import io.renren.modules.app.dao.UserDao;
import io.renren.modules.app.entity.UserEntity;
import io.renren.modules.app.form.LoginForm;
import io.renren.modules.app.service.UserService;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
@Override
public UserEntity queryByMobile(String mobile) {
return baseMapper.selectOne(new QueryWrapper<UserEntity>().eq("mobile", mobile));
}
@Override
public long login(LoginForm form) {
UserEntity user = queryByMobile(form.getMobile());
Assert.isNull(user, "手机号或密码错误");
//密码错误
if(!user.getPassword().equals(DigestUtils.sha256Hex(form.getPassword()))){
throw new RRException("手机号或密码错误");
}
return user.getUserId();
}
}

@ -0,0 +1,95 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.app.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* jwt
*
* @author Mark sunlightcs@gmail.com
*/
@ConfigurationProperties(prefix = "renren.jwt")
@Component
public class JwtUtils {
private Logger logger = LoggerFactory.getLogger(getClass());
private String secret;
private long expire;
private String header;
/**
* jwt token
*/
public String generateToken(long userId) {
Date nowDate = new Date();
//过期时间
Date expireDate = new Date(nowDate.getTime() + expire * 1000);
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(userId+"")
.setIssuedAt(nowDate)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Claims getClaimByToken(String token) {
try {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}catch (Exception e){
logger.debug("validate is token error ", e);
return null;
}
}
/**
* token
* @return true
*/
public boolean isTokenExpired(Date expiration) {
return expiration.before(new Date());
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public long getExpire() {
return expire;
}
public void setExpire(long expire) {
this.expire = expire;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
}

@ -0,0 +1,66 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.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 Mark sunlightcs@gmail.com
*/
@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", "RenrenScheduler");
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.springframework.scheduling.quartz.LocalDataSourceJobStore");
//集群配置
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_");
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
//PostgreSQL数据库需要打开此注释
//prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
factory.setQuartzProperties(prop);
factory.setSchedulerName("RenrenScheduler");
//延时启动
factory.setStartupDelay(30);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
//可选QuartzScheduler 启动时更新己存在的Job这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
//设置自动启动默认为true
factory.setAutoStartup(true);
return factory;
}
}

@ -0,0 +1,132 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.controller;
import io.renren.common.annotation.SysLog;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.modules.job.entity.ScheduleJobEntity;
import io.renren.modules.job.service.ScheduleJobService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("/sys/schedule")
public class ScheduleJobController {
@Autowired
private ScheduleJobService scheduleJobService;
/**
*
*/
@RequestMapping("/list")
@RequiresPermissions("sys:schedule:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = scheduleJobService.queryPage(params);
return R.ok().put("page", page);
}
/**
*
*/
@RequestMapping("/info/{jobId}")
@RequiresPermissions("sys:schedule:info")
public R info(@PathVariable("jobId") Long jobId){
ScheduleJobEntity schedule = scheduleJobService.getById(jobId);
return R.ok().put("schedule", schedule);
}
/**
*
*/
@SysLog("保存定时任务")
@RequestMapping("/save")
@RequiresPermissions("sys:schedule:save")
public R save(@RequestBody ScheduleJobEntity scheduleJob){
ValidatorUtils.validateEntity(scheduleJob);
scheduleJobService.saveJob(scheduleJob);
return R.ok();
}
/**
*
*/
@SysLog("修改定时任务")
@RequestMapping("/update")
@RequiresPermissions("sys:schedule:update")
public R update(@RequestBody ScheduleJobEntity scheduleJob){
ValidatorUtils.validateEntity(scheduleJob);
scheduleJobService.update(scheduleJob);
return R.ok();
}
/**
*
*/
@SysLog("删除定时任务")
@RequestMapping("/delete")
@RequiresPermissions("sys:schedule:delete")
public R delete(@RequestBody Long[] jobIds){
scheduleJobService.deleteBatch(jobIds);
return R.ok();
}
/**
*
*/
@SysLog("立即执行任务")
@RequestMapping("/run")
@RequiresPermissions("sys:schedule:run")
public R run(@RequestBody Long[] jobIds){
scheduleJobService.run(jobIds);
return R.ok();
}
/**
*
*/
@SysLog("暂停定时任务")
@RequestMapping("/pause")
@RequiresPermissions("sys:schedule:pause")
public R pause(@RequestBody Long[] jobIds){
scheduleJobService.pause(jobIds);
return R.ok();
}
/**
*
*/
@SysLog("恢复定时任务")
@RequestMapping("/resume")
@RequiresPermissions("sys:schedule:resume")
public R resume(@RequestBody Long[] jobIds){
scheduleJobService.resume(jobIds);
return R.ok();
}
}

@ -0,0 +1,55 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.controller;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.modules.job.entity.ScheduleJobLogEntity;
import io.renren.modules.job.service.ScheduleJobLogService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("/sys/scheduleLog")
public class ScheduleJobLogController {
@Autowired
private ScheduleJobLogService scheduleJobLogService;
/**
*
*/
@RequestMapping("/list")
@RequiresPermissions("sys:schedule:log")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = scheduleJobLogService.queryPage(params);
return R.ok().put("page", page);
}
/**
*
*/
@RequestMapping("/info/{logId}")
public R info(@PathVariable("logId") Long logId){
ScheduleJobLogEntity log = scheduleJobLogService.getById(logId);
return R.ok().put("log", log);
}
}

@ -0,0 +1,29 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.renren.modules.job.entity.ScheduleJobEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Mapper
public interface ScheduleJobDao extends BaseMapper<ScheduleJobEntity> {
/**
*
*/
int updateBatch(Map<String, Object> map);
}

@ -0,0 +1,23 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.renren.modules.job.entity.ScheduleJobLogEntity;
import org.apache.ibatis.annotations.Mapper;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Mapper
public interface ScheduleJobLogDao extends BaseMapper<ScheduleJobLogEntity> {
}

@ -0,0 +1,74 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
@TableName("schedule_job")
public class ScheduleJobEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* key
*/
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
/**
* id
*/
@TableId
private Long jobId;
/**
* spring bean
*/
@NotBlank(message="bean名称不能为空")
private String beanName;
/**
*
*/
private String params;
/**
* cron
*/
@NotBlank(message="cron表达式不能为空")
private String cronExpression;
/**
*
*/
private Integer status;
/**
*
*/
private String remark;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}

@ -0,0 +1,71 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
@TableName("schedule_job_log")
public class ScheduleJobLogEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId
private Long logId;
/**
* id
*/
private Long jobId;
/**
* spring bean
*/
private String beanName;
/**
*
*/
private String params;
/**
* 0 1
*/
private Integer status;
/**
*
*/
private String error;
/**
* ()
*/
private Integer times;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}

@ -0,0 +1,26 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.service;
import com.baomidou.mybatisplus.extension.service.IService;
import io.renren.common.utils.PageUtils;
import io.renren.modules.job.entity.ScheduleJobLogEntity;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface ScheduleJobLogService extends IService<ScheduleJobLogEntity> {
PageUtils queryPage(Map<String, Object> params);
}

@ -0,0 +1,60 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.service;
import com.baomidou.mybatisplus.extension.service.IService;
import io.renren.common.utils.PageUtils;
import io.renren.modules.job.entity.ScheduleJobEntity;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface ScheduleJobService extends IService<ScheduleJobEntity> {
PageUtils queryPage(Map<String, Object> params);
/**
*
*/
void saveJob(ScheduleJobEntity scheduleJob);
/**
*
*/
void update(ScheduleJobEntity scheduleJob);
/**
*
*/
void deleteBatch(Long[] jobIds);
/**
*
*/
int updateBatch(Long[] jobIds, int status);
/**
*
*/
void run(Long[] jobIds);
/**
*
*/
void pause(Long[] jobIds);
/**
*
*/
void resume(Long[] jobIds);
}

@ -0,0 +1,39 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.job.dao.ScheduleJobLogDao;
import io.renren.modules.job.entity.ScheduleJobLogEntity;
import io.renren.modules.job.service.ScheduleJobLogService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service("scheduleJobLogService")
public class ScheduleJobLogServiceImpl extends ServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
String jobId = (String)params.get("jobId");
IPage<ScheduleJobLogEntity> page = this.page(
new Query<ScheduleJobLogEntity>().getPage(params),
new QueryWrapper<ScheduleJobLogEntity>().like(StringUtils.isNotBlank(jobId),"job_id", jobId)
);
return new PageUtils(page);
}
}

@ -0,0 +1,131 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.Constant;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.job.dao.ScheduleJobDao;
import io.renren.modules.job.entity.ScheduleJobEntity;
import io.renren.modules.job.service.ScheduleJobService;
import io.renren.modules.job.utils.ScheduleUtils;
import org.apache.commons.lang.StringUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.util.*;
@Service("scheduleJobService")
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
@Autowired
private Scheduler scheduler;
/**
*
*/
@PostConstruct
public void init(){
List<ScheduleJobEntity> scheduleJobList = this.list();
for(ScheduleJobEntity scheduleJob : scheduleJobList){
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
//如果不存在,则创建
if(cronTrigger == null) {
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
}else {
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
}
}
}
@Override
public PageUtils queryPage(Map<String, Object> params) {
String beanName = (String)params.get("beanName");
IPage<ScheduleJobEntity> page = this.page(
new Query<ScheduleJobEntity>().getPage(params),
new QueryWrapper <ScheduleJobEntity>().like(StringUtils.isNotBlank(beanName),"bean_name", beanName)
);
return new PageUtils(page);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveJob(ScheduleJobEntity scheduleJob) {
scheduleJob.setCreateTime(new Date());
scheduleJob.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
this.save(scheduleJob);
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(ScheduleJobEntity scheduleJob) {
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
this.updateById(scheduleJob);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteBatch(Long[] jobIds) {
for(Long jobId : jobIds){
ScheduleUtils.deleteScheduleJob(scheduler, jobId);
}
//删除数据
this.removeByIds(Arrays.asList(jobIds));
}
@Override
public int updateBatch(Long[] jobIds, int status){
Map<String, Object> map = new HashMap<>(2);
map.put("list", Arrays.asList(jobIds));
map.put("status", status);
return baseMapper.updateBatch(map);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void run(Long[] jobIds) {
for(Long jobId : jobIds){
ScheduleUtils.run(scheduler, this.getById(jobId));
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void pause(Long[] jobIds) {
for(Long jobId : jobIds){
ScheduleUtils.pauseJob(scheduler, jobId);
}
updateBatch(jobIds, Constant.ScheduleStatus.PAUSE.getValue());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void resume(Long[] jobIds) {
for(Long jobId : jobIds){
ScheduleUtils.resumeJob(scheduler, jobId);
}
updateBatch(jobIds, Constant.ScheduleStatus.NORMAL.getValue());
}
}

@ -0,0 +1,24 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.task;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface ITask {
/**
*
*
* @param params 使JSON
*/
void run(String params);
}

@ -0,0 +1,30 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* (Demo)
*
* testTaskspring bean
*
* @author Mark sunlightcs@gmail.com
*/
@Component("testTask")
public class TestTask implements ITask {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void run(String params){
logger.debug("TestTask定时任务正在执行参数为{}", params);
}
}

@ -0,0 +1,81 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.utils;
import io.renren.common.utils.SpringContextUtils;
import io.renren.modules.job.entity.ScheduleJobEntity;
import io.renren.modules.job.entity.ScheduleJobLogEntity;
import io.renren.modules.job.service.ScheduleJobLogService;
import org.apache.commons.lang.StringUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class ScheduleJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap()
.get(ScheduleJobEntity.JOB_PARAM_KEY);
//获取spring bean
ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService) SpringContextUtils.getBean("scheduleJobLogService");
//数据库保存执行记录
ScheduleJobLogEntity log = new ScheduleJobLogEntity();
log.setJobId(scheduleJob.getJobId());
log.setBeanName(scheduleJob.getBeanName());
log.setParams(scheduleJob.getParams());
log.setCreateTime(new Date());
//任务开始时间
long startTime = System.currentTimeMillis();
try {
//执行任务
logger.debug("任务准备执行任务ID" + scheduleJob.getJobId());
Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
Method method = target.getClass().getDeclaredMethod("run", String.class);
method.invoke(target, scheduleJob.getParams());
//任务执行总时长
long times = System.currentTimeMillis() - startTime;
log.setTimes((int)times);
//任务状态 0成功 1失败
log.setStatus(0);
logger.debug("任务执行完毕任务ID" + scheduleJob.getJobId() + " 总共耗时:" + times + "毫秒");
} catch (Exception e) {
logger.error("任务执行失败任务ID" + scheduleJob.getJobId(), e);
//任务执行总时长
long times = System.currentTimeMillis() - startTime;
log.setTimes((int)times);
//任务状态 0成功 1失败
log.setStatus(1);
log.setError(StringUtils.substring(e.toString(), 0, 2000));
}finally {
scheduleJobLogService.save(log);
}
}
}

@ -0,0 +1,156 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.job.utils;
import io.renren.common.exception.RRException;
import io.renren.common.utils.Constant;
import io.renren.modules.job.entity.ScheduleJobEntity;
import org.quartz.*;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class ScheduleUtils {
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) {
throw new RRException("获取定时任务CronTrigger出现异常", e);
}
}
/**
*
*/
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
try {
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getJobId())).build();
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder).build();
//放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);
scheduler.scheduleJob(jobDetail, trigger);
//暂停任务
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
pauseJob(scheduler, scheduleJob.getJobId());
}
} catch (SchedulerException e) {
throw new RRException("创建定时任务失败", e);
}
}
/**
*
*/
public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
try {
TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//参数
trigger.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);
scheduler.rescheduleJob(triggerKey, trigger);
//暂停任务
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
pauseJob(scheduler, scheduleJob.getJobId());
}
} catch (SchedulerException e) {
throw new RRException("更新定时任务失败", e);
}
}
/**
*
*/
public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
try {
//参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleJobEntity.JOB_PARAM_KEY, scheduleJob);
scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
} catch (SchedulerException e) {
throw new RRException("立即执行定时任务失败", e);
}
}
/**
*
*/
public static void pauseJob(Scheduler scheduler, Long jobId) {
try {
scheduler.pauseJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RRException("暂停定时任务失败", e);
}
}
/**
*
*/
public static void resumeJob(Scheduler scheduler, Long jobId) {
try {
scheduler.resumeJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RRException("暂停定时任务失败", e);
}
}
/**
*
*/
public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
try {
scheduler.deleteJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RRException("删除定时任务失败", e);
}
}
}

@ -0,0 +1,62 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.cloud;
import com.aliyun.oss.OSSClient;
import io.renren.common.exception.RRException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class AliyunCloudStorageService extends CloudStorageService {
private OSSClient client;
public AliyunCloudStorageService(CloudStorageConfig config){
this.config = config;
//初始化
init();
}
private void init(){
client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(),
config.getAliyunAccessKeySecret());
}
@Override
public String upload(byte[] data, String path) {
return upload(new ByteArrayInputStream(data), path);
}
@Override
public String upload(InputStream inputStream, String path) {
try {
client.putObject(config.getAliyunBucketName(), path, inputStream);
} catch (Exception e){
throw new RRException("上传文件失败,请检查配置信息", e);
}
return config.getAliyunDomain() + "/" + path;
}
@Override
public String uploadSuffix(byte[] data, String suffix) {
return upload(data, getPath(config.getAliyunPrefix(), suffix));
}
@Override
public String uploadSuffix(InputStream inputStream, String suffix) {
return upload(inputStream, getPath(config.getAliyunPrefix(), suffix));
}
}

@ -0,0 +1,94 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.cloud;
import io.renren.common.validator.group.AliyunGroup;
import io.renren.common.validator.group.QcloudGroup;
import io.renren.common.validator.group.QiniuGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
public class CloudStorageConfig implements Serializable {
private static final long serialVersionUID = 1L;
//类型 1七牛 2阿里云 3腾讯云
@Range(min=1, max=3, message = "类型错误")
private Integer type;
//七牛绑定的域名
@NotBlank(message="七牛绑定的域名不能为空", groups = QiniuGroup.class)
@URL(message = "七牛绑定的域名格式不正确", groups = QiniuGroup.class)
private String qiniuDomain;
//七牛路径前缀
private String qiniuPrefix;
//七牛ACCESS_KEY
@NotBlank(message="七牛AccessKey不能为空", groups = QiniuGroup.class)
private String qiniuAccessKey;
//七牛SECRET_KEY
@NotBlank(message="七牛SecretKey不能为空", groups = QiniuGroup.class)
private String qiniuSecretKey;
//七牛存储空间名
@NotBlank(message="七牛空间名不能为空", groups = QiniuGroup.class)
private String qiniuBucketName;
//阿里云绑定的域名
@NotBlank(message="阿里云绑定的域名不能为空", groups = AliyunGroup.class)
@URL(message = "阿里云绑定的域名格式不正确", groups = AliyunGroup.class)
private String aliyunDomain;
//阿里云路径前缀
private String aliyunPrefix;
//阿里云EndPoint
@NotBlank(message="阿里云EndPoint不能为空", groups = AliyunGroup.class)
private String aliyunEndPoint;
//阿里云AccessKeyId
@NotBlank(message="阿里云AccessKeyId不能为空", groups = AliyunGroup.class)
private String aliyunAccessKeyId;
//阿里云AccessKeySecret
@NotBlank(message="阿里云AccessKeySecret不能为空", groups = AliyunGroup.class)
private String aliyunAccessKeySecret;
//阿里云BucketName
@NotBlank(message="阿里云BucketName不能为空", groups = AliyunGroup.class)
private String aliyunBucketName;
//腾讯云绑定的域名
@NotBlank(message="腾讯云绑定的域名不能为空", groups = QcloudGroup.class)
@URL(message = "腾讯云绑定的域名格式不正确", groups = QcloudGroup.class)
private String qcloudDomain;
//腾讯云路径前缀
private String qcloudPrefix;
//腾讯云AppId
@NotNull(message="腾讯云AppId不能为空", groups = QcloudGroup.class)
private Integer qcloudAppId;
//腾讯云SecretId
@NotBlank(message="腾讯云SecretId不能为空", groups = QcloudGroup.class)
private String qcloudSecretId;
//腾讯云SecretKey
@NotBlank(message="腾讯云SecretKey不能为空", groups = QcloudGroup.class)
private String qcloudSecretKey;
//腾讯云BucketName
@NotBlank(message="腾讯云BucketName不能为空", groups = QcloudGroup.class)
private String qcloudBucketName;
//腾讯云COS所属地区
@NotBlank(message="所属地区不能为空", groups = QcloudGroup.class)
private String qcloudRegion;
}

@ -0,0 +1,78 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.cloud;
import io.renren.common.utils.DateUtils;
import org.apache.commons.lang.StringUtils;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;
/**
* ()
*
* @author Mark sunlightcs@gmail.com
*/
public abstract class CloudStorageService {
/** 云存储配置信息 */
CloudStorageConfig config;
/**
*
* @param prefix
* @param suffix
* @return
*/
public String getPath(String prefix, String suffix) {
//生成uuid
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
//文件路径
String path = DateUtils.format(new Date(), "yyyyMMdd") + "/" + uuid;
if(StringUtils.isNotBlank(prefix)){
path = prefix + "/" + path;
}
return path + suffix;
}
/**
*
* @param data
* @param path
* @return http
*/
public abstract String upload(byte[] data, String path);
/**
*
* @param data
* @param suffix
* @return http
*/
public abstract String uploadSuffix(byte[] data, String suffix);
/**
*
* @param inputStream
* @param path
* @return http
*/
public abstract String upload(InputStream inputStream, String path);
/**
*
* @param inputStream
* @param suffix
* @return http
*/
public abstract String uploadSuffix(InputStream inputStream, String suffix);
}

@ -0,0 +1,44 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.cloud;
import io.renren.common.utils.ConfigConstant;
import io.renren.common.utils.Constant;
import io.renren.common.utils.SpringContextUtils;
import io.renren.modules.sys.service.SysConfigService;
/**
* Factory
*
* @author Mark sunlightcs@gmail.com
*/
public final class OSSFactory {
private static SysConfigService sysConfigService;
static {
OSSFactory.sysConfigService = (SysConfigService) SpringContextUtils.getBean("sysConfigService");
}
public static CloudStorageService build(){
//获取云存储配置信息
CloudStorageConfig config = sysConfigService.getConfigObject(ConfigConstant.CLOUD_STORAGE_CONFIG_KEY, CloudStorageConfig.class);
if(config.getType() == Constant.CloudService.QINIU.getValue()){
return new QiniuCloudStorageService(config);
}else if(config.getType() == Constant.CloudService.ALIYUN.getValue()){
return new AliyunCloudStorageService(config);
}else if(config.getType() == Constant.CloudService.QCLOUD.getValue()){
return new QcloudCloudStorageService(config);
}
return null;
}
}

@ -0,0 +1,88 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.cloud;
import com.alibaba.fastjson.JSONObject;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.request.UploadFileRequest;
import com.qcloud.cos.sign.Credentials;
import io.renren.common.exception.RRException;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class QcloudCloudStorageService extends CloudStorageService {
private COSClient client;
public QcloudCloudStorageService(CloudStorageConfig config){
this.config = config;
//初始化
init();
}
private void init(){
Credentials credentials = new Credentials(config.getQcloudAppId(), config.getQcloudSecretId(),
config.getQcloudSecretKey());
//初始化客户端配置
ClientConfig clientConfig = new ClientConfig();
//设置bucket所在的区域华南gz 华北tj 华东sh
clientConfig.setRegion(config.getQcloudRegion());
client = new COSClient(clientConfig, credentials);
}
@Override
public String upload(byte[] data, String path) {
//腾讯云必需要以"/"开头
if(!path.startsWith("/")) {
path = "/" + path;
}
//上传到腾讯云
UploadFileRequest request = new UploadFileRequest(config.getQcloudBucketName(), path, data);
String response = client.uploadFile(request);
JSONObject jsonObject = JSONObject.parseObject(response);
if(jsonObject.getInteger("code") != 0) {
throw new RRException("文件上传失败," + jsonObject.getString("message"));
}
return config.getQcloudDomain() + path;
}
@Override
public String upload(InputStream inputStream, String path) {
try {
byte[] data = IOUtils.toByteArray(inputStream);
return this.upload(data, path);
} catch (IOException e) {
throw new RRException("上传文件失败", e);
}
}
@Override
public String uploadSuffix(byte[] data, String suffix) {
return upload(data, getPath(config.getQcloudPrefix(), suffix));
}
@Override
public String uploadSuffix(InputStream inputStream, String suffix) {
return upload(inputStream, getPath(config.getQcloudPrefix(), suffix));
}
}

@ -0,0 +1,77 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.cloud;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import io.renren.common.exception.RRException;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public class QiniuCloudStorageService extends CloudStorageService {
private UploadManager uploadManager;
private String token;
public QiniuCloudStorageService(CloudStorageConfig config){
this.config = config;
//初始化
init();
}
private void init(){
uploadManager = new UploadManager(new Configuration(Zone.autoZone()));
token = Auth.create(config.getQiniuAccessKey(), config.getQiniuSecretKey()).
uploadToken(config.getQiniuBucketName());
}
@Override
public String upload(byte[] data, String path) {
try {
Response res = uploadManager.put(data, path, token);
if (!res.isOK()) {
throw new RuntimeException("上传七牛出错:" + res.toString());
}
} catch (Exception e) {
throw new RRException("上传文件失败,请核对七牛配置信息", e);
}
return config.getQiniuDomain() + "/" + path;
}
@Override
public String upload(InputStream inputStream, String path) {
try {
byte[] data = IOUtils.toByteArray(inputStream);
return this.upload(data, path);
} catch (IOException e) {
throw new RRException("上传文件失败", e);
}
}
@Override
public String uploadSuffix(byte[] data, String suffix) {
return upload(data, getPath(config.getQiniuPrefix(), suffix));
}
@Override
public String uploadSuffix(InputStream inputStream, String suffix) {
return upload(inputStream, getPath(config.getQiniuPrefix(), suffix));
}
}

@ -0,0 +1,125 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.controller;
import com.google.gson.Gson;
import io.renren.common.exception.RRException;
import io.renren.common.utils.ConfigConstant;
import io.renren.common.utils.Constant;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.common.validator.group.AliyunGroup;
import io.renren.common.validator.group.QcloudGroup;
import io.renren.common.validator.group.QiniuGroup;
import io.renren.modules.oss.cloud.CloudStorageConfig;
import io.renren.modules.oss.cloud.OSSFactory;
import io.renren.modules.oss.entity.SysOssEntity;
import io.renren.modules.oss.service.SysOssService;
import io.renren.modules.sys.service.SysConfigService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("sys/oss")
public class SysOssController {
@Autowired
private SysOssService sysOssService;
@Autowired
private SysConfigService sysConfigService;
private final static String KEY = ConfigConstant.CLOUD_STORAGE_CONFIG_KEY;
/**
*
*/
@GetMapping("/list")
@RequiresPermissions("sys:oss:all")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = sysOssService.queryPage(params);
return R.ok().put("page", page);
}
/**
*
*/
@GetMapping("/config")
@RequiresPermissions("sys:oss:all")
public R config(){
CloudStorageConfig config = sysConfigService.getConfigObject(KEY, CloudStorageConfig.class);
return R.ok().put("config", config);
}
/**
*
*/
@PostMapping("/saveConfig")
@RequiresPermissions("sys:oss:all")
public R saveConfig(@RequestBody CloudStorageConfig config){
//校验类型
ValidatorUtils.validateEntity(config);
ValidatorUtils.validateEntity(config, Constant.CloudService.getByValue(config.getType()));
sysConfigService.updateValueByKey(KEY, new Gson().toJson(config));
return R.ok();
}
/**
*
*/
@PostMapping("/upload")
@RequiresPermissions("sys:oss:all")
public R upload(@RequestParam("file") MultipartFile file) throws Exception {
if (file.isEmpty()) {
throw new RRException("上传文件不能为空");
}
//上传文件
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
String url = OSSFactory.build().uploadSuffix(file.getBytes(), suffix);
//保存文件信息
SysOssEntity ossEntity = new SysOssEntity();
ossEntity.setUrl(url);
ossEntity.setCreateDate(new Date());
sysOssService.save(ossEntity);
return R.ok().put("url", url);
}
/**
*
*/
@PostMapping("/delete")
@RequiresPermissions("sys:oss:all")
public R delete(@RequestBody Long[] ids){
sysOssService.removeByIds(Arrays.asList(ids));
return R.ok();
}
}

@ -0,0 +1,23 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.renren.modules.oss.entity.SysOssEntity;
import org.apache.ibatis.annotations.Mapper;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Mapper
public interface SysOssDao extends BaseMapper<SysOssEntity> {
}

@ -0,0 +1,36 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@Data
@TableName("sys_oss")
public class SysOssEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private Long id;
//URL地址
private String url;
//创建时间
private Date createDate;
}

@ -0,0 +1,25 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.service;
import com.baomidou.mybatisplus.extension.service.IService;
import io.renren.common.utils.PageUtils;
import io.renren.modules.oss.entity.SysOssEntity;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
public interface SysOssService extends IService<SysOssEntity> {
PageUtils queryPage(Map<String, Object> params);
}

@ -0,0 +1,35 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.oss.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.oss.dao.SysOssDao;
import io.renren.modules.oss.entity.SysOssEntity;
import io.renren.modules.oss.service.SysOssService;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service("sysOssService")
public class SysOssServiceImpl extends ServiceImpl<SysOssDao, SysOssEntity> implements SysOssService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
IPage<SysOssEntity> page = this.page(
new Query<SysOssEntity>().getPage(params)
);
return new PageUtils(page);
}
}

@ -0,0 +1,31 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.sys.controller;
import io.renren.modules.sys.entity.SysUserEntity;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Controller
*
* @author Mark sunlightcs@gmail.com
*/
public abstract class AbstractController {
protected Logger logger = LoggerFactory.getLogger(getClass());
protected SysUserEntity getUser() {
return (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
}
protected Long getUserId() {
return getUser().getUserId();
}
}

@ -0,0 +1,98 @@
/**
* Copyright (c) 2016-2019 All rights reserved.
*
* https://www.renren.io
*
*
*/
package io.renren.modules.sys.controller;
import io.renren.common.annotation.SysLog;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.modules.sys.entity.SysConfigEntity;
import io.renren.modules.sys.service.SysConfigService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
*
*
* @author Mark sunlightcs@gmail.com
*/
@RestController
@RequestMapping("/sys/config")
public class SysConfigController extends AbstractController {
@Autowired
private SysConfigService sysConfigService;
/**
*
*/
@GetMapping("/list")
@RequiresPermissions("sys:config:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = sysConfigService.queryPage(params);
return R.ok().put("page", page);
}
/**
*
*/
@GetMapping("/info/{id}")
@RequiresPermissions("sys:config:info")
public R info(@PathVariable("id") Long id){
SysConfigEntity config = sysConfigService.getById(id);
return R.ok().put("config", config);
}
/**
*
*/
@SysLog("保存配置")
@PostMapping("/save")
@RequiresPermissions("sys:config:save")
public R save(@RequestBody SysConfigEntity config){
ValidatorUtils.validateEntity(config);
sysConfigService.saveConfig(config);
return R.ok();
}
/**
*
*/
@SysLog("修改配置")
@PostMapping("/update")
@RequiresPermissions("sys:config:update")
public R update(@RequestBody SysConfigEntity config){
ValidatorUtils.validateEntity(config);
sysConfigService.update(config);
return R.ok();
}
/**
*
*/
@SysLog("删除配置")
@PostMapping("/delete")
@RequiresPermissions("sys:config:delete")
public R delete(@RequestBody Long[] ids){
sysConfigService.deleteBatch(ids);
return R.ok();
}
}

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

Loading…
Cancel
Save