mirror of https://gitee.com/y_project/RuoYi.git
RuoYi
6 years ago
458 changed files with 103815 additions and 0 deletions
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT) |
||||
|
||||
Copyright (c) 2018 RuoYi |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of |
||||
this software and associated documentation files (the "Software"), to deal in |
||||
the Software without restriction, including without limitation the rights to |
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
||||
the Software, and to permit persons to whom the Software is furnished to do so, |
||||
subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,92 @@
|
||||
## 平台简介 |
||||
|
||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。 |
||||
|
||||
性别男,若依是女儿的名字。 |
||||
|
||||
若依基于hplus和inspinia两套后台系统摸版开发。有需要可自行到群内下载。 |
||||
|
||||
http://www.zi-han.net/theme/hplus |
||||
|
||||
http://webapplayers.com/inspinia_admin-v2.7.1 |
||||
|
||||
## 内置功能 |
||||
|
||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 |
||||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现。 |
||||
3. 岗位管理:配置系统用户所属担任职务。 |
||||
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 |
||||
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 |
||||
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 |
||||
7. 参数管理:对系统动态配置常用参数。 |
||||
8. 通知公告:系统通知公告信息发布维护。 |
||||
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 |
||||
10. 登录日志:系统登录日志记录查询包含登录异常。 |
||||
11. 在线用户:当前系统中活跃用户状态监控。 |
||||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 |
||||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 |
||||
14. 系统接口:根据业务代码自动生成相关的api接口文档。 |
||||
15. 在线构建器:拖动表单元素生成相应的HTML代码。 |
||||
16. 连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 |
||||
## 在线体验 |
||||
> admin/admin123 |
||||
|
||||
地址:http://www.ruoyi.club |
||||
|
||||
## 演示图 |
||||
|
||||
<table> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%99%BB%E5%BD%95%E7%95%8C%E9%9D%A2.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E9%A6%96%E9%A1%B5.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%94%A8%E6%88%B7%E4%BF%AE%E6%94%B9.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E8%A7%92%E8%89%B2%E7%AE%A1%E7%90%86.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E8%A7%92%E8%89%B2%E4%BF%AE%E6%94%B9.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E8%8F%9C%E5%8D%95%E7%AE%A1%E7%90%86.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E4%BF%AE%E6%94%B9%E8%8F%9C%E5%8D%95.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E9%83%A8%E9%97%A8%E7%AE%A1%E7%90%86.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E4%BF%AE%E6%94%B9%E9%83%A8%E9%97%A8.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%B2%97%E4%BD%8D%E7%AE%A1%E7%90%86.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%B2%97%E4%BD%8D%E4%BF%AE%E6%94%B9.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AD%97%E5%85%B8%E7%B1%BB%E5%9E%8B.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AD%97%E5%85%B8%E6%95%B0%E6%8D%AE.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E9%80%9A%E7%9F%A5%E7%AE%A1%E7%90%86.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E6%93%8D%E4%BD%9C%E6%97%A5%E5%BF%97.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%99%BB%E5%BD%95%E6%97%A5%E5%BF%97.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E6%97%A5%E5%BF%97.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E5%9C%A8%E7%BA%BF%E7%94%A8%E6%88%B7.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90.png"/></td> |
||||
</tr> |
||||
<tr> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E6%95%B0%E6%8D%AE%E7%9B%91%E6%8E%A7.png"/></td> |
||||
<td><img src="https://ruoyi-1256174062.cos.ap-guangzhou.myqcloud.com/%E8%8B%A5%E4%BE%9D2.0/%E7%B3%BB%E7%BB%9F%E6%8E%A5%E5%8F%A3.png"/></td> |
||||
</tr> |
||||
</table> |
||||
|
||||
|
||||
## 若依交流群 |
||||
|
||||
QQ群: [![加入QQ群](https://img.shields.io/badge/QQ群-1389287-blue.svg)](http://shang.qq.com/wpa/qunwpa?idkey=4a9a52f5d9d9c65a8ea67859170ba835d95fc50ec74a2a722293e60e036b5016) 或 [![加入QQ群](https://img.shields.io/badge/QQ群-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN),推荐点击按钮入群,当然如果无法成功操作,请自行搜索群号`1389287`进行添加 |
Binary file not shown.
@ -0,0 +1,290 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>com.ruoyi</groupId> |
||||
<artifactId>RuoYi</artifactId> |
||||
<version>2.1.0</version> |
||||
<packaging>jar</packaging> |
||||
|
||||
<name>RuoYi</name> |
||||
<description>若依管理系统</description> |
||||
|
||||
<parent> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-parent</artifactId> |
||||
<version>2.0.3.RELEASE</version> |
||||
<relativePath /> |
||||
</parent> |
||||
|
||||
<properties> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
||||
<java.version>1.8</java.version> |
||||
<shiro.version>1.4.0</shiro.version> |
||||
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version> |
||||
<mybatis.spring.boot.starter.version>1.3.2</mybatis.spring.boot.starter.version> |
||||
<pagehelper.spring.boot.starter.version>1.2.5</pagehelper.spring.boot.starter.version> |
||||
<fastjson.version>1.2.47</fastjson.version> |
||||
<druid.version>1.1.10</druid.version> |
||||
<commons.io.version>2.5</commons.io.version> |
||||
<commons.fileupload.version>1.3.3</commons.fileupload.version> |
||||
<bitwalker.version>1.19</bitwalker.version> |
||||
<lombok.version>1.16.18</lombok.version> |
||||
<velocity.version>1.7</velocity.version> |
||||
<kaptcha.version>2.3.2</kaptcha.version> |
||||
<swagger.version>2.7.0</swagger.version> |
||||
<jsoup.version>1.11.3</jsoup.version> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
|
||||
<!-- SpringBoot 核心包 --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter</artifactId> |
||||
<!-- |
||||
<exclusions> |
||||
<exclusion> |
||||
<artifactId>spring-boot-starter-tomcat</artifactId> |
||||
<groupId>org.springframework.boot</groupId> |
||||
</exclusion> |
||||
</exclusions> |
||||
--> |
||||
</dependency> |
||||
|
||||
<!-- SpringBoot 测试 --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-test</artifactId> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
|
||||
<!-- SpringBoot 拦截器 --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-aop</artifactId> |
||||
</dependency> |
||||
|
||||
<!-- SpringBoot Web容器 --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-web</artifactId> |
||||
</dependency> |
||||
|
||||
<!-- SpringBoot集成thymeleaf模板 --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId> |
||||
</dependency> |
||||
|
||||
<!-- spring-boot-devtools --> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-devtools</artifactId> |
||||
<optional>true</optional> <!-- 表示依赖不会传递 --> |
||||
</dependency> |
||||
|
||||
<!-- thymeleaf网页解析 --> |
||||
<dependency> |
||||
<groupId>net.sourceforge.nekohtml</groupId> |
||||
<artifactId>nekohtml</artifactId> |
||||
</dependency> |
||||
|
||||
<!-- Mysql驱动包 --> |
||||
<dependency> |
||||
<groupId>mysql</groupId> |
||||
<artifactId>mysql-connector-java</artifactId> |
||||
</dependency> |
||||
|
||||
<!-- SpringBoot集成mybatis框架 --> |
||||
<dependency> |
||||
<groupId>org.mybatis.spring.boot</groupId> |
||||
<artifactId>mybatis-spring-boot-starter</artifactId> |
||||
<version>${mybatis.spring.boot.starter.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- pagehelper 分页插件 --> |
||||
<dependency> |
||||
<groupId>com.github.pagehelper</groupId> |
||||
<artifactId>pagehelper-spring-boot-starter</artifactId> |
||||
<version>${pagehelper.spring.boot.starter.version}</version> |
||||
</dependency> |
||||
|
||||
<!--阿里数据库连接池 --> |
||||
<dependency> |
||||
<groupId>com.alibaba</groupId> |
||||
<artifactId>druid</artifactId> |
||||
<version>${druid.version}</version> |
||||
</dependency> |
||||
|
||||
<!--常用工具类 --> |
||||
<dependency> |
||||
<groupId>org.apache.commons</groupId> |
||||
<artifactId>commons-lang3</artifactId> |
||||
</dependency> |
||||
|
||||
<!--io常用工具类 --> |
||||
<dependency> |
||||
<groupId>commons-io</groupId> |
||||
<artifactId>commons-io</artifactId> |
||||
<version>${commons.io.version}</version> |
||||
</dependency> |
||||
|
||||
<!--文件上传工具类 --> |
||||
<dependency> |
||||
<groupId>commons-fileupload</groupId> |
||||
<artifactId>commons-fileupload</artifactId> |
||||
<version>${commons.fileupload.version}</version> |
||||
</dependency> |
||||
|
||||
<!--Shiro核心框架 --> |
||||
<dependency> |
||||
<groupId>org.apache.shiro</groupId> |
||||
<artifactId>shiro-core</artifactId> |
||||
<version>${shiro.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- Shiro使用Srping框架 --> |
||||
<dependency> |
||||
<groupId>org.apache.shiro</groupId> |
||||
<artifactId>shiro-spring</artifactId> |
||||
<version>${shiro.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- Shiro使用EhCache缓存框架 --> |
||||
<dependency> |
||||
<groupId>org.apache.shiro</groupId> |
||||
<artifactId>shiro-ehcache</artifactId> |
||||
<version>${shiro.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- thymeleaf模板引擎和shiro框架的整合 --> |
||||
<dependency> |
||||
<groupId>com.github.theborakompanioni</groupId> |
||||
<artifactId>thymeleaf-extras-shiro</artifactId> |
||||
<version>${thymeleaf.extras.shiro.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- 阿里JSON解析器 --> |
||||
<dependency> |
||||
<groupId>com.alibaba</groupId> |
||||
<artifactId>fastjson</artifactId> |
||||
<version>${fastjson.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 --> |
||||
<dependency> |
||||
<groupId>eu.bitwalker</groupId> |
||||
<artifactId>UserAgentUtils</artifactId> |
||||
<version>${bitwalker.version}</version> |
||||
</dependency> |
||||
|
||||
<!--Spring框架基本的核心工具--> |
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-context-support</artifactId> |
||||
</dependency> |
||||
|
||||
<!-- 定时任务 --> |
||||
<dependency> |
||||
<groupId>org.quartz-scheduler</groupId> |
||||
<artifactId>quartz</artifactId> |
||||
<exclusions> |
||||
<exclusion> |
||||
<groupId>com.mchange</groupId> |
||||
<artifactId>c3p0</artifactId> |
||||
</exclusion> |
||||
</exclusions> |
||||
</dependency> |
||||
|
||||
<!--velocity代码生成使用模板 --> |
||||
<dependency> |
||||
<groupId>org.apache.velocity</groupId> |
||||
<artifactId>velocity</artifactId> |
||||
<version>${velocity.version}</version> |
||||
</dependency> |
||||
|
||||
<!--验证码 --> |
||||
<dependency> |
||||
<groupId>com.github.penggle</groupId> |
||||
<artifactId>kaptcha</artifactId> |
||||
<version>${kaptcha.version}</version> |
||||
<exclusions> |
||||
<exclusion> |
||||
<artifactId>javax.servlet-api</artifactId> |
||||
<groupId>javax.servlet</groupId> |
||||
</exclusion> |
||||
</exclusions> |
||||
</dependency> |
||||
|
||||
<!-- swagger2--> |
||||
<dependency> |
||||
<groupId>io.springfox</groupId> |
||||
<artifactId>springfox-swagger2</artifactId> |
||||
<version>${swagger.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- swagger2-UI--> |
||||
<dependency> |
||||
<groupId>io.springfox</groupId> |
||||
<artifactId>springfox-swagger-ui</artifactId> |
||||
<version>${swagger.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- HTML解析器 --> |
||||
<dependency> |
||||
<groupId>org.jsoup</groupId> |
||||
<artifactId>jsoup</artifactId> |
||||
<version>${jsoup.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- excel工具 --> |
||||
<dependency> |
||||
<groupId>org.apache.poi</groupId> |
||||
<artifactId>poi-ooxml</artifactId> |
||||
<version>3.9</version> |
||||
</dependency> |
||||
|
||||
</dependencies> |
||||
|
||||
<build> |
||||
<finalName>${project.artifactId}</finalName> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
<configuration> |
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 --> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
|
||||
<repositories> |
||||
<repository> |
||||
<id>public</id> |
||||
<name>aliyun nexus</name> |
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> |
||||
<releases> |
||||
<enabled>true</enabled> |
||||
</releases> |
||||
</repository> |
||||
</repositories> |
||||
|
||||
<pluginRepositories> |
||||
<pluginRepository> |
||||
<id>public</id> |
||||
<name>aliyun nexus</name> |
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> |
||||
<releases> |
||||
<enabled>true</enabled> |
||||
</releases> |
||||
<snapshots> |
||||
<enabled>false</enabled> |
||||
</snapshots> |
||||
</pluginRepository> |
||||
</pluginRepositories> |
||||
|
||||
</project> |
@ -0,0 +1,86 @@
|
||||
#!/bin/bash |
||||
|
||||
AppName=RuoYi.jar |
||||
|
||||
#JVM参数 |
||||
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" |
||||
APP_HOME=`pwd` |
||||
LOG_PATH=$APP_HOME/logs/$AppName.log |
||||
|
||||
if [ "$1" = "" ]; |
||||
then |
||||
echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m" |
||||
exit 1 |
||||
fi |
||||
|
||||
if [ "$AppName" = "" ]; |
||||
then |
||||
echo -e "\033[0;31m 未输入应用名 \033[0m" |
||||
exit 1 |
||||
fi |
||||
|
||||
function start() |
||||
{ |
||||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` |
||||
|
||||
if [ x"$PID" != x"" ]; then |
||||
echo "$AppName is running..." |
||||
else |
||||
nohup java -jar $JVM_OPTS target/$AppName > /dev/null 2>&1 & |
||||
echo "Start $AppName success..." |
||||
fi |
||||
} |
||||
|
||||
function stop() |
||||
{ |
||||
echo "Stop $AppName" |
||||
|
||||
PID="" |
||||
query(){ |
||||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` |
||||
} |
||||
|
||||
query |
||||
if [ x"$PID" != x"" ]; then |
||||
kill -TERM $PID |
||||
echo "$AppName (pid:$PID) exiting..." |
||||
while [ x"$PID" != x"" ] |
||||
do |
||||
sleep 1 |
||||
query |
||||
done |
||||
echo "$AppName exited." |
||||
else |
||||
echo "$AppName already stopped." |
||||
fi |
||||
} |
||||
|
||||
function restart() |
||||
{ |
||||
stop |
||||
sleep 2 |
||||
start |
||||
} |
||||
|
||||
function status() |
||||
{ |
||||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l` |
||||
if [ $PID != 0 ];then |
||||
echo "$AppName is running..." |
||||
else |
||||
echo "$AppName is not running..." |
||||
fi |
||||
} |
||||
|
||||
case $1 in |
||||
start) |
||||
start;; |
||||
stop) |
||||
stop;; |
||||
restart) |
||||
restart;; |
||||
status) |
||||
status;; |
||||
*) |
||||
|
||||
esac |
@ -0,0 +1,170 @@
|
||||
-- ---------------------------- |
||||
-- 1、存储每一个已配置的 jobDetail 的详细信息 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_JOB_DETAILS; |
||||
create table QRTZ_JOB_DETAILS ( |
||||
sched_name varchar(120) not null, |
||||
job_name varchar(200) not null, |
||||
job_group varchar(200) not null, |
||||
description varchar(250) null, |
||||
job_class_name varchar(250) not null, |
||||
is_durable varchar(1) not null, |
||||
is_nonconcurrent varchar(1) not null, |
||||
is_update_data varchar(1) not null, |
||||
requests_recovery varchar(1) not null, |
||||
job_data blob null, |
||||
primary key (sched_name,job_name,job_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 2、 存储已配置的 Trigger 的信息 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_TRIGGERS; |
||||
create table QRTZ_TRIGGERS ( |
||||
sched_name varchar(120) not null, |
||||
trigger_name varchar(200) not null, |
||||
trigger_group varchar(200) not null, |
||||
job_name varchar(200) not null, |
||||
job_group varchar(200) not null, |
||||
description varchar(250) null, |
||||
next_fire_time bigint(13) null, |
||||
prev_fire_time bigint(13) null, |
||||
priority integer null, |
||||
trigger_state varchar(16) not null, |
||||
trigger_type varchar(8) not null, |
||||
start_time bigint(13) not null, |
||||
end_time bigint(13) null, |
||||
calendar_name varchar(200) null, |
||||
misfire_instr smallint(2) null, |
||||
job_data blob null, |
||||
primary key (sched_name,trigger_name,trigger_group), |
||||
foreign key (sched_name,job_name,job_group) references QRTZ_JOB_DETAILS(sched_name,job_name,job_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_SIMPLE_TRIGGERS; |
||||
create table QRTZ_SIMPLE_TRIGGERS ( |
||||
sched_name varchar(120) not null, |
||||
trigger_name varchar(200) not null, |
||||
trigger_group varchar(200) not null, |
||||
repeat_count bigint(7) not null, |
||||
repeat_interval bigint(12) not null, |
||||
times_triggered bigint(10) not null, |
||||
primary key (sched_name,trigger_name,trigger_group), |
||||
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_CRON_TRIGGERS; |
||||
create table QRTZ_CRON_TRIGGERS ( |
||||
sched_name varchar(120) not null, |
||||
trigger_name varchar(200) not null, |
||||
trigger_group varchar(200) not null, |
||||
cron_expression varchar(200) not null, |
||||
time_zone_id varchar(80), |
||||
primary key (sched_name,trigger_name,trigger_group), |
||||
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_BLOB_TRIGGERS; |
||||
create table QRTZ_BLOB_TRIGGERS ( |
||||
sched_name varchar(120) not null, |
||||
trigger_name varchar(200) not null, |
||||
trigger_group varchar(200) not null, |
||||
blob_data blob null, |
||||
primary key (sched_name,trigger_name,trigger_group), |
||||
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_CALENDARS; |
||||
create table QRTZ_CALENDARS ( |
||||
sched_name varchar(120) not null, |
||||
calendar_name varchar(200) not null, |
||||
calendar blob not null, |
||||
primary key (sched_name,calendar_name) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 7、 存储已暂停的 Trigger 组的信息 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_PAUSED_TRIGGER_GRPS; |
||||
create table QRTZ_PAUSED_TRIGGER_GRPS ( |
||||
sched_name varchar(120) not null, |
||||
trigger_group varchar(200) not null, |
||||
primary key (sched_name,trigger_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_FIRED_TRIGGERS; |
||||
create table QRTZ_FIRED_TRIGGERS ( |
||||
sched_name varchar(120) not null, |
||||
entry_id varchar(95) not null, |
||||
trigger_name varchar(200) not null, |
||||
trigger_group varchar(200) not null, |
||||
instance_name varchar(200) not null, |
||||
fired_time bigint(13) not null, |
||||
sched_time bigint(13) not null, |
||||
priority integer not null, |
||||
state varchar(16) not null, |
||||
job_name varchar(200) null, |
||||
job_group varchar(200) null, |
||||
is_nonconcurrent varchar(1) null, |
||||
requests_recovery varchar(1) null, |
||||
primary key (sched_name,entry_id) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例 |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_SCHEDULER_STATE; |
||||
create table QRTZ_SCHEDULER_STATE ( |
||||
sched_name varchar(120) not null, |
||||
instance_name varchar(200) not null, |
||||
last_checkin_time bigint(13) not null, |
||||
checkin_interval bigint(13) not null, |
||||
primary key (sched_name,instance_name) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
-- ---------------------------- |
||||
-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁) |
||||
-- ---------------------------- |
||||
drop table if exists QRTZ_LOCKS; |
||||
create table QRTZ_LOCKS ( |
||||
sched_name varchar(120) not null, |
||||
lock_name varchar(40) not null, |
||||
primary key (sched_name,lock_name) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
drop table if exists QRTZ_SIMPROP_TRIGGERS; |
||||
create table QRTZ_SIMPROP_TRIGGERS ( |
||||
sched_name varchar(120) not null, |
||||
trigger_name varchar(200) not null, |
||||
trigger_group varchar(200) not null, |
||||
str_prop_1 varchar(512) null, |
||||
str_prop_2 varchar(512) null, |
||||
str_prop_3 varchar(512) null, |
||||
int_prop_1 int null, |
||||
int_prop_2 int null, |
||||
long_prop_1 bigint null, |
||||
long_prop_2 bigint null, |
||||
dec_prop_1 numeric(13,4) null, |
||||
dec_prop_2 numeric(13,4) null, |
||||
bool_prop_1 varchar(1) null, |
||||
bool_prop_2 varchar(1) null, |
||||
primary key (sched_name,trigger_name,trigger_group), |
||||
foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group) |
||||
) engine=innodb default charset=utf8; |
||||
|
||||
commit; |
@ -0,0 +1,597 @@
|
||||
-- ---------------------------- |
||||
-- 1、部门表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_dept; |
||||
create table sys_dept ( |
||||
dept_id int(11) not null auto_increment comment '部门id', |
||||
parent_id int(11) default 0 comment '父部门id', |
||||
dept_name varchar(30) default '' comment '部门名称', |
||||
order_num int(4) default 0 comment '显示顺序', |
||||
leader varchar(20) default '' comment '负责人', |
||||
phone varchar(11) default '' comment '联系电话', |
||||
email varchar(50) default '' comment '邮箱', |
||||
status char(1) default '0' comment '部门状态(0正常 1停用)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
primary key (dept_id) |
||||
) engine=innodb auto_increment=200 default charset=utf8 comment = '部门表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-部门表数据 |
||||
-- ---------------------------- |
||||
insert into sys_dept values(100, 0, '若依集团', 0, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(101, 100, '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(102, 100, '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(103, 100, '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(104, 100, '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(105, 100, '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(106, 101, '研发一部', 1, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(107, 101, '研发二部', 2, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(108, 102, '市场一部', 1, '若依', '15888888888', 'ry@qq.com', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
insert into sys_dept values(109, 102, '市场二部', 2, '若依', '15888888888', 'ry@qq.com', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00'); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 2、用户信息表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_user; |
||||
create table sys_user ( |
||||
user_id int(11) not null auto_increment comment '用户ID', |
||||
dept_id int(11) default null comment '部门ID', |
||||
login_name varchar(30) not null comment '登录账号', |
||||
user_name varchar(30) not null comment '用户昵称', |
||||
user_type varchar(2) default '00' comment '用户类型(00系统用户)', |
||||
email varchar(50) default '' comment '用户邮箱', |
||||
phonenumber varchar(11) default '' comment '手机号码', |
||||
sex char(1) default '0' comment '用户性别(0男 1女 2未知)', |
||||
avatar varchar(100) default '' comment '头像路径', |
||||
password varchar(50) default '' comment '密码', |
||||
salt varchar(20) default '' comment '盐加密', |
||||
status char(1) default '0' comment '帐号状态(0正常 1停用)', |
||||
del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', |
||||
login_ip varchar(20) default '' comment '最后登陆IP', |
||||
login_date datetime comment '最后登陆时间', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (user_id) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '用户信息表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-用户信息表数据 |
||||
-- ---------------------------- |
||||
insert into sys_user values(1, 106, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', '2018-03-16 11-33-00', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员'); |
||||
insert into sys_user values(2, 108, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', '2018-03-16 11-33-00', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '测试员'); |
||||
|
||||
-- ---------------------------- |
||||
-- 3、岗位信息表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_post; |
||||
create table sys_post |
||||
( |
||||
post_id int(11) not null auto_increment comment '岗位ID', |
||||
post_code varchar(64) not null comment '岗位编码', |
||||
post_name varchar(50) not null comment '岗位名称', |
||||
post_sort int(4) not null comment '显示顺序', |
||||
status char(1) not null comment '状态(0正常 1停用)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (post_id) |
||||
) engine=innodb default charset=utf8 comment = '岗位信息表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-岗位信息表数据 |
||||
-- ---------------------------- |
||||
insert into sys_post values(1, 'ceo', '董事长', 1, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 4、角色信息表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_role; |
||||
create table sys_role ( |
||||
role_id int(11) not null auto_increment comment '角色ID', |
||||
role_name varchar(30) not null comment '角色名称', |
||||
role_key varchar(100) not null comment '角色权限字符串', |
||||
role_sort int(4) not null comment '显示顺序', |
||||
status char(1) not null comment '角色状态(0正常 1停用)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (role_id) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '角色信息表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-角色信息表数据 |
||||
-- ---------------------------- |
||||
insert into sys_role values('1', '管理员', 'admin', 1, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员'); |
||||
insert into sys_role values('2', '普通角色', 'common', 2, '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '普通角色'); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 5、菜单权限表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_menu; |
||||
create table sys_menu ( |
||||
menu_id int(11) not null auto_increment comment '菜单ID', |
||||
menu_name varchar(50) not null comment '菜单名称', |
||||
parent_id int(11) default 0 comment '父菜单ID', |
||||
order_num int(4) default null comment '显示顺序', |
||||
url varchar(200) default '' comment '请求地址', |
||||
menu_type char(1) default '' comment '菜单类型(M目录 C菜单 F按钮)', |
||||
visible char(1) default 0 comment '菜单状态(0显示 1隐藏)', |
||||
perms varchar(100) default '' comment '权限标识', |
||||
icon varchar(100) default '' comment '菜单图标', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (menu_id) |
||||
) engine=innodb auto_increment=2000 default charset=utf8 comment = '菜单权限表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-菜单信息表数据 |
||||
-- ---------------------------- |
||||
-- 一级菜单 |
||||
insert into sys_menu values('1', '系统管理', '0', '1', '#', 'M', '0', '', 'fa fa-gear', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统管理目录'); |
||||
insert into sys_menu values('2', '系统监控', '0', '2', '#', 'M', '0', '', 'fa fa-video-camera', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统监控目录'); |
||||
insert into sys_menu values('3', '系统工具', '0', '3', '#', 'M', '0', '', 'fa fa-bars', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统工具目录'); |
||||
-- 二级菜单 |
||||
insert into sys_menu values('100', '用户管理', '1', '1', '/system/user', 'C', '0', 'system:user:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '用户管理菜单'); |
||||
insert into sys_menu values('101', '角色管理', '1', '2', '/system/role', 'C', '0', 'system:role:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '角色管理菜单'); |
||||
insert into sys_menu values('102', '菜单管理', '1', '3', '/system/menu', 'C', '0', 'system:menu:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '菜单管理菜单'); |
||||
insert into sys_menu values('103', '部门管理', '1', '4', '/system/dept', 'C', '0', 'system:dept:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '部门管理菜单'); |
||||
insert into sys_menu values('104', '岗位管理', '1', '5', '/system/post', 'C', '0', 'system:post:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '岗位管理菜单'); |
||||
insert into sys_menu values('105', '字典管理', '1', '6', '/system/dict', 'C', '0', 'system:dict:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '字典管理菜单'); |
||||
insert into sys_menu values('106', '参数设置', '1', '7', '/system/config', 'C', '0', 'system:config:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '参数设置菜单'); |
||||
insert into sys_menu values('107', '通知公告', '1', '8', '/system/notice', 'C', '0', 'system:notice:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知公告菜单'); |
||||
insert into sys_menu values('108', '日志管理', '1', '9', '#', 'M', '0', '', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '日志管理菜单'); |
||||
insert into sys_menu values('109', '在线用户', '2', '1', '/monitor/online', 'C', '0', 'monitor:online:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '在线用户菜单'); |
||||
insert into sys_menu values('110', '定时任务', '2', '2', '/monitor/job', 'C', '0', 'monitor:job:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '定时任务菜单'); |
||||
insert into sys_menu values('111', '数据监控', '2', '3', '/monitor/data', 'C', '0', 'monitor:data:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '数据监控菜单'); |
||||
insert into sys_menu values('112', '表单构建', '3', '1', '/tool/build', 'C', '0', 'tool:build:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '表单构建菜单'); |
||||
insert into sys_menu values('113', '代码生成', '3', '2', '/tool/gen', 'C', '0', 'tool:gen:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '代码生成菜单'); |
||||
insert into sys_menu values('114', '系统接口', '3', '3', '/tool/swagger', 'C', '0', 'tool:swagger:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统接口菜单'); |
||||
-- 三级菜单 |
||||
insert into sys_menu values('500', '操作日志', '108', '1', '/monitor/operlog', 'C', '0', 'monitor:operlog:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '操作日志菜单'); |
||||
insert into sys_menu values('501', '登录日志', '108', '2', '/monitor/logininfor', 'C', '0', 'monitor:logininfor:view', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '登录日志菜单'); |
||||
-- 用户管理按钮 |
||||
insert into sys_menu values('1000', '用户查询', '100', '1', '#', 'F', '0', 'system:user:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1001', '用户新增', '100', '2', '#', 'F', '0', 'system:user:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1002', '用户修改', '100', '3', '#', 'F', '0', 'system:user:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1003', '用户删除', '100', '4', '#', 'F', '0', 'system:user:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1004', '用户保存', '100', '5', '#', 'F', '0', 'system:user:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1005', '重置密码', '100', '6', '#', 'F', '0', 'system:user:resetPwd', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 角色管理按钮 |
||||
insert into sys_menu values('1006', '角色查询', '101', '1', '#', 'F', '0', 'system:role:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1007', '角色新增', '101', '2', '#', 'F', '0', 'system:role:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1008', '角色修改', '101', '3', '#', 'F', '0', 'system:role:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1009', '角色删除', '101', '4', '#', 'F', '0', 'system:role:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1010', '角色保存', '101', '5', '#', 'F', '0', 'system:role:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 菜单管理按钮 |
||||
insert into sys_menu values('1011', '菜单查询', '102', '1', '#', 'F', '0', 'system:menu:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1012', '菜单新增', '102', '2', '#', 'F', '0', 'system:menu:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1013', '菜单修改', '102', '3', '#', 'F', '0', 'system:menu:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1014', '菜单删除', '102', '4', '#', 'F', '0', 'system:menu:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1015', '菜单保存', '102', '5', '#', 'F', '0', 'system:menu:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 部门管理按钮 |
||||
insert into sys_menu values('1016', '部门查询', '103', '1', '#', 'F', '0', 'system:dept:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1017', '部门新增', '103', '2', '#', 'F', '0', 'system:dept:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1018', '部门修改', '103', '3', '#', 'F', '0', 'system:dept:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1019', '部门删除', '103', '4', '#', 'F', '0', 'system:dept:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1020', '部门保存', '103', '5', '#', 'F', '0', 'system:dept:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 岗位管理按钮 |
||||
insert into sys_menu values('1021', '岗位查询', '104', '1', '#', 'F', '0', 'system:post:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1022', '岗位新增', '104', '2', '#', 'F', '0', 'system:post:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1023', '岗位修改', '104', '3', '#', 'F', '0', 'system:post:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1024', '岗位删除', '104', '4', '#', 'F', '0', 'system:post:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1025', '岗位保存', '104', '5', '#', 'F', '0', 'system:post:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 字典管理按钮 |
||||
insert into sys_menu values('1026', '字典查询', '105', '1', '#', 'F', '0', 'system:dict:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1027', '字典新增', '105', '2', '#', 'F', '0', 'system:dict:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1028', '字典修改', '105', '3', '#', 'F', '0', 'system:dict:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1029', '字典删除', '105', '4', '#', 'F', '0', 'system:dict:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1030', '字典保存', '105', '5', '#', 'F', '0', 'system:dict:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 参数设置按钮 |
||||
insert into sys_menu values('1031', '参数查询', '106', '1', '#', 'F', '0', 'system:config:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1032', '参数新增', '106', '2', '#', 'F', '0', 'system:config:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1033', '参数修改', '106', '3', '#', 'F', '0', 'system:config:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1034', '参数删除', '106', '4', '#', 'F', '0', 'system:config:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1035', '参数保存', '106', '5', '#', 'F', '0', 'system:config:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 通知公告按钮 |
||||
insert into sys_menu values('1036', '公告查询', '107', '1', '#', 'F', '0', 'system:notice:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1037', '公告新增', '107', '2', '#', 'F', '0', 'system:notice:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1038', '公告修改', '107', '3', '#', 'F', '0', 'system:notice:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1039', '公告删除', '107', '4', '#', 'F', '0', 'system:notice:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1040', '公告保存', '107', '5', '#', 'F', '0', 'system:notice:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 操作日志按钮 |
||||
insert into sys_menu values('1041', '操作查询', '500', '1', '#', 'F', '0', 'monitor:operlog:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1042', '操作删除', '500', '2', '#', 'F', '0', 'monitor:operlog:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1043', '详细信息', '500', '3', '#', 'F', '0', 'monitor:operlog:detail', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 登录日志按钮 |
||||
insert into sys_menu values('1044', '登录查询', '501', '1', '#', 'F', '0', 'monitor:logininfor:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1045', '登录删除', '501', '2', '#', 'F', '0', 'monitor:logininfor:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 在线用户按钮 |
||||
insert into sys_menu values('1046', '在线查询', '109', '1', '#', 'F', '0', 'monitor:online:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1047', '批量强退', '109', '2', '#', 'F', '0', 'monitor:online:batchForceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1048', '单条强退', '109', '3', '#', 'F', '0', 'monitor:online:forceLogout', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 定时任务按钮 |
||||
insert into sys_menu values('1049', '任务查询', '110', '1', '#', 'F', '0', 'monitor:job:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1050', '任务新增', '110', '2', '#', 'F', '0', 'monitor:job:add', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1051', '任务修改', '110', '3', '#', 'F', '0', 'monitor:job:edit', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1052', '任务删除', '110', '4', '#', 'F', '0', 'monitor:job:remove', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1053', '任务保存', '110', '5', '#', 'F', '0', 'monitor:job:save', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1054', '状态修改', '110', '6', '#', 'F', '0', 'monitor:job:changeStatus', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
-- 代码生成按钮 |
||||
insert into sys_menu values('1055', '生成查询', '113', '1', '#', 'F', '0', 'tool:gen:list', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_menu values('1056', '生成代码', '113', '2', '#', 'F', '0', 'tool:gen:code', '#', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 6、用户和角色关联表 用户N-1角色 |
||||
-- ---------------------------- |
||||
drop table if exists sys_user_role; |
||||
create table sys_user_role ( |
||||
user_id int(11) not null comment '用户ID', |
||||
role_id int(11) not null comment '角色ID', |
||||
primary key(user_id, role_id) |
||||
) engine=innodb default charset=utf8 comment = '用户和角色关联表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-用户和角色关联表数据 |
||||
-- ---------------------------- |
||||
insert into sys_user_role values ('1', '1'); |
||||
insert into sys_user_role values ('2', '2'); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 7、角色和菜单关联表 角色1-N菜单 |
||||
-- ---------------------------- |
||||
drop table if exists sys_role_menu; |
||||
create table sys_role_menu ( |
||||
role_id int(11) not null comment '角色ID', |
||||
menu_id int(11) not null comment '菜单ID', |
||||
primary key(role_id, menu_id) |
||||
) engine=innodb default charset=utf8 comment = '角色和菜单关联表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-角色和菜单关联表数据 |
||||
-- ---------------------------- |
||||
insert into sys_role_menu values ('1', '1'); |
||||
insert into sys_role_menu values ('1', '2'); |
||||
insert into sys_role_menu values ('1', '3'); |
||||
insert into sys_role_menu values ('1', '100'); |
||||
insert into sys_role_menu values ('1', '101'); |
||||
insert into sys_role_menu values ('1', '102'); |
||||
insert into sys_role_menu values ('1', '103'); |
||||
insert into sys_role_menu values ('1', '104'); |
||||
insert into sys_role_menu values ('1', '105'); |
||||
insert into sys_role_menu values ('1', '106'); |
||||
insert into sys_role_menu values ('1', '107'); |
||||
insert into sys_role_menu values ('1', '108'); |
||||
insert into sys_role_menu values ('1', '109'); |
||||
insert into sys_role_menu values ('1', '110'); |
||||
insert into sys_role_menu values ('1', '111'); |
||||
insert into sys_role_menu values ('1', '112'); |
||||
insert into sys_role_menu values ('1', '113'); |
||||
insert into sys_role_menu values ('1', '114'); |
||||
insert into sys_role_menu values ('1', '500'); |
||||
insert into sys_role_menu values ('1', '501'); |
||||
insert into sys_role_menu values ('1', '1000'); |
||||
insert into sys_role_menu values ('1', '1001'); |
||||
insert into sys_role_menu values ('1', '1002'); |
||||
insert into sys_role_menu values ('1', '1003'); |
||||
insert into sys_role_menu values ('1', '1004'); |
||||
insert into sys_role_menu values ('1', '1005'); |
||||
insert into sys_role_menu values ('1', '1006'); |
||||
insert into sys_role_menu values ('1', '1007'); |
||||
insert into sys_role_menu values ('1', '1008'); |
||||
insert into sys_role_menu values ('1', '1009'); |
||||
insert into sys_role_menu values ('1', '1010'); |
||||
insert into sys_role_menu values ('1', '1011'); |
||||
insert into sys_role_menu values ('1', '1012'); |
||||
insert into sys_role_menu values ('1', '1013'); |
||||
insert into sys_role_menu values ('1', '1014'); |
||||
insert into sys_role_menu values ('1', '1015'); |
||||
insert into sys_role_menu values ('1', '1016'); |
||||
insert into sys_role_menu values ('1', '1017'); |
||||
insert into sys_role_menu values ('1', '1018'); |
||||
insert into sys_role_menu values ('1', '1019'); |
||||
insert into sys_role_menu values ('1', '1020'); |
||||
insert into sys_role_menu values ('1', '1021'); |
||||
insert into sys_role_menu values ('1', '1022'); |
||||
insert into sys_role_menu values ('1', '1023'); |
||||
insert into sys_role_menu values ('1', '1024'); |
||||
insert into sys_role_menu values ('1', '1025'); |
||||
insert into sys_role_menu values ('1', '1026'); |
||||
insert into sys_role_menu values ('1', '1027'); |
||||
insert into sys_role_menu values ('1', '1028'); |
||||
insert into sys_role_menu values ('1', '1029'); |
||||
insert into sys_role_menu values ('1', '1030'); |
||||
insert into sys_role_menu values ('1', '1031'); |
||||
insert into sys_role_menu values ('1', '1032'); |
||||
insert into sys_role_menu values ('1', '1033'); |
||||
insert into sys_role_menu values ('1', '1034'); |
||||
insert into sys_role_menu values ('1', '1035'); |
||||
insert into sys_role_menu values ('1', '1036'); |
||||
insert into sys_role_menu values ('1', '1037'); |
||||
insert into sys_role_menu values ('1', '1038'); |
||||
insert into sys_role_menu values ('1', '1039'); |
||||
insert into sys_role_menu values ('1', '1040'); |
||||
insert into sys_role_menu values ('1', '1041'); |
||||
insert into sys_role_menu values ('1', '1042'); |
||||
insert into sys_role_menu values ('1', '1043'); |
||||
insert into sys_role_menu values ('1', '1044'); |
||||
insert into sys_role_menu values ('1', '1045'); |
||||
insert into sys_role_menu values ('1', '1046'); |
||||
insert into sys_role_menu values ('1', '1047'); |
||||
insert into sys_role_menu values ('1', '1048'); |
||||
insert into sys_role_menu values ('1', '1049'); |
||||
insert into sys_role_menu values ('1', '1050'); |
||||
insert into sys_role_menu values ('1', '1051'); |
||||
insert into sys_role_menu values ('1', '1052'); |
||||
insert into sys_role_menu values ('1', '1053'); |
||||
insert into sys_role_menu values ('1', '1054'); |
||||
insert into sys_role_menu values ('1', '1055'); |
||||
insert into sys_role_menu values ('1', '1056'); |
||||
|
||||
-- ---------------------------- |
||||
-- 8、用户与岗位关联表 用户1-N岗位 |
||||
-- ---------------------------- |
||||
drop table if exists sys_user_post; |
||||
create table sys_user_post |
||||
( |
||||
user_id varchar(64) not null comment '用户ID', |
||||
post_id varchar(64) not null comment '岗位ID', |
||||
primary key (user_id, post_id) |
||||
) engine=innodb default charset=utf8 comment = '用户与岗位关联表'; |
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-用户与岗位关联表数据 |
||||
-- ---------------------------- |
||||
insert into sys_user_post values ('1', '1'); |
||||
insert into sys_user_post values ('2', '2'); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 9、操作日志记录 |
||||
-- ---------------------------- |
||||
drop table if exists sys_oper_log; |
||||
create table sys_oper_log ( |
||||
oper_id int(11) not null auto_increment comment '日志主键', |
||||
title varchar(50) default '' comment '模块标题', |
||||
action varchar(100) default '' comment '功能请求', |
||||
method varchar(100) default '' comment '方法名称', |
||||
channel varchar(20) default '' comment '来源渠道(manage后台用户 mobile手机端用户 other其它)', |
||||
oper_name varchar(50) default '' comment '操作人员', |
||||
dept_name varchar(50) default '' comment '部门名称', |
||||
oper_url varchar(255) default '' comment '请求URL', |
||||
oper_ip varchar(30) default '' comment '主机地址', |
||||
oper_location varchar(255) default '' comment '操作地点', |
||||
oper_param varchar(255) default '' comment '请求参数', |
||||
status char(1) default '0' comment '操作状态(0正常 1异常)', |
||||
error_msg varchar(2000) default '' comment '错误消息', |
||||
oper_time datetime comment '操作时间', |
||||
primary key (oper_id) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '操作日志记录'; |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 10、字典类型表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_dict_type; |
||||
create table sys_dict_type |
||||
( |
||||
dict_id int(11) not null auto_increment comment '字典主键', |
||||
dict_name varchar(100) default '' comment '字典名称', |
||||
dict_type varchar(100) default '' comment '字典类型', |
||||
status char(1) default '0' comment '状态(0正常 1停用)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (dict_id), |
||||
unique (dict_type) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '字典类型表'; |
||||
|
||||
insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '用户性别列表'); |
||||
insert into sys_dict_type values(2, '菜单状态', 'sys_show_hide', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '菜单状态列表'); |
||||
insert into sys_dict_type values(3, '系统开关', 'sys_normal_disable', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统开关列表'); |
||||
insert into sys_dict_type values(4, '任务状态', 'sys_job_status', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '任务状态列表'); |
||||
insert into sys_dict_type values(5, '系统是否', 'sys_yes_no', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统是否列表'); |
||||
insert into sys_dict_type values(6, '通知类型', 'sys_notice_type', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知类型列表'); |
||||
insert into sys_dict_type values(7, '通知状态', 'sys_notice_status', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知状态列表'); |
||||
insert into sys_dict_type values(8, '操作类型', 'sys_oper_type', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '操作类型列表'); |
||||
insert into sys_dict_type values(9, '系统状态', 'sys_common_status', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '登录状态列表'); |
||||
|
||||
-- ---------------------------- |
||||
-- 11、字典数据表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_dict_data; |
||||
create table sys_dict_data |
||||
( |
||||
dict_code int(11) not null auto_increment comment '字典编码', |
||||
dict_sort int(4) default 0 comment '字典排序', |
||||
dict_label varchar(100) default '' comment '字典标签', |
||||
dict_value varchar(100) default '' comment '字典键值', |
||||
dict_type varchar(100) default '' comment '字典类型', |
||||
css_class varchar(500) default '' comment '样式属性', |
||||
is_default char(1) default 'N' comment '是否默认(Y是 N否)', |
||||
status char(1) default '0' comment '状态(0正常 1停用)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (dict_code) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '字典数据表'; |
||||
|
||||
|
||||
insert into sys_dict_data values(1, 1, '男', '0', 'sys_user_sex', '', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '性别男'); |
||||
insert into sys_dict_data values(2, 2, '女', '1', 'sys_user_sex', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '性别女'); |
||||
insert into sys_dict_data values(3, 3, '未知', '2', 'sys_user_sex', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '性别未知'); |
||||
insert into sys_dict_data values(4, 1, '显示', '0', 'sys_show_hide', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '显示菜单'); |
||||
insert into sys_dict_data values(5, 2, '隐藏', '1', 'sys_show_hide', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '隐藏菜单'); |
||||
insert into sys_dict_data values(6, 1, '正常', '0', 'sys_normal_disable', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态'); |
||||
insert into sys_dict_data values(7, 2, '停用', '1', 'sys_normal_disable', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '停用状态'); |
||||
insert into sys_dict_data values(8, 1, '正常', '0', 'sys_job_status', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态'); |
||||
insert into sys_dict_data values(9, 2, '暂停', '1', 'sys_job_status', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '停用状态'); |
||||
insert into sys_dict_data values(10, 1, '是', 'Y', 'sys_yes_no', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统默认是'); |
||||
insert into sys_dict_data values(11, 2, '否', 'N', 'sys_yes_no', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统默认否'); |
||||
insert into sys_dict_data values(12, 1, '通知', '1', 'sys_notice_type', '', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '通知'); |
||||
insert into sys_dict_data values(13, 2, '公告', '2', 'sys_notice_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '公告'); |
||||
insert into sys_dict_data values(14, 1, '正常', '0', 'sys_notice_status', 'radio radio-info radio-inline', 'Y', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态'); |
||||
insert into sys_dict_data values(15, 2, '关闭', '1', 'sys_notice_status', 'radio radio-danger radio-inline', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '关闭状态'); |
||||
insert into sys_dict_data values(16, 1, '新增', '1', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(17, 2, '修改', '2', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(18, 3, '保存', '3', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(19, 4, '删除', '4', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(20, 5, '授权', '5', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(21, 6, '导出', '6', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(22, 7, '导入', '7', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(23, 8, '强退', '8', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(24, 9, '禁止访问', '9', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(25, 10, '生成代码', '10', 'sys_oper_type', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '新增操作'); |
||||
insert into sys_dict_data values(26, 1, '成功', '0', 'sys_common_status', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '正常状态'); |
||||
insert into sys_dict_data values(27, 2, '失败', '1', 'sys_common_status', '', 'N', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '停用状态'); |
||||
|
||||
-- ---------------------------- |
||||
-- 12、参数配置表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_config; |
||||
create table sys_config ( |
||||
config_id int(5) not null auto_increment comment '参数主键', |
||||
config_name varchar(100) default '' comment '参数名称', |
||||
config_key varchar(100) default '' comment '参数键名', |
||||
config_value varchar(100) default '' comment '参数键值', |
||||
config_type char(1) default 'N' comment '系统内置(Y是 N否)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注', |
||||
primary key (config_id) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '参数配置表'; |
||||
|
||||
insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-default', 'Y', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '默认 skin-default、蓝色 skin-blue、黄色 skin-yellow' ); |
||||
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '初始化密码 123456' ); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 13、系统访问记录 |
||||
-- ---------------------------- |
||||
drop table if exists sys_logininfor; |
||||
create table sys_logininfor ( |
||||
info_id int(11) not null auto_increment comment '访问ID', |
||||
login_name varchar(50) default '' comment '登录账号', |
||||
ipaddr varchar(50) default '' comment '登录IP地址', |
||||
login_location varchar(255) default '' comment '登录地点', |
||||
browser varchar(50) default '' comment '浏览器类型', |
||||
os varchar(50) default '' comment '操作系统', |
||||
status char(1) default '0' comment '登录状态(0成功 1失败)', |
||||
msg varchar(255) default '' comment '提示消息', |
||||
login_time datetime comment '访问时间', |
||||
primary key (info_id) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '系统访问记录'; |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 14、在线用户记录 |
||||
-- ---------------------------- |
||||
drop table if exists sys_user_online; |
||||
create table sys_user_online ( |
||||
sessionId varchar(50) default '' comment '用户会话id', |
||||
login_name varchar(50) default '' comment '登录账号', |
||||
dept_name varchar(50) default '' comment '部门名称', |
||||
ipaddr varchar(50) default '' comment '登录IP地址', |
||||
login_location varchar(255) default '' comment '登录地点', |
||||
browser varchar(50) default '' comment '浏览器类型', |
||||
os varchar(50) default '' comment '操作系统', |
||||
status varchar(10) default '' comment '在线状态on_line在线off_line离线', |
||||
start_timestsamp datetime comment 'session创建时间', |
||||
last_access_time datetime comment 'session最后访问时间', |
||||
expire_time int(5) default 0 comment '超时时间,单位为分钟', |
||||
primary key (sessionId) |
||||
) engine=innodb default charset=utf8 comment = '在线用户记录'; |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 15、定时任务调度表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_job; |
||||
create table sys_job ( |
||||
job_id int(11) not null auto_increment comment '任务ID', |
||||
job_name varchar(64) default '' comment '任务名称', |
||||
job_group varchar(64) default '' comment '任务组名', |
||||
method_name varchar(500) default '' comment '任务方法', |
||||
params varchar(200) default '' comment '方法参数', |
||||
cron_expression varchar(255) default '' comment 'cron执行表达式', |
||||
status char(1) default '0' comment '状态(0正常 1暂停)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(500) default '' comment '备注信息', |
||||
primary key (job_id, job_name, job_group) |
||||
) engine=innodb auto_increment=100 default charset=utf8 comment = '定时任务调度表'; |
||||
|
||||
insert into sys_job values(1, 'ryTask', '系统默认(无参)', 'ryNoParams', '', '0/10 * * * * ?', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
insert into sys_job values(2, 'ryTask', '系统默认(有参)', 'ryParams', 'ry', '0/20 * * * * ?', '1', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', ''); |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 16、定时任务调度日志表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_job_log; |
||||
create table sys_job_log ( |
||||
job_log_id int(11) not null auto_increment comment '任务日志ID', |
||||
job_name varchar(64) not null comment '任务名称', |
||||
job_group varchar(64) not null comment '任务组名', |
||||
method_name varchar(500) comment '任务方法', |
||||
params varchar(200) default '' comment '方法参数', |
||||
job_message varchar(500) comment '日志信息', |
||||
status char(1) default '0' comment '执行状态(0正常 1失败)', |
||||
exception_info text comment '异常信息', |
||||
create_time datetime comment '创建时间', |
||||
primary key (job_log_id) |
||||
) engine=innodb default charset=utf8 comment = '定时任务调度日志表'; |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 17、通知公告表 |
||||
-- ---------------------------- |
||||
drop table if exists sys_notice; |
||||
create table sys_notice ( |
||||
notice_id int(4) not null auto_increment comment '公告ID', |
||||
notice_title varchar(50) not null comment '公告标题', |
||||
notice_type char(2) not null comment '公告类型(1通知 2公告)', |
||||
notice_content varchar(500) not null comment '公告内容', |
||||
status char(1) default '0' comment '公告状态(0正常 1关闭)', |
||||
create_by varchar(64) default '' comment '创建者', |
||||
create_time datetime comment '创建时间', |
||||
update_by varchar(64) default '' comment '更新者', |
||||
update_time datetime comment '更新时间', |
||||
remark varchar(255) default '' comment '备注', |
||||
primary key (notice_id) |
||||
) engine=innodb auto_increment=10 default charset=utf8 comment = '通知公告表'; |
||||
|
||||
|
||||
-- ---------------------------- |
||||
-- 初始化-公告信息表数据 |
||||
-- ---------------------------- |
||||
insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员'); |
||||
insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员'); |
@ -0,0 +1,33 @@
|
||||
package com.ruoyi; |
||||
|
||||
import org.mybatis.spring.annotation.MapperScan; |
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import org.springframework.transaction.annotation.EnableTransactionManagement; |
||||
|
||||
/** |
||||
* 启动程序 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@SpringBootApplication |
||||
@EnableTransactionManagement |
||||
@MapperScan("com.ruoyi.project.*.*.mapper") |
||||
public class RuoYiApplication |
||||
{ |
||||
public static void main(String[] args) |
||||
{ |
||||
// System.setProperty("spring.devtools.restart.enabled", "false");
|
||||
SpringApplication.run(RuoYiApplication.class, args); |
||||
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + |
||||
" .-------. ____ __ \n" + |
||||
" | _ _ \\ \\ \\ / / \n" + |
||||
" | ( ' ) | \\ _. / ' \n" + |
||||
" |(_ o _) / _( )_ .' \n" + |
||||
" | (_,_).' __ ___(_ o _)' \n" + |
||||
" | |\\ \\ | || |(_,_)' \n" + |
||||
" | | \\ `' /| `-' / \n" + |
||||
" | | \\ / \\ / \n" + |
||||
" ''-' `'-' `-..-' "); |
||||
} |
||||
} |
@ -0,0 +1,19 @@
|
||||
package com.ruoyi; |
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder; |
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; |
||||
|
||||
/** |
||||
* web容器中进行部署 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class RuoYiServletInitializer extends SpringBootServletInitializer |
||||
{ |
||||
@Override |
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) |
||||
{ |
||||
return application.sources(RuoYiApplication.class); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,46 @@
|
||||
package com.ruoyi.common.constant; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 通用Map数据 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class CommonMap |
||||
{ |
||||
/** 状态编码转换 */ |
||||
public static Map<String, String> javaTypeMap = new HashMap<String, String>(); |
||||
|
||||
static |
||||
{ |
||||
initJavaTypeMap(); |
||||
} |
||||
|
||||
/** |
||||
* 返回状态映射 |
||||
*/ |
||||
public static void initJavaTypeMap() |
||||
{ |
||||
javaTypeMap.put("tinyint", "Integer"); |
||||
javaTypeMap.put("smallint", "Integer"); |
||||
javaTypeMap.put("mediumint", "Integer"); |
||||
javaTypeMap.put("int", "Integer"); |
||||
javaTypeMap.put("integer", "integer"); |
||||
javaTypeMap.put("bigint", "Long"); |
||||
javaTypeMap.put("float", "Float"); |
||||
javaTypeMap.put("double", "Double"); |
||||
javaTypeMap.put("decimal", "BigDecimal"); |
||||
javaTypeMap.put("bit", "Boolean"); |
||||
javaTypeMap.put("char", "String"); |
||||
javaTypeMap.put("varchar", "String"); |
||||
javaTypeMap.put("tinytext", "String"); |
||||
javaTypeMap.put("text", "String"); |
||||
javaTypeMap.put("mediumtext", "String"); |
||||
javaTypeMap.put("longtext", "String"); |
||||
javaTypeMap.put("date", "Date"); |
||||
javaTypeMap.put("datetime", "Date"); |
||||
javaTypeMap.put("timestamp", "Date"); |
||||
} |
||||
} |
@ -0,0 +1,65 @@
|
||||
package com.ruoyi.common.constant; |
||||
|
||||
/** |
||||
* 通用常量信息 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class Constants |
||||
{ |
||||
/** |
||||
* UTF-8 字符集 |
||||
*/ |
||||
public static final String UTF8 = "UTF-8"; |
||||
|
||||
/** |
||||
* 通用成功标识 |
||||
*/ |
||||
public static final String SUCCESS = "0"; |
||||
|
||||
/** |
||||
* 通用失败标识 |
||||
*/ |
||||
public static final String FAIL = "1"; |
||||
|
||||
/** |
||||
* 登录成功 |
||||
*/ |
||||
public static final String LOGIN_SUCCESS = "Success"; |
||||
|
||||
/** |
||||
* 注销 |
||||
*/ |
||||
public static final String LOGOUT = "Logout"; |
||||
|
||||
/** |
||||
* 登录失败 |
||||
*/ |
||||
public static final String LOGIN_FAIL = "Error"; |
||||
|
||||
/** |
||||
* 自动去除表前缀 |
||||
*/ |
||||
public static String AUTO_REOMVE_PRE = "true"; |
||||
|
||||
/** |
||||
* 当前记录起始索引 |
||||
*/ |
||||
public static String PAGENUM = "pageNum"; |
||||
|
||||
/** |
||||
* 每页显示记录数 |
||||
*/ |
||||
public static String PAGESIZE = "pageSize"; |
||||
|
||||
/** |
||||
* 排序列 |
||||
*/ |
||||
public static String ORDERBYCOLUMN = "orderByColumn"; |
||||
|
||||
/** |
||||
* 排序的方向 "desc" 或者 "asc". |
||||
*/ |
||||
public static String ISASC = "isAsc"; |
||||
|
||||
} |
@ -0,0 +1,39 @@
|
||||
package com.ruoyi.common.constant; |
||||
|
||||
/** |
||||
* 任务调度通用常量 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface ScheduleConstants |
||||
{ |
||||
/** |
||||
* 任务调度参数key |
||||
*/ |
||||
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY"; |
||||
|
||||
public enum Status |
||||
{ |
||||
/** |
||||
* 正常 |
||||
*/ |
||||
NORMAL("0"), |
||||
/** |
||||
* 暂停 |
||||
*/ |
||||
PAUSE("1"); |
||||
|
||||
private String value; |
||||
|
||||
private Status(String value) |
||||
{ |
||||
this.value = value; |
||||
} |
||||
|
||||
public String getValue() |
||||
{ |
||||
return value; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,65 @@
|
||||
package com.ruoyi.common.constant; |
||||
|
||||
/** |
||||
* Shiro通用常量 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface ShiroConstants |
||||
{ |
||||
/** |
||||
* 当前登录的用户 |
||||
*/ |
||||
public static final String CURRENT_USER = "currentUser"; |
||||
|
||||
/** |
||||
* 用户名 |
||||
*/ |
||||
public static final String CURRENT_USERNAME = "username"; |
||||
|
||||
/** |
||||
* 消息key |
||||
*/ |
||||
public static String MESSAGE = "message"; |
||||
|
||||
/** |
||||
* 错误key |
||||
*/ |
||||
public static String ERROR = "errorMsg"; |
||||
|
||||
/** |
||||
* 编码格式 |
||||
*/ |
||||
public static String ENCODING = "UTF-8"; |
||||
|
||||
/** |
||||
* 当前在线会话 |
||||
*/ |
||||
public String ONLINE_SESSION = "online_session"; |
||||
|
||||
/** |
||||
* 验证码key |
||||
*/ |
||||
public static final String CURRENT_CAPTCHA = "captcha"; |
||||
|
||||
/** |
||||
* 验证码开关 |
||||
*/ |
||||
public static final String CURRENT_EBABLED = "captchaEbabled"; |
||||
|
||||
/** |
||||
* 验证码开关 |
||||
*/ |
||||
public static final String CURRENT_TYPE = "captchaType"; |
||||
|
||||
/** |
||||
* 验证码 |
||||
*/ |
||||
public static final String CURRENT_VALIDATECODE = "validateCode"; |
||||
|
||||
/** |
||||
* 验证码错误 |
||||
*/ |
||||
public static final String CAPTCHA_ERROR = "captchaError"; |
||||
|
||||
} |
@ -0,0 +1,80 @@
|
||||
package com.ruoyi.common.constant; |
||||
|
||||
/** |
||||
* 用户常量信息 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserConstants |
||||
{ |
||||
|
||||
/** 正常状态 */ |
||||
public static final String NORMAL = "0"; |
||||
|
||||
/** 异常状态 */ |
||||
public static final String EXCEPTION = "1"; |
||||
|
||||
/** 用户封禁状态 */ |
||||
public static final String USER_BLOCKED = "1"; |
||||
|
||||
/** 角色封禁状态 */ |
||||
public static final String ROLE_BLOCKED = "1"; |
||||
|
||||
/** 部门正常状态 */ |
||||
public static final String DEPT_NORMAL = "0"; |
||||
|
||||
/** |
||||
* 用户名长度限制 |
||||
*/ |
||||
public static final int USERNAME_MIN_LENGTH = 2; |
||||
public static final int USERNAME_MAX_LENGTH = 20; |
||||
|
||||
/** 登录名称是否唯一的返回结果码 */ |
||||
public final static String USER_NAME_UNIQUE = "0"; |
||||
public final static String USER_NAME_NOT_UNIQUE = "1"; |
||||
|
||||
/** 手机号码是否唯一的返回结果 */ |
||||
public final static String USER_PHONE_UNIQUE = "0"; |
||||
public final static String USER_PHONE_NOT_UNIQUE = "1"; |
||||
|
||||
/** e-mail 是否唯一的返回结果 */ |
||||
public final static String USER_EMAIL_UNIQUE = "0"; |
||||
public final static String USER_EMAIL_NOT_UNIQUE = "1"; |
||||
|
||||
/** 部门名称是否唯一的返回结果码 */ |
||||
public final static String DEPT_NAME_UNIQUE = "0"; |
||||
public final static String DEPT_NAME_NOT_UNIQUE = "1"; |
||||
|
||||
/** 角色名称是否唯一的返回结果码 */ |
||||
public final static String ROLE_NAME_UNIQUE = "0"; |
||||
public final static String ROLE_NAME_NOT_UNIQUE = "1"; |
||||
|
||||
/** 菜单名称是否唯一的返回结果码 */ |
||||
public final static String MENU_NAME_UNIQUE = "0"; |
||||
public final static String MENU_NAME_NOT_UNIQUE = "1"; |
||||
|
||||
/** 字典类型是否唯一的返回结果码 */ |
||||
public final static String DICT_TYPE_UNIQUE = "0"; |
||||
public final static String DICT_TYPE_NOT_UNIQUE = "1"; |
||||
|
||||
/** 参数键名是否唯一的返回结果码 */ |
||||
public final static String CONFIG_KEY_UNIQUE = "0"; |
||||
public final static String CONFIG_KEY_NOT_UNIQUE = "1"; |
||||
|
||||
/** |
||||
* 密码长度限制 |
||||
*/ |
||||
public static final int PASSWORD_MIN_LENGTH = 5; |
||||
public static final int PASSWORD_MAX_LENGTH = 20; |
||||
|
||||
/** |
||||
* 手机号码格式限制 |
||||
*/ |
||||
public static final String MOBILE_PHONE_NUMBER_PATTERN = "^0{0,1}(13[0-9]|15[0-9]|14[0-9]|18[0-9])[0-9]{8}$"; |
||||
|
||||
/** |
||||
* 邮箱格式限制 |
||||
*/ |
||||
public static final String EMAIL_PATTERN = "^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?"; |
||||
|
||||
} |
@ -0,0 +1,15 @@
|
||||
package com.ruoyi.common.exception; |
||||
|
||||
/** |
||||
* 演示模式异常 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class DemoModeException extends RuntimeException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public DemoModeException() |
||||
{ |
||||
} |
||||
} |
@ -0,0 +1,105 @@
|
||||
package com.ruoyi.common.exception.base; |
||||
|
||||
import org.springframework.util.StringUtils; |
||||
|
||||
import com.ruoyi.common.utils.MessageUtils; |
||||
|
||||
/** |
||||
* 基础异常 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class BaseException extends RuntimeException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* 所属模块 |
||||
*/ |
||||
private String module; |
||||
|
||||
/** |
||||
* 错误码 |
||||
*/ |
||||
private String code; |
||||
|
||||
/** |
||||
* 错误码对应的参数 |
||||
*/ |
||||
private Object[] args; |
||||
|
||||
/** |
||||
* 错误消息 |
||||
*/ |
||||
private String defaultMessage; |
||||
|
||||
public BaseException(String module, String code, Object[] args, String defaultMessage) |
||||
{ |
||||
this.module = module; |
||||
this.code = code; |
||||
this.args = args; |
||||
this.defaultMessage = defaultMessage; |
||||
} |
||||
|
||||
public BaseException(String module, String code, Object[] args) |
||||
{ |
||||
this(module, code, args, null); |
||||
} |
||||
|
||||
public BaseException(String module, String defaultMessage) |
||||
{ |
||||
this(module, null, null, defaultMessage); |
||||
} |
||||
|
||||
public BaseException(String code, Object[] args) |
||||
{ |
||||
this(null, code, args, null); |
||||
} |
||||
|
||||
public BaseException(String defaultMessage) |
||||
{ |
||||
this(null, null, null, defaultMessage); |
||||
} |
||||
|
||||
@Override |
||||
public String getMessage() |
||||
{ |
||||
String message = null; |
||||
if (!StringUtils.isEmpty(code)) |
||||
{ |
||||
message = MessageUtils.message(code, args); |
||||
} |
||||
if (message == null) |
||||
{ |
||||
message = defaultMessage; |
||||
} |
||||
return message; |
||||
} |
||||
|
||||
public String getModule() |
||||
{ |
||||
return module; |
||||
} |
||||
|
||||
public String getCode() |
||||
{ |
||||
return code; |
||||
} |
||||
|
||||
public Object[] getArgs() |
||||
{ |
||||
return args; |
||||
} |
||||
|
||||
public String getDefaultMessage() |
||||
{ |
||||
return defaultMessage; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() |
||||
{ |
||||
return this.getClass() + "{" + "module='" + module + '\'' + ", message='" + getMessage() + '\'' + '}'; |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.ruoyi.common.exception.file; |
||||
|
||||
import org.apache.commons.fileupload.FileUploadException; |
||||
|
||||
/** |
||||
* 文件名超长 误异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class FileNameLengthLimitExceededException extends FileUploadException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
private int length; |
||||
private int maxLength; |
||||
private String filename; |
||||
|
||||
public FileNameLengthLimitExceededException(String filename, int length, int maxLength) |
||||
{ |
||||
super("file name : [" + filename + "], length : [" + length + "], max length : [" + maxLength + "]"); |
||||
this.length = length; |
||||
this.maxLength = maxLength; |
||||
this.filename = filename; |
||||
} |
||||
|
||||
public String getFilename() |
||||
{ |
||||
return filename; |
||||
} |
||||
|
||||
public int getLength() |
||||
{ |
||||
return length; |
||||
} |
||||
|
||||
public int getMaxLength() |
||||
{ |
||||
return maxLength; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,74 @@
|
||||
package com.ruoyi.common.exception.file; |
||||
|
||||
import java.util.Arrays; |
||||
import org.apache.commons.fileupload.FileUploadException; |
||||
|
||||
/** |
||||
* 文件上传 误异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class InvalidExtensionException extends FileUploadException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String[] allowedExtension; |
||||
private String extension; |
||||
private String filename; |
||||
|
||||
public InvalidExtensionException(String[] allowedExtension, String extension, String filename) |
||||
{ |
||||
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" |
||||
+ Arrays.toString(allowedExtension) + "]"); |
||||
this.allowedExtension = allowedExtension; |
||||
this.extension = extension; |
||||
this.filename = filename; |
||||
} |
||||
|
||||
public String[] getAllowedExtension() |
||||
{ |
||||
return allowedExtension; |
||||
} |
||||
|
||||
public String getExtension() |
||||
{ |
||||
return extension; |
||||
} |
||||
|
||||
public String getFilename() |
||||
{ |
||||
return filename; |
||||
} |
||||
|
||||
public static class InvalidImageExtensionException extends InvalidExtensionException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) |
||||
{ |
||||
super(allowedExtension, extension, filename); |
||||
} |
||||
} |
||||
|
||||
public static class InvalidFlashExtensionException extends InvalidExtensionException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) |
||||
{ |
||||
super(allowedExtension, extension, filename); |
||||
} |
||||
} |
||||
|
||||
public static class InvalidMediaExtensionException extends InvalidExtensionException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) |
||||
{ |
||||
super(allowedExtension, extension, filename); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 验证码错误异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class CaptchaException extends UserException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public CaptchaException() |
||||
{ |
||||
super("user.jcaptcha.error", null); |
||||
} |
||||
} |
@ -0,0 +1,18 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 角色锁定异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class RoleBlockedException extends UserException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public RoleBlockedException(String reason) |
||||
{ |
||||
super("role.blocked", new Object[] { reason }); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 用户锁定异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserBlockedException extends UserException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public UserBlockedException(String reason) |
||||
{ |
||||
super("user.blocked", new Object[] { reason }); |
||||
} |
||||
} |
@ -0,0 +1,20 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
import com.ruoyi.common.exception.base.BaseException; |
||||
|
||||
/** |
||||
* 用户信息异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserException extends BaseException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public UserException(String code, Object[] args) |
||||
{ |
||||
super("user", code, args, null); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,17 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 用户不存在异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserNotExistsException extends UserException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public UserNotExistsException() |
||||
{ |
||||
super("user.not.exists", null); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 用户密码不正确或不符合规范异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserPasswordNotMatchException extends UserException |
||||
{ |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public UserPasswordNotMatchException() |
||||
{ |
||||
super("user.password.not.match", null); |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 用户错误记数异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserPasswordRetryLimitCountException extends UserException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public UserPasswordRetryLimitCountException(int retryLimitCount, String password) |
||||
{ |
||||
super("user.password.retry.limit.count", new Object[] { retryLimitCount, password }); |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.ruoyi.common.exception.user; |
||||
|
||||
/** |
||||
* 用户错误最大次数异常类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserPasswordRetryLimitExceedException extends UserException |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public UserPasswordRetryLimitExceedException(int retryLimitCount) |
||||
{ |
||||
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount }); |
||||
} |
||||
} |
@ -0,0 +1,88 @@
|
||||
package com.ruoyi.common.support; |
||||
|
||||
import java.nio.charset.Charset; |
||||
import java.nio.charset.StandardCharsets; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
|
||||
/** |
||||
* 字符集工具类 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
public class CharsetKit |
||||
{ |
||||
/** ISO-8859-1 */ |
||||
public static final String ISO_8859_1 = "ISO-8859-1"; |
||||
/** UTF-8 */ |
||||
public static final String UTF_8 = "UTF-8"; |
||||
/** GBK */ |
||||
public static final String GBK = "GBK"; |
||||
|
||||
/** ISO-8859-1 */ |
||||
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); |
||||
/** UTF-8 */ |
||||
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); |
||||
/** GBK */ |
||||
public static final Charset CHARSET_GBK = Charset.forName(GBK); |
||||
|
||||
/** |
||||
* 转换为Charset对象 |
||||
* |
||||
* @param charset 字符集,为空则返回默认字符集 |
||||
* @return Charset |
||||
*/ |
||||
public static Charset charset(String charset) |
||||
{ |
||||
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); |
||||
} |
||||
|
||||
/** |
||||
* 转换字符串的字符集编码 |
||||
* |
||||
* @param source 字符串 |
||||
* @param srcCharset 源字符集,默认ISO-8859-1 |
||||
* @param destCharset 目标字符集,默认UTF-8 |
||||
* @return 转换后的字符集 |
||||
*/ |
||||
public static String convert(String source, String srcCharset, String destCharset) |
||||
{ |
||||
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); |
||||
} |
||||
|
||||
/** |
||||
* 转换字符串的字符集编码 |
||||
* |
||||
* @param source 字符串 |
||||
* @param srcCharset 源字符集,默认ISO-8859-1 |
||||
* @param destCharset 目标字符集,默认UTF-8 |
||||
* @return 转换后的字符集 |
||||
*/ |
||||
public static String convert(String source, Charset srcCharset, Charset destCharset) |
||||
{ |
||||
if (null == srcCharset) |
||||
{ |
||||
srcCharset = StandardCharsets.ISO_8859_1; |
||||
} |
||||
|
||||
if (null == destCharset) |
||||
{ |
||||
srcCharset = StandardCharsets.UTF_8; |
||||
} |
||||
|
||||
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) |
||||
{ |
||||
return source; |
||||
} |
||||
return new String(source.getBytes(srcCharset), destCharset); |
||||
} |
||||
|
||||
/** |
||||
* @return 系统字符集编码 |
||||
*/ |
||||
public static String systemCharset() |
||||
{ |
||||
return Charset.defaultCharset().name(); |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,95 @@
|
||||
package com.ruoyi.common.support; |
||||
|
||||
import com.ruoyi.common.utils.StringUtils; |
||||
|
||||
/** |
||||
* 字符串格式化 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class StrFormatter |
||||
{ |
||||
|
||||
public static final String EMPTY_JSON = "{}"; |
||||
public static final char C_BACKSLASH = '\\'; |
||||
public static final char C_DELIM_START = '{'; |
||||
public static final char C_DELIM_END = '}'; |
||||
|
||||
/** |
||||
* 格式化字符串<br> |
||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br> |
||||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br> |
||||
* 例:<br> |
||||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br> |
||||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br> |
||||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> |
||||
* |
||||
* @param strPattern 字符串模板 |
||||
* @param argArray 参数列表 |
||||
* @return 结果 |
||||
*/ |
||||
public static String format(final String strPattern, final Object... argArray) |
||||
{ |
||||
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) |
||||
{ |
||||
return strPattern; |
||||
} |
||||
final int strPatternLength = strPattern.length(); |
||||
|
||||
// 初始化定义好的长度以获得更好的性能
|
||||
StringBuilder sbuf = new StringBuilder(strPatternLength + 50); |
||||
|
||||
int handledPosition = 0; |
||||
int delimIndex;// 占位符所在位置
|
||||
for (int argIndex = 0; argIndex < argArray.length; argIndex++) |
||||
{ |
||||
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); |
||||
if (delimIndex == -1) |
||||
{ |
||||
if (handledPosition == 0) |
||||
{ |
||||
return strPattern; |
||||
} |
||||
else |
||||
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
|
||||
sbuf.append(strPattern, handledPosition, strPatternLength); |
||||
return sbuf.toString(); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) |
||||
{ |
||||
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) |
||||
{ |
||||
// 转义符之前还有一个转义符,占位符依旧有效
|
||||
sbuf.append(strPattern, handledPosition, delimIndex - 1); |
||||
sbuf.append(Convert.utf8Str(argArray[argIndex])); |
||||
handledPosition = delimIndex + 2; |
||||
} |
||||
else |
||||
{ |
||||
// 占位符被转义
|
||||
argIndex--; |
||||
sbuf.append(strPattern, handledPosition, delimIndex - 1); |
||||
sbuf.append(C_DELIM_START); |
||||
handledPosition = delimIndex + 1; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
// 正常占位符
|
||||
sbuf.append(strPattern, handledPosition, delimIndex); |
||||
sbuf.append(Convert.utf8Str(argArray[argIndex])); |
||||
handledPosition = delimIndex + 2; |
||||
} |
||||
} |
||||
} |
||||
// append the characters following the last {} pair.
|
||||
// 加入最后一个占位符后所有的字符
|
||||
sbuf.append(strPattern, handledPosition, strPattern.length()); |
||||
|
||||
return sbuf.toString(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,96 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.ruoyi.common.constant.Constants; |
||||
import java.io.BufferedReader; |
||||
import java.io.DataOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* 获取地址类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class AddressUtils |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); |
||||
|
||||
public static final String IP_URL = "http://ip.taobao.com/service/getIpInfo.php"; |
||||
|
||||
/** |
||||
* 获取查询结果 |
||||
* |
||||
* @param urlStr |
||||
* @param content |
||||
* @param encoding |
||||
* @return |
||||
*/ |
||||
private static String sendPost(String content, String encoding) |
||||
{ |
||||
URL url = null; |
||||
HttpURLConnection connection = null; |
||||
try |
||||
{ |
||||
url = new URL(IP_URL); |
||||
connection = (HttpURLConnection) url.openConnection(); |
||||
connection.setConnectTimeout(2000); |
||||
connection.setReadTimeout(2000); |
||||
connection.setDoOutput(true); |
||||
connection.setDoInput(true); |
||||
connection.setRequestMethod("POST"); |
||||
connection.setUseCaches(false); |
||||
connection.connect(); |
||||
DataOutputStream out = new DataOutputStream(connection.getOutputStream()); |
||||
out.writeBytes(content); |
||||
out.flush(); |
||||
out.close(); |
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding)); |
||||
StringBuffer buffer = new StringBuffer(); |
||||
String line = ""; |
||||
while ((line = reader.readLine()) != null) |
||||
{ |
||||
buffer.append(line); |
||||
} |
||||
reader.close(); |
||||
return buffer.toString(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
log.error("温馨提醒:您的主机已经断网,请您检查主机的网络连接"); |
||||
log.error("根据IP获取所在位置----------错误消息:" + e.getMessage()); |
||||
} |
||||
finally |
||||
{ |
||||
if (connection != null) |
||||
{ |
||||
connection.disconnect(); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static String getRealAddressByIP(String ip) |
||||
{ |
||||
String address = ""; |
||||
try |
||||
{ |
||||
address = sendPost("ip=" + ip, Constants.UTF8); |
||||
|
||||
JSONObject json = JSONObject.parseObject(address); |
||||
JSONObject object = json.getObject("data", JSONObject.class); |
||||
String region = object.getString("region"); |
||||
String city = object.getString("city"); |
||||
address = region + " " + city; |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.error("根据IP获取所在位置----------错误消息:" + e.getMessage()); |
||||
} |
||||
return address; |
||||
} |
||||
} |
@ -0,0 +1,100 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import org.apache.commons.lang3.time.DateFormatUtils; |
||||
|
||||
/** |
||||
* 时间工具类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class DateUtils |
||||
{ |
||||
public static String YYYY = "yyyy"; |
||||
|
||||
public static String YYYY_MM = "yyyy-MM"; |
||||
|
||||
public static String YYYY_MM_DD = "yyyy-MM-dd"; |
||||
|
||||
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; |
||||
|
||||
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; |
||||
|
||||
/** |
||||
* 获取当前Date型日期 |
||||
* |
||||
* @return Date() 当前日期 |
||||
*/ |
||||
public static Date getNowDate() |
||||
{ |
||||
return new Date(); |
||||
} |
||||
|
||||
/** |
||||
* 获取当前日期, 默认格式为yyyy-MM-dd |
||||
* |
||||
* @return String |
||||
*/ |
||||
public static String getDate() |
||||
{ |
||||
return dateTimeNow(YYYY_MM_DD); |
||||
} |
||||
|
||||
public static final String getTime() |
||||
{ |
||||
return dateTimeNow(YYYY_MM_DD_HH_MM_SS); |
||||
} |
||||
|
||||
public static final String dateTimeNow() |
||||
{ |
||||
return dateTimeNow(YYYYMMDDHHMMSS); |
||||
} |
||||
|
||||
public static final String dateTimeNow(final String format) |
||||
{ |
||||
return parseDateToStr(format, new Date()); |
||||
} |
||||
|
||||
public static final String dateTime(final Date date) |
||||
{ |
||||
return parseDateToStr(YYYY_MM_DD, date); |
||||
} |
||||
|
||||
public static final String parseDateToStr(final String format, final Date date) |
||||
{ |
||||
return new SimpleDateFormat(format).format(date); |
||||
} |
||||
|
||||
public static final Date dateTime(final String format, final String ts) |
||||
{ |
||||
try |
||||
{ |
||||
return new SimpleDateFormat(format).parse(ts); |
||||
} |
||||
catch (ParseException e) |
||||
{ |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 日期路径 即年/月/日 如2018/08/08 |
||||
*/ |
||||
public static final String datePath() |
||||
{ |
||||
Date now = new Date(); |
||||
return DateFormatUtils.format(now, "yyyy/MM/dd"); |
||||
} |
||||
|
||||
/** |
||||
* 日期路径 即年/月/日 如20180808 |
||||
*/ |
||||
public static final String dateTime() |
||||
{ |
||||
Date now = new Date(); |
||||
return DateFormatUtils.format(now, "yyyyMMdd"); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,155 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import org.apache.shiro.crypto.hash.Md5Hash; |
||||
import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileSizeLimitExceededException; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; |
||||
import com.ruoyi.framework.config.RuoYiConfig; |
||||
|
||||
/** |
||||
* 文件上传工具类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class FileUploadUtils |
||||
{ |
||||
|
||||
// 默认大小 50M
|
||||
public static final long DEFAULT_MAX_SIZE = 52428800; |
||||
|
||||
// 默认上传的地址
|
||||
private static String defaultBaseDir = RuoYiConfig.getProfile(); |
||||
|
||||
// 默认的文件名最大长度
|
||||
public static final int DEFAULT_FILE_NAME_LENGTH = 200; |
||||
|
||||
// 默认文件类型jpg
|
||||
public static final String IMAGE_JPG_EXTENSION = ".jpg"; |
||||
|
||||
private static int counter = 0; |
||||
|
||||
public static void setDefaultBaseDir(String defaultBaseDir) |
||||
{ |
||||
FileUploadUtils.defaultBaseDir = defaultBaseDir; |
||||
} |
||||
|
||||
public static String getDefaultBaseDir() |
||||
{ |
||||
return defaultBaseDir; |
||||
} |
||||
|
||||
/** |
||||
* 以默认配置进行文件上传 |
||||
* |
||||
* @param file 上传的文件 |
||||
* @return 文件名称 |
||||
* @throws Exception |
||||
*/ |
||||
public static final String upload(MultipartFile file) throws IOException |
||||
{ |
||||
try |
||||
{ |
||||
return upload(getDefaultBaseDir(), file, FileUploadUtils.IMAGE_JPG_EXTENSION); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
throw new IOException(e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 根据文件路径上传 |
||||
* |
||||
* @param baseDir 相对应用的基目录 |
||||
* @param file 上传的文件 |
||||
* @return 文件名称 |
||||
* @throws IOException |
||||
*/ |
||||
public static final String upload(String baseDir, MultipartFile file) throws IOException |
||||
{ |
||||
try |
||||
{ |
||||
return upload(baseDir, file, FileUploadUtils.IMAGE_JPG_EXTENSION); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
throw new IOException(e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 文件上传 |
||||
* |
||||
* @param baseDir 相对应用的基目录 |
||||
* @param file 上传的文件 |
||||
* @param needDatePathAndRandomName 是否需要日期目录和随机文件名前缀 |
||||
* @param extension 上传文件类型 |
||||
* @return 返回上传成功的文件名 |
||||
* @throws FileSizeLimitExceededException 如果超出最大大小 |
||||
* @throws FileNameLengthLimitExceededException 文件名太长 |
||||
* @throws IOException 比如读写文件出错时 |
||||
*/ |
||||
public static final String upload(String baseDir, MultipartFile file, String extension) |
||||
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException |
||||
{ |
||||
|
||||
int fileNamelength = file.getOriginalFilename().length(); |
||||
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) |
||||
{ |
||||
throw new FileNameLengthLimitExceededException(file.getOriginalFilename(), fileNamelength, |
||||
FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); |
||||
} |
||||
|
||||
assertAllowed(file); |
||||
|
||||
String fileName = encodingFilename(file.getOriginalFilename(), extension); |
||||
|
||||
File desc = getAbsoluteFile(baseDir, baseDir + fileName); |
||||
file.transferTo(desc); |
||||
return fileName; |
||||
} |
||||
|
||||
private static final File getAbsoluteFile(String uploadDir, String filename) throws IOException |
||||
{ |
||||
File desc = new File(File.separator + filename); |
||||
|
||||
if (!desc.getParentFile().exists()) |
||||
{ |
||||
desc.getParentFile().mkdirs(); |
||||
} |
||||
if (!desc.exists()) |
||||
{ |
||||
desc.createNewFile(); |
||||
} |
||||
return desc; |
||||
} |
||||
|
||||
/** |
||||
* 编码文件名 |
||||
*/ |
||||
private static final String encodingFilename(String filename, String extension) |
||||
{ |
||||
filename = filename.replace("_", " "); |
||||
filename = new Md5Hash(filename + System.nanoTime() + counter++).toHex().toString() + extension; |
||||
return filename; |
||||
} |
||||
|
||||
/** |
||||
* 文件大小校验 |
||||
* |
||||
* @param file 上传的文件 |
||||
* @return |
||||
* @throws FileSizeLimitExceededException 如果超出最大大小 |
||||
*/ |
||||
public static final void assertAllowed(MultipartFile file) throws FileSizeLimitExceededException |
||||
{ |
||||
long size = file.getSize(); |
||||
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) |
||||
{ |
||||
throw new FileSizeLimitExceededException("not allowed upload upload", size, DEFAULT_MAX_SIZE); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,43 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
/** |
||||
* 获取IP方法 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class IpUtils |
||||
{ |
||||
public static String getIpAddr(HttpServletRequest request) |
||||
{ |
||||
if (request == null) |
||||
{ |
||||
return "unknown"; |
||||
} |
||||
String ip = request.getHeader("x-forwarded-for"); |
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
||||
{ |
||||
ip = request.getHeader("Proxy-Client-IP"); |
||||
} |
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
||||
{ |
||||
ip = request.getHeader("X-Forwarded-For"); |
||||
} |
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
||||
{ |
||||
ip = request.getHeader("WL-Proxy-Client-IP"); |
||||
} |
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
||||
{ |
||||
ip = request.getHeader("X-Real-IP"); |
||||
} |
||||
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) |
||||
{ |
||||
ip = request.getRemoteAddr(); |
||||
} |
||||
|
||||
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; |
||||
} |
||||
} |
@ -0,0 +1,136 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import com.alibaba.fastjson.JSON; |
||||
import org.apache.shiro.SecurityUtils; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 处理并记录日志文件 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class LogUtils |
||||
{ |
||||
|
||||
public static final Logger ERROR_LOG = LoggerFactory.getLogger("sys-error"); |
||||
public static final Logger ACCESS_LOG = LoggerFactory.getLogger("sys-access"); |
||||
|
||||
/** |
||||
* 记录访问日志 [username][jsessionid][ip][accept][UserAgent][url][params][Referer] |
||||
* |
||||
* @param request |
||||
*/ |
||||
public static void logAccess(HttpServletRequest request) |
||||
{ |
||||
String username = getUsername(); |
||||
String jsessionId = request.getRequestedSessionId(); |
||||
String ip = IpUtils.getIpAddr(request); |
||||
String accept = request.getHeader("accept"); |
||||
String userAgent = request.getHeader("User-Agent"); |
||||
String url = request.getRequestURI(); |
||||
String params = getParams(request); |
||||
|
||||
StringBuilder s = new StringBuilder(); |
||||
s.append(getBlock(username)); |
||||
s.append(getBlock(jsessionId)); |
||||
s.append(getBlock(ip)); |
||||
s.append(getBlock(accept)); |
||||
s.append(getBlock(userAgent)); |
||||
s.append(getBlock(url)); |
||||
s.append(getBlock(params)); |
||||
s.append(getBlock(request.getHeader("Referer"))); |
||||
getAccessLog().info(s.toString()); |
||||
} |
||||
|
||||
/** |
||||
* 记录异常错误 格式 [exception] |
||||
* |
||||
* @param message |
||||
* @param e |
||||
*/ |
||||
public static void logError(String message, Throwable e) |
||||
{ |
||||
String username = getUsername(); |
||||
StringBuilder s = new StringBuilder(); |
||||
s.append(getBlock("exception")); |
||||
s.append(getBlock(username)); |
||||
s.append(getBlock(message)); |
||||
ERROR_LOG.error(s.toString(), e); |
||||
} |
||||
|
||||
/** |
||||
* 记录页面错误 错误日志记录 [page/eception][username][statusCode][errorMessage][servletName][uri][exceptionName][ip][exception] |
||||
* |
||||
* @param request |
||||
*/ |
||||
public static void logPageError(HttpServletRequest request) |
||||
{ |
||||
String username = getUsername(); |
||||
|
||||
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); |
||||
String message = (String) request.getAttribute("javax.servlet.error.message"); |
||||
String uri = (String) request.getAttribute("javax.servlet.error.request_uri"); |
||||
Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception"); |
||||
|
||||
if (statusCode == null) |
||||
{ |
||||
statusCode = 0; |
||||
} |
||||
|
||||
StringBuilder s = new StringBuilder(); |
||||
s.append(getBlock(t == null ? "page" : "exception")); |
||||
s.append(getBlock(username)); |
||||
s.append(getBlock(statusCode)); |
||||
s.append(getBlock(message)); |
||||
s.append(getBlock(IpUtils.getIpAddr(request))); |
||||
|
||||
s.append(getBlock(uri)); |
||||
s.append(getBlock(request.getHeader("Referer"))); |
||||
StringWriter sw = new StringWriter(); |
||||
|
||||
while (t != null) |
||||
{ |
||||
t.printStackTrace(new PrintWriter(sw)); |
||||
t = t.getCause(); |
||||
} |
||||
s.append(getBlock(sw.toString())); |
||||
getErrorLog().error(s.toString()); |
||||
|
||||
} |
||||
|
||||
public static String getBlock(Object msg) |
||||
{ |
||||
if (msg == null) |
||||
{ |
||||
msg = ""; |
||||
} |
||||
return "[" + msg.toString() + "]"; |
||||
} |
||||
|
||||
protected static String getParams(HttpServletRequest request) |
||||
{ |
||||
Map<String, String[]> params = request.getParameterMap(); |
||||
return JSON.toJSONString(params); |
||||
} |
||||
|
||||
protected static String getUsername() |
||||
{ |
||||
return (String) SecurityUtils.getSubject().getPrincipal(); |
||||
} |
||||
|
||||
public static Logger getAccessLog() |
||||
{ |
||||
return ACCESS_LOG; |
||||
} |
||||
|
||||
public static Logger getErrorLog() |
||||
{ |
||||
return ERROR_LOG; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,51 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
import java.util.Map.Entry; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
/** |
||||
* Map通用处理方法 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class MapDataUtil |
||||
{ |
||||
public static Map<String, Object> convertDataMap(HttpServletRequest request) |
||||
{ |
||||
Map<String, String[]> properties = request.getParameterMap(); |
||||
Map<String, Object> returnMap = new HashMap<String, Object>(); |
||||
Iterator<?> entries = properties.entrySet().iterator(); |
||||
Map.Entry<?, ?> entry; |
||||
String name = ""; |
||||
String value = ""; |
||||
while (entries.hasNext()) |
||||
{ |
||||
entry = (Entry<?, ?>) entries.next(); |
||||
name = (String) entry.getKey(); |
||||
Object valueObj = entry.getValue(); |
||||
if (null == valueObj) |
||||
{ |
||||
value = ""; |
||||
} |
||||
else if (valueObj instanceof String[]) |
||||
{ |
||||
String[] values = (String[]) valueObj; |
||||
for (int i = 0; i < values.length; i++) |
||||
{ |
||||
value = values[i] + ","; |
||||
} |
||||
value = value.substring(0, value.length() - 1); |
||||
} |
||||
else |
||||
{ |
||||
value = valueObj.toString(); |
||||
} |
||||
returnMap.put(name, value); |
||||
} |
||||
return returnMap; |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import org.springframework.context.MessageSource; |
||||
import com.ruoyi.common.utils.spring.SpringUtils; |
||||
|
||||
/** |
||||
* 获取i18n资源文件 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class MessageUtils |
||||
{ |
||||
|
||||
/** |
||||
* 根据消息键和参数 获取消息 委托给spring messageSource |
||||
* |
||||
* @param code 消息键 |
||||
* @param args 参数 |
||||
* @return |
||||
*/ |
||||
public static String message(String code, Object... args) |
||||
{ |
||||
MessageSource messageSource = SpringUtils.getBean(MessageSource.class); |
||||
return messageSource.getMessage(code, args, null); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,137 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import java.io.IOException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import javax.servlet.http.HttpSession; |
||||
import org.springframework.web.context.request.RequestAttributes; |
||||
import org.springframework.web.context.request.RequestContextHolder; |
||||
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
import com.ruoyi.common.support.Convert; |
||||
|
||||
/** |
||||
* 客户端工具类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class ServletUtils |
||||
{ |
||||
/** |
||||
* 获取String参数 |
||||
*/ |
||||
public static String getParameter(String name) |
||||
{ |
||||
return getRequest().getParameter(name); |
||||
} |
||||
|
||||
/** |
||||
* 获取String参数 |
||||
*/ |
||||
public static String getParameter(String name, String defaultValue) |
||||
{ |
||||
return Convert.toStr(getRequest().getParameter(name), defaultValue); |
||||
} |
||||
|
||||
/** |
||||
* 获取Integer参数 |
||||
*/ |
||||
public static Integer getParameterToInt(String name) |
||||
{ |
||||
return Convert.toInt(getRequest().getParameter(name)); |
||||
} |
||||
|
||||
/** |
||||
* 获取Integer参数 |
||||
*/ |
||||
public static Integer getParameterToInt(String name, Integer defaultValue) |
||||
{ |
||||
return Convert.toInt(getRequest().getParameter(name), defaultValue); |
||||
} |
||||
|
||||
/** |
||||
* 获取request |
||||
*/ |
||||
public static HttpServletRequest getRequest() |
||||
{ |
||||
return getRequestAttributes().getRequest(); |
||||
} |
||||
|
||||
/** |
||||
* 获取response |
||||
*/ |
||||
public static HttpServletResponse getResponse() |
||||
{ |
||||
return getRequestAttributes().getResponse(); |
||||
} |
||||
|
||||
/** |
||||
* 获取session |
||||
*/ |
||||
public static HttpSession getSession() |
||||
{ |
||||
return getRequest().getSession(); |
||||
} |
||||
|
||||
public static ServletRequestAttributes getRequestAttributes() |
||||
{ |
||||
RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); |
||||
return (ServletRequestAttributes) attributes; |
||||
} |
||||
|
||||
/** |
||||
* 将字符串渲染到客户端 |
||||
* |
||||
* @param response 渲染对象 |
||||
* @param string 待渲染的字符串 |
||||
* @return null |
||||
*/ |
||||
public static String renderString(HttpServletResponse response, String string) |
||||
{ |
||||
try |
||||
{ |
||||
response.setContentType("application/json"); |
||||
response.setCharacterEncoding("utf-8"); |
||||
response.getWriter().print(string); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
e.printStackTrace(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* 是否是Ajax异步请求 |
||||
* |
||||
* @param request |
||||
*/ |
||||
public static boolean isAjaxRequest(HttpServletRequest request) |
||||
{ |
||||
|
||||
String accept = request.getHeader("accept"); |
||||
if (accept != null && accept.indexOf("application/json") != -1) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
String xRequestedWith = request.getHeader("X-Requested-With"); |
||||
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
String uri = request.getRequestURI(); |
||||
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
String ajax = request.getParameter("__ajax"); |
||||
if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,373 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
|
||||
import org.apache.commons.lang.text.StrBuilder; |
||||
|
||||
import com.ruoyi.common.support.StrFormatter; |
||||
|
||||
/** |
||||
* 字符串工具类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class StringUtils |
||||
{ |
||||
/** 空字符串 */ |
||||
private static final String NULLSTR = ""; |
||||
|
||||
/** 下划线 */ |
||||
private static final char SEPARATOR = '_'; |
||||
|
||||
/** |
||||
* 获取参数不为空值 |
||||
* |
||||
* @param value defaultValue 要判断的value |
||||
* @return value 返回值 |
||||
*/ |
||||
public static <T> T nvl(T value, T defaultValue) |
||||
{ |
||||
return value != null ? value : defaultValue; |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个Collection是否为空, 包含List,Set,Queue |
||||
* |
||||
* @param coll 要判断的Collection |
||||
* @return true:为空 false:非空 |
||||
*/ |
||||
public static boolean isEmpty(Collection<?> coll) |
||||
{ |
||||
return isNull(coll) || coll.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个Collection是否非空,包含List,Set,Queue |
||||
* |
||||
* @param coll 要判断的Collection |
||||
* @return true:非空 false:空 |
||||
*/ |
||||
public static boolean isNotEmpty(Collection<?> coll) |
||||
{ |
||||
return !isEmpty(coll); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个对象数组是否为空 |
||||
* |
||||
* @param objects 要判断的对象数组 |
||||
** @return true:为空 false:非空 |
||||
*/ |
||||
public static boolean isEmpty(Object[] objects) |
||||
{ |
||||
return isNull(objects) || (objects.length == 0); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个对象数组是否非空 |
||||
* |
||||
* @param objects 要判断的对象数组 |
||||
* @return true:非空 false:空 |
||||
*/ |
||||
public static boolean isNotEmpty(Object[] objects) |
||||
{ |
||||
return !isEmpty(objects); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个Map是否为空 |
||||
* |
||||
* @param map 要判断的Map |
||||
* @return true:为空 false:非空 |
||||
*/ |
||||
public static boolean isEmpty(Map<?, ?> map) |
||||
{ |
||||
return isNull(map) || map.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个Map是否为空 |
||||
* |
||||
* @param map 要判断的Map |
||||
* @return true:非空 false:空 |
||||
*/ |
||||
public static boolean isNotEmpty(Map<?, ?> map) |
||||
{ |
||||
return !isEmpty(map); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个字符串是否为空串 |
||||
* |
||||
* @param str String |
||||
* @return true:为空 false:非空 |
||||
*/ |
||||
public static boolean isEmpty(String str) |
||||
{ |
||||
return isNull(str) || NULLSTR.equals(str.trim()); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个字符串是否为非空串 |
||||
* |
||||
* @param str String |
||||
* @return true:非空串 false:空串 |
||||
*/ |
||||
public static boolean isNotEmpty(String str) |
||||
{ |
||||
return !isEmpty(str); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个对象是否为空 |
||||
* |
||||
* @param object Object |
||||
* @return true:为空 false:非空 |
||||
*/ |
||||
public static boolean isNull(Object object) |
||||
{ |
||||
return object == null; |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个对象是否非空 |
||||
* |
||||
* @param object Object |
||||
* @return true:非空 false:空 |
||||
*/ |
||||
public static boolean isNotNull(Object object) |
||||
{ |
||||
return !isNull(object); |
||||
} |
||||
|
||||
/** |
||||
* * 判断一个对象是否是数组类型(Java基本型别的数组) |
||||
* |
||||
* @param object 对象 |
||||
* @return true:是数组 false:不是数组 |
||||
*/ |
||||
public static boolean isArray(Object object) |
||||
{ |
||||
return isNotNull(object) && object.getClass().isArray(); |
||||
} |
||||
|
||||
/** |
||||
* 去空格 |
||||
*/ |
||||
public static String trim(String str) |
||||
{ |
||||
return (str == null ? "" : str.trim()); |
||||
} |
||||
|
||||
/** |
||||
* 截取字符串 |
||||
* |
||||
* @param str 字符串 |
||||
* @param start 开始 |
||||
* @return 结果 |
||||
*/ |
||||
public static String substring(final String str, int start) |
||||
{ |
||||
if (str == null) |
||||
{ |
||||
return NULLSTR; |
||||
} |
||||
|
||||
if (start < 0) |
||||
{ |
||||
start = str.length() + start; |
||||
} |
||||
|
||||
if (start < 0) |
||||
{ |
||||
start = 0; |
||||
} |
||||
if (start > str.length()) |
||||
{ |
||||
return NULLSTR; |
||||
} |
||||
|
||||
return str.substring(start); |
||||
} |
||||
|
||||
/** |
||||
* 截取字符串 |
||||
* |
||||
* @param str 字符串 |
||||
* @param start 开始 |
||||
* @param end 结束 |
||||
* @return 结果 |
||||
*/ |
||||
public static String substring(final String str, int start, int end) |
||||
{ |
||||
if (str == null) |
||||
{ |
||||
return NULLSTR; |
||||
} |
||||
|
||||
if (end < 0) |
||||
{ |
||||
end = str.length() + end; |
||||
} |
||||
if (start < 0) |
||||
{ |
||||
start = str.length() + start; |
||||
} |
||||
|
||||
if (end > str.length()) |
||||
{ |
||||
end = str.length(); |
||||
} |
||||
|
||||
if (start > end) |
||||
{ |
||||
return NULLSTR; |
||||
} |
||||
|
||||
if (start < 0) |
||||
{ |
||||
start = 0; |
||||
} |
||||
if (end < 0) |
||||
{ |
||||
end = 0; |
||||
} |
||||
|
||||
return str.substring(start, end); |
||||
} |
||||
|
||||
/** |
||||
* 格式化文本, {} 表示占位符<br> |
||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br> |
||||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br> |
||||
* 例:<br> |
||||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br> |
||||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br> |
||||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> |
||||
* |
||||
* @param template 文本模板,被替换的部分用 {} 表示 |
||||
* @param params 参数值 |
||||
* @return 格式化后的文本 |
||||
*/ |
||||
public static String format(String template, Object... params) |
||||
{ |
||||
if (isEmpty(params) || isEmpty(template)) |
||||
{ |
||||
return template; |
||||
} |
||||
return StrFormatter.format(template, params); |
||||
} |
||||
|
||||
/** |
||||
* 驼峰首字符小写 |
||||
*/ |
||||
public static String uncapitalize(String str) |
||||
{ |
||||
int strLen; |
||||
if (str == null || (strLen = str.length()) == 0) |
||||
{ |
||||
return str; |
||||
} |
||||
return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString(); |
||||
} |
||||
|
||||
/** |
||||
* 下划线转驼峰命名 |
||||
*/ |
||||
public static String toUnderScoreCase(String s) |
||||
{ |
||||
if (s == null) |
||||
{ |
||||
return null; |
||||
} |
||||
StringBuilder sb = new StringBuilder(); |
||||
boolean upperCase = false; |
||||
for (int i = 0; i < s.length(); i++) |
||||
{ |
||||
char c = s.charAt(i); |
||||
|
||||
boolean nextUpperCase = true; |
||||
|
||||
if (i < (s.length() - 1)) |
||||
{ |
||||
nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); |
||||
} |
||||
|
||||
if ((i > 0) && Character.isUpperCase(c)) |
||||
{ |
||||
if (!upperCase || !nextUpperCase) |
||||
{ |
||||
sb.append(SEPARATOR); |
||||
} |
||||
upperCase = true; |
||||
} |
||||
else |
||||
{ |
||||
upperCase = false; |
||||
} |
||||
|
||||
sb.append(Character.toLowerCase(c)); |
||||
} |
||||
|
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* 是否包含字符串 |
||||
* |
||||
* @param str 验证字符串 |
||||
* @param strs 字符串组 |
||||
* @return 包含返回true |
||||
*/ |
||||
public static boolean inStringIgnoreCase(String str, String... strs) |
||||
{ |
||||
if (str != null && strs != null) |
||||
{ |
||||
for (String s : strs) |
||||
{ |
||||
if (str.equalsIgnoreCase(trim(s))) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld |
||||
* |
||||
* @param name 转换前的下划线大写方式命名的字符串 |
||||
* @return 转换后的驼峰式命名的字符串 |
||||
*/ |
||||
public static String convertToCamelCase(String name) |
||||
{ |
||||
StringBuilder result = new StringBuilder(); |
||||
// 快速检查
|
||||
if (name == null || name.isEmpty()) |
||||
{ |
||||
// 没必要转换
|
||||
return ""; |
||||
} |
||||
else if (!name.contains("_")) |
||||
{ |
||||
// 不含下划线,仅将首字母大写
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1); |
||||
} |
||||
// 用下划线将原始字符串分割
|
||||
String[] camels = name.split("_"); |
||||
for (String camel : camels) |
||||
{ |
||||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||||
if (camel.isEmpty()) |
||||
{ |
||||
continue; |
||||
} |
||||
// 首字母大写
|
||||
result.append(camel.substring(0, 1).toUpperCase()); |
||||
result.append(camel.substring(1).toLowerCase()); |
||||
} |
||||
return result.toString(); |
||||
} |
||||
} |
@ -0,0 +1,71 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import com.ruoyi.common.constant.Constants; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.common.utils.spring.SpringUtils; |
||||
import com.ruoyi.project.monitor.logininfor.domain.Logininfor; |
||||
import com.ruoyi.project.monitor.logininfor.service.LogininforServiceImpl; |
||||
import eu.bitwalker.useragentutils.UserAgent; |
||||
|
||||
/** |
||||
* 记录用户日志信息 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class SystemLogUtils |
||||
{ |
||||
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); |
||||
|
||||
/** |
||||
* 记录格式 [ip][用户名][操作][错误消息] |
||||
* <p/> |
||||
* 注意操作如下: loginError 登录失败 loginSuccess 登录成功 passwordError 密码错误 changePassword 修改密码 changeStatus 修改状态 |
||||
* |
||||
* @param username |
||||
* @param op |
||||
* @param msg |
||||
* @param args |
||||
*/ |
||||
public static void log(String username, String status, String msg, Object... args) |
||||
{ |
||||
StringBuilder s = new StringBuilder(); |
||||
s.append(LogUtils.getBlock(ShiroUtils.getIp())); |
||||
s.append(AddressUtils.getRealAddressByIP(ShiroUtils.getIp())); |
||||
s.append(LogUtils.getBlock(username)); |
||||
s.append(LogUtils.getBlock(status)); |
||||
s.append(LogUtils.getBlock(msg)); |
||||
|
||||
sys_user_logger.info(s.toString(), args); |
||||
|
||||
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) |
||||
{ |
||||
saveOpLog(username, msg, Constants.SUCCESS); |
||||
} |
||||
else if (Constants.LOGIN_FAIL.equals(status)) |
||||
{ |
||||
saveOpLog(username, msg, Constants.FAIL); |
||||
} |
||||
} |
||||
|
||||
public static void saveOpLog(String username, String message, String status) |
||||
{ |
||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); |
||||
// 获取客户端操作系统
|
||||
String os = userAgent.getOperatingSystem().getName(); |
||||
// 获取客户端浏览器
|
||||
String browser = userAgent.getBrowser().getName(); |
||||
LogininforServiceImpl logininforService = SpringUtils.getBean(LogininforServiceImpl.class); |
||||
Logininfor logininfor = new Logininfor(); |
||||
logininfor.setLoginName(username); |
||||
logininfor.setStatus(status); |
||||
logininfor.setIpaddr(ShiroUtils.getIp()); |
||||
logininfor.setLoginLocation(AddressUtils.getRealAddressByIP(ShiroUtils.getIp())); |
||||
logininfor.setBrowser(browser); |
||||
logininfor.setOs(os); |
||||
logininfor.setMsg(message); |
||||
logininforService.insertLogininfor(logininfor); |
||||
} |
||||
} |
@ -0,0 +1,145 @@
|
||||
package com.ruoyi.common.utils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
|
||||
import com.ruoyi.project.system.menu.domain.Menu; |
||||
|
||||
/** |
||||
* 权限数据处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class TreeUtils |
||||
{ |
||||
|
||||
/** |
||||
* 根据父节点的ID获取所有子节点 |
||||
* |
||||
* @param list 分类表 |
||||
* @param typeId 传入的父节点ID |
||||
* @return String |
||||
*/ |
||||
public static List<Menu> getChildPerms(List<Menu> list, int parentId) |
||||
{ |
||||
List<Menu> returnList = new ArrayList<Menu>(); |
||||
for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();) |
||||
{ |
||||
Menu t = (Menu) iterator.next(); |
||||
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
|
||||
if (t.getParentId() == parentId) |
||||
{ |
||||
recursionFn(list, t); |
||||
returnList.add(t); |
||||
} |
||||
} |
||||
return returnList; |
||||
} |
||||
|
||||
/** |
||||
* 递归列表 |
||||
* |
||||
* @param list |
||||
* @param Menu |
||||
*/ |
||||
private static void recursionFn(List<Menu> list, Menu t) |
||||
{ |
||||
// 得到子节点列表
|
||||
List<Menu> childList = getChildList(list, t); |
||||
t.setChildren(childList); |
||||
for (Menu tChild : childList) |
||||
{ |
||||
if (hasChild(list, tChild)) |
||||
{ |
||||
// 判断是否有子节点
|
||||
Iterator<Menu> it = childList.iterator(); |
||||
while (it.hasNext()) |
||||
{ |
||||
Menu n = (Menu) it.next(); |
||||
recursionFn(list, n); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 得到子节点列表 |
||||
*/ |
||||
private static List<Menu> getChildList(List<Menu> list, Menu t) |
||||
{ |
||||
|
||||
List<Menu> tlist = new ArrayList<Menu>(); |
||||
Iterator<Menu> it = list.iterator(); |
||||
while (it.hasNext()) |
||||
{ |
||||
Menu n = (Menu) it.next(); |
||||
if (n.getParentId().longValue() == t.getMenuId().longValue()) |
||||
{ |
||||
tlist.add(n); |
||||
} |
||||
} |
||||
return tlist; |
||||
} |
||||
|
||||
List<Menu> returnList = new ArrayList<Menu>(); |
||||
|
||||
/** |
||||
* 根据父节点的ID获取所有子节点 |
||||
* |
||||
* @param list 分类表 |
||||
* @param typeId 传入的父节点ID |
||||
* @param prefix 子节点前缀 |
||||
*/ |
||||
public List<Menu> getChildPerms(List<Menu> list, int typeId, String prefix) |
||||
{ |
||||
if (list == null) |
||||
{ |
||||
return null; |
||||
} |
||||
for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();) |
||||
{ |
||||
Menu node = (Menu) iterator.next(); |
||||
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
|
||||
if (node.getParentId() == typeId) |
||||
{ |
||||
recursionFn(list, node, prefix); |
||||
} |
||||
// 二、遍历所有的父节点下的所有子节点
|
||||
/* |
||||
* if (node.getParentId()==0) { recursionFn(list, node); } |
||||
*/ |
||||
} |
||||
return returnList; |
||||
} |
||||
|
||||
private void recursionFn(List<Menu> list, Menu node, String p) |
||||
{ |
||||
// 得到子节点列表
|
||||
List<Menu> childList = getChildList(list, node); |
||||
if (hasChild(list, node)) |
||||
{ |
||||
// 判断是否有子节点
|
||||
returnList.add(node); |
||||
Iterator<Menu> it = childList.iterator(); |
||||
while (it.hasNext()) |
||||
{ |
||||
Menu n = (Menu) it.next(); |
||||
n.setMenuName(p + n.getMenuName()); |
||||
recursionFn(list, n, p + p); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
returnList.add(node); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 判断是否有子节点 |
||||
*/ |
||||
private static boolean hasChild(List<Menu> list, Menu t) |
||||
{ |
||||
return getChildList(list, t).size() > 0 ? true : false; |
||||
} |
||||
} |
@ -0,0 +1,409 @@
|
||||
package com.ruoyi.common.utils.poi; |
||||
|
||||
import java.io.FileNotFoundException; |
||||
import java.io.FileOutputStream; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.lang.reflect.Field; |
||||
import java.math.BigDecimal; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.UUID; |
||||
import org.apache.poi.hssf.usermodel.DVConstraint; |
||||
import org.apache.poi.hssf.usermodel.HSSFCell; |
||||
import org.apache.poi.hssf.usermodel.HSSFCellStyle; |
||||
import org.apache.poi.hssf.usermodel.HSSFDataValidation; |
||||
import org.apache.poi.hssf.usermodel.HSSFFont; |
||||
import org.apache.poi.hssf.usermodel.HSSFRow; |
||||
import org.apache.poi.hssf.usermodel.HSSFSheet; |
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
||||
import org.apache.poi.hssf.util.HSSFColor; |
||||
import org.apache.poi.ss.usermodel.Cell; |
||||
import org.apache.poi.ss.usermodel.CellStyle; |
||||
import org.apache.poi.ss.usermodel.Row; |
||||
import org.apache.poi.ss.usermodel.Sheet; |
||||
import org.apache.poi.ss.usermodel.Workbook; |
||||
import org.apache.poi.ss.usermodel.WorkbookFactory; |
||||
import org.apache.poi.ss.util.CellRangeAddressList; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.util.ResourceUtils; |
||||
import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
||||
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager; |
||||
import com.ruoyi.framework.web.domain.AjaxResult; |
||||
|
||||
/** |
||||
* Excel相关处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class ExcelUtil<T> |
||||
{ |
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class); |
||||
|
||||
public Class<T> clazz; |
||||
|
||||
public ExcelUtil(Class<T> clazz) |
||||
{ |
||||
this.clazz = clazz; |
||||
} |
||||
|
||||
public List<T> importExcel(String sheetName, InputStream input) throws Exception |
||||
{ |
||||
List<T> list = new ArrayList<T>(); |
||||
|
||||
Workbook workbook = WorkbookFactory.create(input); |
||||
Sheet sheet = workbook.getSheet(sheetName); |
||||
if (!sheetName.trim().equals("")) |
||||
{ |
||||
sheet = workbook.getSheet(sheetName); // 如果指定sheet名,则取指定sheet中的内容.
|
||||
} |
||||
if (sheet == null) |
||||
{ |
||||
sheet = workbook.getSheetAt(0); // 如果传入的sheet名不存在则默认指向第1个sheet.
|
||||
} |
||||
int rows = sheet.getPhysicalNumberOfRows(); |
||||
|
||||
if (rows > 0) |
||||
{ |
||||
// 有数据时才处理
|
||||
Field[] allFields = clazz.getDeclaredFields(); // 得到类的所有field.
|
||||
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>(); // 定义一个map用于存放列的序号和field.
|
||||
for (Field field : allFields) |
||||
{ |
||||
// 将有注解的field存放到map中.
|
||||
if (field.isAnnotationPresent(Excel.class)) |
||||
{ |
||||
Excel attr = field.getAnnotation(Excel.class); |
||||
int col = getExcelCol(attr.column());// 获得列号
|
||||
field.setAccessible(true);// 设置类的私有字段属性可访问.
|
||||
fieldsMap.put(col, field); |
||||
} |
||||
} |
||||
for (int i = 1; i < rows; i++) |
||||
{ |
||||
// 从第2行开始取数据,默认第一行是表头.
|
||||
Row row = sheet.getRow(i); |
||||
int cellNum = sheet.getRow(0).getPhysicalNumberOfCells(); |
||||
T entity = null; |
||||
for (int j = 0; j < cellNum; j++) |
||||
{ |
||||
Cell cell = row.getCell(j); |
||||
if (cell == null) |
||||
{ |
||||
continue; |
||||
} |
||||
else |
||||
{ |
||||
// 先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 by zhuyangyong 20171228
|
||||
row.getCell(j).setCellType(Cell.CELL_TYPE_STRING); |
||||
cell = row.getCell(j); |
||||
} |
||||
|
||||
String c = cell.getStringCellValue(); |
||||
if (c.equals("")) |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
entity = (entity == null ? clazz.newInstance() : entity);// 如果不存在实例则新建.
|
||||
Field field = fieldsMap.get(j);// 从map中得到对应列的field.
|
||||
// 取得类型,并根据对象类型设置值.
|
||||
Class<?> fieldType = field.getType(); |
||||
if (String.class == fieldType) |
||||
{ |
||||
field.set(entity, String.valueOf(c)); |
||||
} |
||||
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) |
||||
{ |
||||
field.set(entity, Integer.parseInt(c)); |
||||
} |
||||
else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) |
||||
{ |
||||
field.set(entity, Long.valueOf(c)); |
||||
} |
||||
else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) |
||||
{ |
||||
field.set(entity, Float.valueOf(c)); |
||||
} |
||||
else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) |
||||
{ |
||||
field.set(entity, Short.valueOf(c)); |
||||
} |
||||
else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) |
||||
{ |
||||
field.set(entity, Double.valueOf(c)); |
||||
} |
||||
else if (Character.TYPE == fieldType) |
||||
{ |
||||
if ((c != null) && (c.length() > 0)) |
||||
{ |
||||
field.set(entity, Character.valueOf(c.charAt(0))); |
||||
} |
||||
} |
||||
else if (java.util.Date.class == fieldType) |
||||
{ |
||||
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) |
||||
{ |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
||||
cell.setCellValue(sdf.format(cell.getNumericCellValue())); |
||||
c = sdf.format(cell.getNumericCellValue()); |
||||
} |
||||
else |
||||
{ |
||||
c = cell.getStringCellValue(); |
||||
} |
||||
} |
||||
else if (java.math.BigDecimal.class == fieldType) |
||||
{ |
||||
c = cell.getStringCellValue(); |
||||
} |
||||
} |
||||
if (entity != null) |
||||
{ |
||||
list.add(entity); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* 对list数据源将其里面的数据导入到excel表单 |
||||
* |
||||
* @param sheetName 工作表的名称 |
||||
*/ |
||||
public AjaxResult exportExcel(List<T> list, String sheetName) |
||||
{ |
||||
Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段
|
||||
List<Field> fields = new ArrayList<Field>(); |
||||
// 得到所有field并存放到一个list中.
|
||||
for (Field field : allFields) |
||||
{ |
||||
if (field.isAnnotationPresent(Excel.class)) |
||||
{ |
||||
fields.add(field); |
||||
} |
||||
} |
||||
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();// 产生工作薄对象
|
||||
// excel2003中每个sheet中最多有65536行
|
||||
int sheetSize = 65536; |
||||
double sheetNo = Math.ceil(list.size() / sheetSize);// 取出一共有多少个sheet.
|
||||
for (int index = 0; index <= sheetNo; index++) |
||||
{ |
||||
HSSFSheet sheet = workbook.createSheet();// 产生工作表对象
|
||||
if (sheetNo == 0) |
||||
{ |
||||
workbook.setSheetName(index, sheetName); |
||||
} |
||||
else |
||||
{ |
||||
workbook.setSheetName(index, sheetName + index);// 设置工作表的名称.
|
||||
} |
||||
HSSFRow row; |
||||
HSSFCell cell; // 产生单元格
|
||||
|
||||
row = sheet.createRow(0); // 产生一行
|
||||
// 写入各个字段的列头名称
|
||||
for (int i = 0; i < fields.size(); i++) |
||||
{ |
||||
Field field = fields.get(i); |
||||
Excel attr = field.getAnnotation(Excel.class); |
||||
int col = getExcelCol(attr.column()); // 获得列号
|
||||
cell = row.createCell(col); // 创建列
|
||||
cell.setCellType(HSSFCell.CELL_TYPE_STRING); // 设置列中写入内容为String类型
|
||||
HSSFCellStyle cellStyle = workbook.createCellStyle(); |
||||
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); |
||||
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); |
||||
if (attr.name().indexOf("注:") >= 0) |
||||
{ |
||||
HSSFFont font = workbook.createFont(); |
||||
font.setColor(HSSFFont.COLOR_RED); |
||||
cellStyle.setFont(font); |
||||
cellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index); |
||||
sheet.setColumnWidth(i, 6000); |
||||
} |
||||
else |
||||
{ |
||||
HSSFFont font = workbook.createFont(); |
||||
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 粗体显示
|
||||
cellStyle.setFont(font); // 选择需要用到的字体格式
|
||||
cellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index); |
||||
// 设置列宽
|
||||
sheet.setColumnWidth(i, 3766); |
||||
} |
||||
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); |
||||
cellStyle.setWrapText(true); |
||||
cell.setCellStyle(cellStyle); |
||||
|
||||
cell.setCellValue(attr.name());// 写入列名
|
||||
|
||||
// 如果设置了提示信息则鼠标放上去提示.
|
||||
if (!attr.prompt().trim().equals("")) |
||||
{ |
||||
setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, col, col); // 这里默认设了2-101列提示.
|
||||
} |
||||
// 如果设置了combo属性则本列只能选择不能输入
|
||||
if (attr.combo().length > 0) |
||||
{ |
||||
setHSSFValidation(sheet, attr.combo(), 1, 100, col, col); // 这里默认设了2-101列只能选择不能输入.
|
||||
} |
||||
} |
||||
|
||||
int startNo = index * sheetSize; |
||||
int endNo = Math.min(startNo + sheetSize, list.size()); |
||||
// 写入各条记录,每条记录对应excel表中的一行
|
||||
HSSFCellStyle cs = workbook.createCellStyle(); |
||||
cs.setAlignment(HSSFCellStyle.ALIGN_CENTER); |
||||
cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER); |
||||
for (int i = startNo; i < endNo; i++) |
||||
{ |
||||
row = sheet.createRow(i + 1 - startNo); |
||||
T vo = (T) list.get(i); // 得到导出对象.
|
||||
for (int j = 0; j < fields.size(); j++) |
||||
{ |
||||
Field field = fields.get(j); // 获得field.
|
||||
field.setAccessible(true); // 设置实体类私有属性可访问
|
||||
Excel attr = field.getAnnotation(Excel.class); |
||||
try |
||||
{ |
||||
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
||||
if (attr.isExport()) |
||||
{ |
||||
cell = row.createCell(getExcelCol(attr.column()));// 创建cell
|
||||
cell.setCellStyle(cs); |
||||
try |
||||
{ |
||||
if (String.valueOf(field.get(vo)).length() > 10) |
||||
throw new Exception("长度超过10位就不用转数字了"); |
||||
// 如果可以转成数字则导出为数字类型
|
||||
BigDecimal bc = new BigDecimal(String.valueOf(field.get(vo))); |
||||
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); |
||||
cell.setCellValue(bc.doubleValue()); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
cell.setCellType(HSSFCell.CELL_TYPE_STRING); |
||||
if (vo == null) |
||||
{ |
||||
cell.setCellValue(""); // 如果数据存在就填入,不存在填入空格.
|
||||
} |
||||
else |
||||
{ |
||||
cell.setCellValue(field.get(vo) == null ? "" : String.valueOf(field.get(vo)));// 如果数据存在就填入,不存在填入空格.
|
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.error("导出Excel失败{}", e); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
try |
||||
{ |
||||
String filename = encodingFilename(sheetName); |
||||
OutputStream out = new FileOutputStream(getfile() + filename); |
||||
workbook.write(out); |
||||
out.close(); |
||||
return AjaxResult.success(filename); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.error("关闭flush失败{}", e); |
||||
return AjaxResult.error("导出Excel失败,请联系网站管理员!"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 将EXCEL中A,B,C,D,E列映射成0,1,2,3 |
||||
* |
||||
* @param col |
||||
*/ |
||||
public static int getExcelCol(String col) |
||||
{ |
||||
col = col.toUpperCase(); |
||||
// 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。
|
||||
int count = -1; |
||||
char[] cs = col.toCharArray(); |
||||
for (int i = 0; i < cs.length; i++) |
||||
{ |
||||
count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i); |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
/** |
||||
* 设置单元格上提示 |
||||
* |
||||
* @param sheet 要设置的sheet. |
||||
* @param promptTitle 标题 |
||||
* @param promptContent 内容 |
||||
* @param firstRow 开始行 |
||||
* @param endRow 结束行 |
||||
* @param firstCol 开始列 |
||||
* @param endCol 结束列 |
||||
* @return 设置好的sheet. |
||||
*/ |
||||
public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle, String promptContent, int firstRow, |
||||
int endRow, int firstCol, int endCol) |
||||
{ |
||||
// 构造constraint对象
|
||||
DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1"); |
||||
// 四个参数分别是:起始行、终止行、起始列、终止列
|
||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); |
||||
// 数据有效性对象
|
||||
HSSFDataValidation data_validation_view = new HSSFDataValidation(regions, constraint); |
||||
data_validation_view.createPromptBox(promptTitle, promptContent); |
||||
sheet.addValidationData(data_validation_view); |
||||
return sheet; |
||||
} |
||||
|
||||
/** |
||||
* 设置某些列的值只能输入预制的数据,显示下拉框. |
||||
* |
||||
* @param sheet 要设置的sheet. |
||||
* @param textlist 下拉框显示的内容 |
||||
* @param firstRow 开始行 |
||||
* @param endRow 结束行 |
||||
* @param firstCol 开始列 |
||||
* @param endCol 结束列 |
||||
* @return 设置好的sheet. |
||||
*/ |
||||
public static HSSFSheet setHSSFValidation(HSSFSheet sheet, String[] textlist, int firstRow, int endRow, |
||||
int firstCol, int endCol) |
||||
{ |
||||
// 加载下拉列表内容
|
||||
DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist); |
||||
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
|
||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); |
||||
// 数据有效性对象
|
||||
HSSFDataValidation data_validation_list = new HSSFDataValidation(regions, constraint); |
||||
sheet.addValidationData(data_validation_list); |
||||
return sheet; |
||||
} |
||||
|
||||
/** |
||||
* 编码文件名 |
||||
*/ |
||||
public String encodingFilename(String filename) |
||||
{ |
||||
filename = UUID.randomUUID().toString() + "_" + filename + ".xls"; |
||||
return filename; |
||||
} |
||||
|
||||
public String getfile() throws FileNotFoundException |
||||
{ |
||||
return ResourceUtils.getURL("classpath:").getPath() + "static/file/"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,76 @@
|
||||
package com.ruoyi.common.utils.security; |
||||
|
||||
import org.apache.shiro.SecurityUtils; |
||||
import org.apache.shiro.mgt.RealmSecurityManager; |
||||
import org.apache.shiro.session.Session; |
||||
import org.apache.shiro.subject.PrincipalCollection; |
||||
import org.apache.shiro.subject.SimplePrincipalCollection; |
||||
import org.apache.shiro.subject.Subject; |
||||
import com.ruoyi.framework.shiro.realm.UserRealm; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* shiro 工具类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class ShiroUtils |
||||
{ |
||||
|
||||
public static Subject getSubjct() |
||||
{ |
||||
return SecurityUtils.getSubject(); |
||||
} |
||||
|
||||
public static Session getSession() |
||||
{ |
||||
return SecurityUtils.getSubject().getSession(); |
||||
} |
||||
|
||||
public static void logout() |
||||
{ |
||||
getSubjct().logout(); |
||||
} |
||||
|
||||
public static User getUser() |
||||
{ |
||||
return (User) getSubjct().getPrincipal(); |
||||
} |
||||
|
||||
public static void setUser(User user) |
||||
{ |
||||
Subject subject = getSubjct(); |
||||
PrincipalCollection principalCollection = subject.getPrincipals(); |
||||
String realmName = principalCollection.getRealmNames().iterator().next(); |
||||
PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName); |
||||
// 重新加载Principal
|
||||
subject.runAs(newPrincipalCollection); |
||||
} |
||||
|
||||
public static void clearCachedAuthorizationInfo() |
||||
{ |
||||
RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager(); |
||||
UserRealm realm = (UserRealm) rsm.getRealms().iterator().next(); |
||||
realm.clearCachedAuthorizationInfo(); |
||||
} |
||||
|
||||
public static Long getUserId() |
||||
{ |
||||
return getUser().getUserId().longValue(); |
||||
} |
||||
|
||||
public static String getLoginName() |
||||
{ |
||||
return getUser().getLoginName(); |
||||
} |
||||
|
||||
public static String getIp() |
||||
{ |
||||
return getSubjct().getSession().getHost(); |
||||
} |
||||
|
||||
public static String getSessionId() |
||||
{ |
||||
return String.valueOf(getSubjct().getSession().getId()); |
||||
} |
||||
} |
@ -0,0 +1,102 @@
|
||||
package com.ruoyi.common.utils.spring; |
||||
|
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* spring工具类 方便在非spring管理环境中获取bean |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public final class SpringUtils implements BeanFactoryPostProcessor |
||||
{ |
||||
/** Spring应用上下文环境 */ |
||||
private static ConfigurableListableBeanFactory beanFactory; |
||||
|
||||
@Override |
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException |
||||
{ |
||||
SpringUtils.beanFactory = beanFactory; |
||||
} |
||||
|
||||
/** |
||||
* 获取对象 |
||||
* |
||||
* @param name |
||||
* @return Object 一个以所给名字注册的bean的实例 |
||||
* @throws org.springframework.beans.BeansException |
||||
* |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public static <T> T getBean(String name) throws BeansException |
||||
{ |
||||
return (T) beanFactory.getBean(name); |
||||
} |
||||
|
||||
/** |
||||
* 获取类型为requiredType的对象 |
||||
* |
||||
* @param clz |
||||
* @return |
||||
* @throws org.springframework.beans.BeansException |
||||
* |
||||
*/ |
||||
public static <T> T getBean(Class<T> clz) throws BeansException |
||||
{ |
||||
T result = (T) beanFactory.getBean(clz); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true |
||||
* |
||||
* @param name |
||||
* @return boolean |
||||
*/ |
||||
public static boolean containsBean(String name) |
||||
{ |
||||
return beanFactory.containsBean(name); |
||||
} |
||||
|
||||
/** |
||||
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) |
||||
* |
||||
* @param name |
||||
* @return boolean |
||||
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException |
||||
* |
||||
*/ |
||||
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException |
||||
{ |
||||
return beanFactory.isSingleton(name); |
||||
} |
||||
|
||||
/** |
||||
* @param name |
||||
* @return Class 注册对象的类型 |
||||
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException |
||||
* |
||||
*/ |
||||
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException |
||||
{ |
||||
return beanFactory.getType(name); |
||||
} |
||||
|
||||
/** |
||||
* 如果给定的bean名字在bean定义中有别名,则返回这些别名 |
||||
* |
||||
* @param name |
||||
* @return |
||||
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException |
||||
* |
||||
*/ |
||||
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException |
||||
{ |
||||
return beanFactory.getAliases(name); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,86 @@
|
||||
package com.ruoyi.common.xss; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
import javax.servlet.Filter; |
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.FilterConfig; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.ServletRequest; |
||||
import javax.servlet.ServletResponse; |
||||
import javax.servlet.annotation.WebFilter; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
|
||||
/** |
||||
* 防止XSS攻击的过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@WebFilter(filterName = "xssFilter", urlPatterns = "/system/*") |
||||
public class XssFilter implements Filter |
||||
{ |
||||
|
||||
/** |
||||
* 排除链接 |
||||
*/ |
||||
public List<String> excludes = new ArrayList<>(); |
||||
|
||||
@Override |
||||
public void init(FilterConfig filterConfig) throws ServletException |
||||
{ |
||||
String temp = filterConfig.getInitParameter("excludes"); |
||||
if (temp != null) |
||||
{ |
||||
String[] url = temp.split(","); |
||||
for (int i = 0; url != null && i < url.length; i++) |
||||
{ |
||||
excludes.add(url[i]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
||||
throws IOException, ServletException |
||||
{ |
||||
HttpServletRequest req = (HttpServletRequest) request; |
||||
HttpServletResponse resp = (HttpServletResponse) response; |
||||
if (handleExcludeURL(req, resp)) |
||||
{ |
||||
chain.doFilter(request, response); |
||||
return; |
||||
} |
||||
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); |
||||
chain.doFilter(xssRequest, response); |
||||
} |
||||
|
||||
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) |
||||
{ |
||||
if (excludes == null || excludes.isEmpty()) |
||||
{ |
||||
return false; |
||||
} |
||||
String url = request.getServletPath(); |
||||
for (String pattern : excludes) |
||||
{ |
||||
Pattern p = Pattern.compile("^" + pattern); |
||||
Matcher m = p.matcher(url); |
||||
if (m.find()) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public void destroy() |
||||
{ |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.ruoyi.common.xss; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletRequestWrapper; |
||||
import org.jsoup.Jsoup; |
||||
import org.jsoup.safety.Whitelist; |
||||
|
||||
/** |
||||
* XSS过滤处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper |
||||
{ |
||||
|
||||
/** |
||||
* @param request |
||||
*/ |
||||
public XssHttpServletRequestWrapper(HttpServletRequest request) |
||||
{ |
||||
super(request); |
||||
} |
||||
|
||||
@Override |
||||
public String[] getParameterValues(String name) |
||||
{ |
||||
String[] values = super.getParameterValues(name); |
||||
if (values != null) |
||||
{ |
||||
int length = values.length; |
||||
String[] escapseValues = new String[length]; |
||||
for (int i = 0; i < length; i++) |
||||
{ |
||||
// 防xss攻击和过滤前后空格
|
||||
escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim(); |
||||
} |
||||
return escapseValues; |
||||
} |
||||
return super.getParameterValues(name); |
||||
} |
||||
} |
@ -0,0 +1,178 @@
|
||||
package com.ruoyi.framework.aspectj; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.Map; |
||||
import com.ruoyi.common.utils.AddressUtils; |
||||
import org.aspectj.lang.JoinPoint; |
||||
import org.aspectj.lang.Signature; |
||||
import org.aspectj.lang.annotation.AfterReturning; |
||||
import org.aspectj.lang.annotation.AfterThrowing; |
||||
import org.aspectj.lang.annotation.Aspect; |
||||
import org.aspectj.lang.annotation.Pointcut; |
||||
import org.aspectj.lang.reflect.MethodSignature; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.scheduling.annotation.Async; |
||||
import org.springframework.scheduling.annotation.EnableAsync; |
||||
import org.springframework.stereotype.Component; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.ruoyi.common.utils.ServletUtils; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.framework.aspectj.lang.annotation.Log; |
||||
import com.ruoyi.framework.aspectj.lang.constant.BusinessStatus; |
||||
import com.ruoyi.project.monitor.operlog.domain.OperLog; |
||||
import com.ruoyi.project.monitor.operlog.service.IOperLogService; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* 操作日志记录处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Aspect |
||||
@Component |
||||
@EnableAsync |
||||
public class LogAspect |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class); |
||||
|
||||
@Autowired |
||||
private IOperLogService operLogService; |
||||
|
||||
// 配置织入点
|
||||
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)") |
||||
public void logPointCut() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* 前置通知 用于拦截操作 |
||||
* |
||||
* @param joinPoint 切点 |
||||
*/ |
||||
@AfterReturning(pointcut = "logPointCut()") |
||||
public void doBefore(JoinPoint joinPoint) |
||||
{ |
||||
handleLog(joinPoint, null); |
||||
} |
||||
|
||||
/** |
||||
* 拦截异常操作 |
||||
* |
||||
* @param joinPoint |
||||
* @param e |
||||
*/ |
||||
@AfterThrowing(value = "logPointCut()", throwing = "e") |
||||
public void doAfter(JoinPoint joinPoint, Exception e) |
||||
{ |
||||
handleLog(joinPoint, e); |
||||
} |
||||
|
||||
@Async |
||||
protected void handleLog(final JoinPoint joinPoint, final Exception e) |
||||
{ |
||||
try |
||||
{ |
||||
// 获得注解
|
||||
Log controllerLog = getAnnotationLog(joinPoint); |
||||
if (controllerLog == null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
// 获取当前的用户
|
||||
User currentUser = ShiroUtils.getUser(); |
||||
|
||||
// *========数据库日志=========*//
|
||||
OperLog operLog = new OperLog(); |
||||
operLog.setStatus(BusinessStatus.SUCCESS); |
||||
// 请求的地址
|
||||
String ip = ShiroUtils.getIp(); |
||||
operLog.setOperIp(ip); |
||||
// 操作地点
|
||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(ip)); |
||||
|
||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); |
||||
if (currentUser != null) |
||||
{ |
||||
operLog.setOperName(currentUser.getLoginName()); |
||||
operLog.setDeptName(currentUser.getDept().getDeptName()); |
||||
} |
||||
|
||||
if (e != null) |
||||
{ |
||||
operLog.setStatus(BusinessStatus.FAIL); |
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); |
||||
} |
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName(); |
||||
String methodName = joinPoint.getSignature().getName(); |
||||
operLog.setMethod(className + "." + methodName + "()"); |
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(controllerLog, operLog); |
||||
// 保存数据库
|
||||
operLogService.insertOperlog(operLog); |
||||
} |
||||
catch (Exception exp) |
||||
{ |
||||
// 记录本地异常日志
|
||||
log.error("==前置通知异常=="); |
||||
log.error("异常信息:{}", exp.getMessage()); |
||||
exp.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取注解中对方法的描述信息 用于Controller层注解 |
||||
* |
||||
* @param joinPoint 切点 |
||||
* @return 方法描述 |
||||
* @throws Exception |
||||
*/ |
||||
public void getControllerMethodDescription(Log log, OperLog operLog) throws Exception |
||||
{ |
||||
// 设置action动作
|
||||
operLog.setAction(log.action()); |
||||
// 设置标题
|
||||
operLog.setTitle(log.title()); |
||||
// 设置channel
|
||||
operLog.setChannel(log.channel()); |
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData()) |
||||
{ |
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(operLog); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取请求的参数,放到log中 |
||||
* |
||||
* @param operLog |
||||
* @param request |
||||
*/ |
||||
private void setRequestValue(OperLog operLog) |
||||
{ |
||||
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap(); |
||||
String params = JSONObject.toJSONString(map); |
||||
operLog.setOperParam(StringUtils.substring(params, 0, 255)); |
||||
} |
||||
|
||||
/** |
||||
* 是否存在注解,如果存在就获取 |
||||
*/ |
||||
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception |
||||
{ |
||||
Signature signature = joinPoint.getSignature(); |
||||
MethodSignature methodSignature = (MethodSignature) signature; |
||||
Method method = methodSignature.getMethod(); |
||||
|
||||
if (method != null) |
||||
{ |
||||
return method.getAnnotation(Log.class); |
||||
} |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.ruoyi.framework.aspectj.lang.annotation; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* 自定义注解 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target(ElementType.FIELD) |
||||
public @interface Excel |
||||
{ |
||||
/** |
||||
* 导出到Excel中的名字. |
||||
*/ |
||||
public abstract String name(); |
||||
|
||||
/** |
||||
* 配置列的名称 |
||||
*/ |
||||
public abstract String column(); |
||||
|
||||
/** |
||||
* 提示信息 |
||||
*/ |
||||
public abstract String prompt() default ""; |
||||
|
||||
/** |
||||
* 设置只能选择不能输入的列内容. |
||||
*/ |
||||
public abstract String[] combo() default {}; |
||||
|
||||
/** |
||||
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. |
||||
*/ |
||||
public abstract boolean isExport() default true; |
||||
} |
@ -0,0 +1,33 @@
|
||||
package com.ruoyi.framework.aspectj.lang.annotation; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
import com.ruoyi.framework.aspectj.lang.constant.OperatorType; |
||||
|
||||
/** |
||||
* 自定义操作日志记录注解 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
@Target({ ElementType.PARAMETER, ElementType.METHOD }) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
public @interface Log |
||||
{ |
||||
/** 模块 */ |
||||
String title() default ""; |
||||
|
||||
/** 功能 */ |
||||
String action() default ""; |
||||
|
||||
/** 渠道 */ |
||||
String channel() default OperatorType.MANAGE; |
||||
|
||||
/** 是否保存请求的参数 */ |
||||
boolean isSaveRequestData() default true; |
||||
|
||||
} |
@ -0,0 +1,19 @@
|
||||
package com.ruoyi.framework.aspectj.lang.constant; |
||||
|
||||
/** |
||||
* 操作状态 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
public class BusinessStatus |
||||
{ |
||||
/** 其它 */ |
||||
public static final String OTHER = "-1"; |
||||
|
||||
/** 成功 */ |
||||
public static final String SUCCESS = "0"; |
||||
|
||||
/** 失败 */ |
||||
public static final String FAIL = "1"; |
||||
} |
@ -0,0 +1,33 @@
|
||||
package com.ruoyi.framework.aspectj.lang.constant; |
||||
|
||||
/** |
||||
* 业务操作类型 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
public class BusinessType |
||||
{ |
||||
/** 其它 */ |
||||
public static final String OTHER = "0"; |
||||
/** 新增 */ |
||||
public static final String INSERT = "1"; |
||||
/** 修改 */ |
||||
public static final String UPDATE = "2"; |
||||
/** 保存 */ |
||||
public static final String SAVE = "3"; |
||||
/** 删除 */ |
||||
public static final String DELETE = "4"; |
||||
/** 授权 */ |
||||
public static final String GRANT = "5"; |
||||
/** 导出 */ |
||||
public static final String EXPORT = "6"; |
||||
/** 导入 */ |
||||
public static final String IMPORT = "7"; |
||||
/** 强退 */ |
||||
public static final String FORCE = "8"; |
||||
/** 禁止访问 */ |
||||
public static final String FORBID = "9"; |
||||
/** 生成代码 */ |
||||
public static final String GENCODE = "10"; |
||||
} |
@ -0,0 +1,22 @@
|
||||
package com.ruoyi.framework.aspectj.lang.constant; |
||||
|
||||
/** |
||||
* 操作人类别 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
public class OperatorType |
||||
{ |
||||
/** 其它 */ |
||||
public static final String OTHER = "0"; |
||||
|
||||
/** 后台用户 */ |
||||
public static final String MANAGE = "1"; |
||||
|
||||
/** 渠道用户 */ |
||||
public static final String CHANNEL = "2"; |
||||
|
||||
/** 手机端用户 */ |
||||
public static final String MOBILE = "3"; |
||||
} |
@ -0,0 +1,61 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.util.Properties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import com.google.code.kaptcha.impl.DefaultKaptcha; |
||||
import com.google.code.kaptcha.util.Config; |
||||
|
||||
/** |
||||
* 验证码配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class CaptchaConfig |
||||
{ |
||||
@Bean(name = "captchaProducer") |
||||
public DefaultKaptcha getKaptchaBean() |
||||
{ |
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); |
||||
Properties properties = new Properties(); |
||||
properties.setProperty("kaptcha.border", "yes"); |
||||
properties.setProperty("kaptcha.border.color", "105,179,90"); |
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue"); |
||||
properties.setProperty("kaptcha.image.width", "160"); |
||||
properties.setProperty("kaptcha.image.height", "60"); |
||||
properties.setProperty("kaptcha.textproducer.font.size", "28"); |
||||
properties.setProperty("kaptcha.session.key", "kaptchaCode"); |
||||
properties.setProperty("kaptcha.textproducer.char.spac", "35"); |
||||
properties.setProperty("kaptcha.textproducer.char.length", "5"); |
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier"); |
||||
properties.setProperty("kaptcha.noise.color", "white"); |
||||
Config config = new Config(properties); |
||||
defaultKaptcha.setConfig(config); |
||||
return defaultKaptcha; |
||||
} |
||||
|
||||
@Bean(name = "captchaProducerMath") |
||||
public DefaultKaptcha getKaptchaBeanMath() |
||||
{ |
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); |
||||
Properties properties = new Properties(); |
||||
properties.setProperty("kaptcha.border", "yes"); |
||||
properties.setProperty("kaptcha.border.color", "105,179,90"); |
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue"); |
||||
properties.setProperty("kaptcha.image.width", "160"); |
||||
properties.setProperty("kaptcha.image.height", "60"); |
||||
properties.setProperty("kaptcha.textproducer.font.size", "38"); |
||||
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath"); |
||||
properties.setProperty("kaptcha.textproducer.impl", "com.ruoyi.framework.config.KaptchaTextCreator"); |
||||
properties.setProperty("kaptcha.textproducer.char.spac", "5"); |
||||
properties.setProperty("kaptcha.textproducer.char.length", "6"); |
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier"); |
||||
properties.setProperty("kaptcha.noise.color", "white"); |
||||
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); |
||||
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy"); |
||||
Config config = new Config(properties); |
||||
defaultKaptcha.setConfig(config); |
||||
return defaultKaptcha; |
||||
} |
||||
} |
@ -0,0 +1,161 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.sql.SQLException; |
||||
import javax.sql.DataSource; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean; |
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Primary; |
||||
import com.alibaba.druid.pool.DruidDataSource; |
||||
import com.alibaba.druid.support.http.StatViewServlet; |
||||
import com.alibaba.druid.support.http.WebStatFilter; |
||||
|
||||
/** |
||||
* Druid数据库信息配置加载 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class DruidConfig |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(DruidConfig.class); |
||||
|
||||
@Value("${spring.datasource.url}") |
||||
private String dbUrl; |
||||
|
||||
@Value("${spring.datasource.username}") |
||||
private String username; |
||||
|
||||
@Value("${spring.datasource.password}") |
||||
private String password; |
||||
|
||||
@Value("${spring.datasource.driverClassName}") |
||||
private String driverClassName; |
||||
|
||||
@Value("${spring.datasource.initialSize}") |
||||
private int initialSize; |
||||
|
||||
@Value("${spring.datasource.minIdle}") |
||||
private int minIdle; |
||||
|
||||
@Value("${spring.datasource.maxActive}") |
||||
private int maxActive; |
||||
|
||||
@Value("${spring.datasource.maxWait}") |
||||
private int maxWait; |
||||
|
||||
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}") |
||||
private int timeBetweenEvictionRunsMillis; |
||||
|
||||
@Value("${spring.datasource.minEvictableIdleTimeMillis}") |
||||
private int minEvictableIdleTimeMillis; |
||||
|
||||
@Value("${spring.datasource.validationQuery}") |
||||
private String validationQuery; |
||||
|
||||
@Value("${spring.datasource.testWhileIdle}") |
||||
private boolean testWhileIdle; |
||||
|
||||
@Value("${spring.datasource.testOnBorrow}") |
||||
private boolean testOnBorrow; |
||||
|
||||
@Value("${spring.datasource.testOnReturn}") |
||||
private boolean testOnReturn; |
||||
|
||||
@Value("${spring.datasource.poolPreparedStatements}") |
||||
private boolean poolPreparedStatements; |
||||
|
||||
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") |
||||
private int maxPoolPreparedStatementPerConnectionSize; |
||||
|
||||
@Value("${spring.datasource.filters}") |
||||
private String filters; |
||||
|
||||
@Value("{spring.datasource.connectionProperties}") |
||||
private String connectionProperties; |
||||
|
||||
@Bean(initMethod = "init", destroyMethod = "close") /** 声明其为Bean实例 */ |
||||
@Primary /** 在同样的DataSource中,首先使用被标注的DataSource */ |
||||
public DataSource dataSource() |
||||
{ |
||||
DruidDataSource datasource = new DruidDataSource(); |
||||
|
||||
datasource.setUrl(this.dbUrl); |
||||
datasource.setUsername(username); |
||||
datasource.setPassword(password); |
||||
datasource.setDriverClassName(driverClassName); |
||||
|
||||
/** configuration */ |
||||
datasource.setInitialSize(initialSize); |
||||
datasource.setMinIdle(minIdle); |
||||
datasource.setMaxActive(maxActive); |
||||
datasource.setMaxWait(maxWait); |
||||
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); |
||||
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); |
||||
datasource.setValidationQuery(validationQuery); |
||||
datasource.setTestWhileIdle(testWhileIdle); |
||||
datasource.setTestOnBorrow(testOnBorrow); |
||||
datasource.setTestOnReturn(testOnReturn); |
||||
datasource.setPoolPreparedStatements(poolPreparedStatements); |
||||
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); |
||||
try |
||||
{ |
||||
datasource.setFilters(filters); |
||||
} |
||||
catch (SQLException e) |
||||
{ |
||||
log.error("druid configuration initialization filter", e); |
||||
} |
||||
datasource.setConnectionProperties(connectionProperties); |
||||
|
||||
return datasource; |
||||
} |
||||
|
||||
/** |
||||
* 注册一个StatViewServlet 相当于在web.xml中声明了一个servlet |
||||
*/ |
||||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
||||
@Bean |
||||
public ServletRegistrationBean druidServlet() |
||||
{ |
||||
ServletRegistrationBean reg = new ServletRegistrationBean(); |
||||
reg.setServlet(new StatViewServlet()); |
||||
reg.addUrlMappings("/monitor/druid/*"); |
||||
/** 白名单 */ |
||||
// reg.addInitParameter("allow", "10.211.61.45,127.0.0.1,123.207.20.136");
|
||||
/** IP黑名单(共同存在时,deny优先于allow) */ |
||||
// reg.addInitParameter("deny", "10.211.61.4");
|
||||
/** 是否能够重置数据 禁用HTML页面上的“Reset All”功能 */ |
||||
reg.addInitParameter("resetEnable", "false"); |
||||
return reg; |
||||
} |
||||
|
||||
/** |
||||
* 注册一个:filterRegistrationBean 相当于在web.xml中声明了一个Filter |
||||
*/ |
||||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
||||
@Bean |
||||
public FilterRegistrationBean filterRegistrationBean() |
||||
{ |
||||
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); |
||||
filterRegistrationBean.setFilter(new WebStatFilter()); |
||||
/** 添加过滤规则. */ |
||||
filterRegistrationBean.addUrlPatterns("/*"); |
||||
/** 监控选项滤器 */ |
||||
filterRegistrationBean.addInitParameter("DruidWebStatFilter", "/*"); |
||||
/** 添加不需要忽略的格式信息. */ |
||||
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/monitor/druid/*"); |
||||
/** 配置profileEnable能够监控单个url调用的sql列表 */ |
||||
filterRegistrationBean.addInitParameter("profileEnable", "true"); |
||||
/** 当前的cookie的用户 */ |
||||
filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE"); |
||||
/** 当前的session的用户 */ |
||||
filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION"); |
||||
return filterRegistrationBean; |
||||
} |
||||
} |
@ -0,0 +1,34 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.util.Map; |
||||
import javax.servlet.DispatcherType; |
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import com.google.common.collect.Maps; |
||||
import com.ruoyi.common.xss.XssFilter; |
||||
|
||||
/** |
||||
* Filter配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class FilterConfig |
||||
{ |
||||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
||||
@Bean |
||||
public FilterRegistrationBean xssFilterRegistration() |
||||
{ |
||||
FilterRegistrationBean registration = new FilterRegistrationBean(); |
||||
registration.setDispatcherTypes(DispatcherType.REQUEST); |
||||
registration.setFilter(new XssFilter()); |
||||
registration.addUrlPatterns("/*"); |
||||
registration.setName("xssFilter"); |
||||
registration.setOrder(Integer.MAX_VALUE); |
||||
Map<String, String> initParameters = Maps.newHashMap(); |
||||
initParameters.put("excludes", "/system/notice/*"); |
||||
registration.setInitParameters(initParameters); |
||||
return registration; |
||||
} |
||||
} |
@ -0,0 +1,71 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* 读取代码生成相关配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
@ConfigurationProperties(prefix = "gen") |
||||
public class GenConfig |
||||
{ |
||||
/** 作者 */ |
||||
public static String author; |
||||
/** 生成包路径 */ |
||||
public static String packageName; |
||||
/** 自动去除表前缀,默认是true */ |
||||
public static String autoRemovePre; |
||||
/** 表前缀(类名不会包含表前缀) */ |
||||
public static String tablePrefix; |
||||
|
||||
public static String getAuthor() |
||||
{ |
||||
return author; |
||||
} |
||||
|
||||
public void setAuthor(String author) |
||||
{ |
||||
GenConfig.author = author; |
||||
} |
||||
|
||||
public static String getPackageName() |
||||
{ |
||||
return packageName; |
||||
} |
||||
|
||||
public void setPackageName(String packageName) |
||||
{ |
||||
GenConfig.packageName = packageName; |
||||
} |
||||
|
||||
public static String getAutoRemovePre() |
||||
{ |
||||
return autoRemovePre; |
||||
} |
||||
|
||||
public void setAutoRemovePre(String autoRemovePre) |
||||
{ |
||||
GenConfig.autoRemovePre = autoRemovePre; |
||||
} |
||||
|
||||
public static String getTablePrefix() |
||||
{ |
||||
return tablePrefix; |
||||
} |
||||
|
||||
public void setTablePrefix(String tablePrefix) |
||||
{ |
||||
GenConfig.tablePrefix = tablePrefix; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() |
||||
{ |
||||
return "GenConfig [getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() |
||||
+ "]"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,44 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.util.Locale; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.web.servlet.LocaleResolver; |
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; |
||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver; |
||||
|
||||
/** |
||||
* 资源文件配置加载 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class I18nConfig implements WebMvcConfigurer |
||||
{ |
||||
|
||||
@Bean |
||||
public LocaleResolver localeResolver() |
||||
{ |
||||
SessionLocaleResolver slr = new SessionLocaleResolver(); |
||||
// 默认语言
|
||||
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); |
||||
return slr; |
||||
} |
||||
|
||||
@Bean |
||||
public LocaleChangeInterceptor localeChangeInterceptor() |
||||
{ |
||||
LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); |
||||
// 参数名
|
||||
lci.setParamName("lang"); |
||||
return lci; |
||||
} |
||||
|
||||
@Override |
||||
public void addInterceptors(InterceptorRegistry registry) |
||||
{ |
||||
registry.addInterceptor(localeChangeInterceptor()); |
||||
} |
||||
} |
@ -0,0 +1,77 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.util.Random; |
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator; |
||||
|
||||
/** |
||||
* 验证码文本生成器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class KaptchaTextCreator extends DefaultTextCreator |
||||
{ |
||||
|
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); |
||||
|
||||
@Override |
||||
public String getText() |
||||
{ |
||||
Integer result = 0; |
||||
Random random = new Random(); |
||||
int x = random.nextInt(10); |
||||
int y = random.nextInt(10); |
||||
StringBuilder suChinese = new StringBuilder(); |
||||
int randomoperands = (int) Math.round(Math.random() * 2); |
||||
if (randomoperands == 0) |
||||
{ |
||||
result = x * y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("*"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
else if (randomoperands == 1) |
||||
{ |
||||
if (!(x == 0) && y % x == 0) |
||||
{ |
||||
result = y / x; |
||||
suChinese.append(CNUMBERS[y]); |
||||
suChinese.append("/"); |
||||
suChinese.append(CNUMBERS[x]); |
||||
} |
||||
else |
||||
{ |
||||
result = x + y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("+"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
} |
||||
else if (randomoperands == 2) |
||||
{ |
||||
if (x >= y) |
||||
{ |
||||
result = x - y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("-"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
else |
||||
{ |
||||
result = y - x; |
||||
suChinese.append(CNUMBERS[y]); |
||||
suChinese.append("-"); |
||||
suChinese.append(CNUMBERS[x]); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
result = x + y; |
||||
suChinese.append(CNUMBERS[x]); |
||||
suChinese.append("+"); |
||||
suChinese.append(CNUMBERS[y]); |
||||
} |
||||
suChinese.append("=?@" + result); |
||||
return suChinese.toString(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,42 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; |
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; |
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||
|
||||
/** |
||||
* 通用配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class ResourcesConfig implements WebMvcConfigurer |
||||
{ |
||||
/** |
||||
* 首页地址 |
||||
*/ |
||||
@Value("${shiro.user.indexUrl}") |
||||
private String indexUrl; |
||||
|
||||
/** |
||||
* 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页 |
||||
*/ |
||||
@Override |
||||
public void addViewControllers(ViewControllerRegistry registry) |
||||
{ |
||||
registry.addViewController("/").setViewName("forward:" + indexUrl); |
||||
} |
||||
|
||||
@Override |
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) |
||||
{ |
||||
/** 头像上传路径 */ |
||||
registry.addResourceHandler("/profile/**").addResourceLocations("file:" + RuoYiConfig.getProfile()); |
||||
|
||||
/** swagger配置 */ |
||||
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); |
||||
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); |
||||
} |
||||
} |
@ -0,0 +1,64 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* 读取项目相关配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
@ConfigurationProperties(prefix = "ruoyi") |
||||
public class RuoYiConfig |
||||
{ |
||||
/** 项目名称 */ |
||||
private String name; |
||||
/** 版本 */ |
||||
private String version; |
||||
/** 版权年份 */ |
||||
private String copyrightYear; |
||||
/** 上传路径 */ |
||||
private static String profile; |
||||
|
||||
public String getName() |
||||
{ |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) |
||||
{ |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getVersion() |
||||
{ |
||||
return version; |
||||
} |
||||
|
||||
public void setVersion(String version) |
||||
{ |
||||
this.version = version; |
||||
} |
||||
|
||||
public String getCopyrightYear() |
||||
{ |
||||
return copyrightYear; |
||||
} |
||||
|
||||
public void setCopyrightYear(String copyrightYear) |
||||
{ |
||||
this.copyrightYear = copyrightYear; |
||||
} |
||||
|
||||
public static String getProfile() |
||||
{ |
||||
return profile; |
||||
} |
||||
|
||||
public void setProfile(String profile) |
||||
{ |
||||
RuoYiConfig.profile = profile; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,56 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean; |
||||
import javax.sql.DataSource; |
||||
import java.util.Properties; |
||||
|
||||
/** |
||||
* 定时任务配置 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
@Configuration |
||||
public class ScheduleConfig |
||||
{ |
||||
|
||||
@Bean |
||||
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) |
||||
{ |
||||
SchedulerFactoryBean factory = new SchedulerFactoryBean(); |
||||
factory.setDataSource(dataSource); |
||||
|
||||
// quartz参数
|
||||
Properties prop = new Properties(); |
||||
prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); |
||||
prop.put("org.quartz.scheduler.instanceId", "AUTO"); |
||||
// 线程池配置
|
||||
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); |
||||
prop.put("org.quartz.threadPool.threadCount", "20"); |
||||
prop.put("org.quartz.threadPool.threadPriority", "5"); |
||||
// JobStore配置
|
||||
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); |
||||
// 集群配置
|
||||
prop.put("org.quartz.jobStore.isClustered", "true"); |
||||
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); |
||||
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); |
||||
|
||||
prop.put("org.quartz.jobStore.misfireThreshold", "12000"); |
||||
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); |
||||
factory.setQuartzProperties(prop); |
||||
|
||||
factory.setSchedulerName("RuoyiScheduler"); |
||||
// 延时启动
|
||||
factory.setStartupDelay(1); |
||||
factory.setApplicationContextSchedulerContextKey("applicationContextKey"); |
||||
// 可选,QuartzScheduler
|
||||
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
|
||||
factory.setOverwriteExistingJobs(true); |
||||
// 设置自动启动,默认为true
|
||||
factory.setAutoStartup(true); |
||||
|
||||
return factory; |
||||
} |
||||
} |
@ -0,0 +1,360 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
|
||||
import javax.servlet.Filter; |
||||
|
||||
import org.apache.shiro.cache.ehcache.EhCacheManager; |
||||
import org.apache.shiro.codec.Base64; |
||||
import org.apache.shiro.mgt.SecurityManager; |
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; |
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean; |
||||
import org.apache.shiro.web.mgt.CookieRememberMeManager; |
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager; |
||||
import org.apache.shiro.web.servlet.SimpleCookie; |
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; |
||||
import org.springframework.beans.factory.annotation.Qualifier; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import com.ruoyi.framework.shiro.realm.UserRealm; |
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO; |
||||
import com.ruoyi.framework.shiro.session.OnlineSessionFactory; |
||||
import com.ruoyi.framework.shiro.web.filter.LogoutFilter; |
||||
import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter; |
||||
import com.ruoyi.framework.shiro.web.filter.online.OnlineSessionFilter; |
||||
import com.ruoyi.framework.shiro.web.filter.sync.SyncOnlineSessionFilter; |
||||
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager; |
||||
import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler; |
||||
|
||||
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; |
||||
|
||||
/** |
||||
* 权限配置加载 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
public class ShiroConfig |
||||
{ |
||||
public static final String PREMISSION_STRING = "perms[\"{0}\"]"; |
||||
|
||||
// Session超时时间,单位为毫秒(默认30分钟)
|
||||
@Value("${shiro.session.expireTime}") |
||||
private int expireTime; |
||||
|
||||
// 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||
@Value("${shiro.session.validationInterval}") |
||||
private int validationInterval; |
||||
|
||||
// 验证码开关
|
||||
@Value("${shiro.user.captchaEbabled}") |
||||
private boolean captchaEbabled; |
||||
|
||||
// 验证码类型
|
||||
@Value("${shiro.user.captchaType}") |
||||
private String captchaType; |
||||
|
||||
// 设置Cookie的域名
|
||||
@Value("${shiro.cookie.domain}") |
||||
private String domain; |
||||
|
||||
// 设置cookie的有效访问路径
|
||||
@Value("${shiro.cookie.path}") |
||||
private String path; |
||||
|
||||
// 设置HttpOnly属性
|
||||
@Value("${shiro.cookie.httpOnly}") |
||||
private boolean httpOnly; |
||||
|
||||
// 设置Cookie的过期时间,秒为单位
|
||||
@Value("${shiro.cookie.maxAge}") |
||||
private int maxAge; |
||||
|
||||
// 登录地址
|
||||
@Value("${shiro.user.loginUrl}") |
||||
private String loginUrl; |
||||
|
||||
// 权限认证失败地址
|
||||
@Value("${shiro.user.unauthorizedUrl}") |
||||
private String unauthorizedUrl; |
||||
|
||||
/** |
||||
* 缓存管理器 使用Ehcache实现 |
||||
*/ |
||||
@Bean |
||||
public EhCacheManager getEhCacheManager() |
||||
{ |
||||
EhCacheManager em = new EhCacheManager(); |
||||
em.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml"); |
||||
return em; |
||||
} |
||||
|
||||
/** |
||||
* 自定义Realm |
||||
*/ |
||||
@Bean |
||||
public UserRealm userRealm(EhCacheManager cacheManager) |
||||
{ |
||||
UserRealm userRealm = new UserRealm(); |
||||
userRealm.setCacheManager(cacheManager); |
||||
return userRealm; |
||||
} |
||||
|
||||
/** |
||||
* 自定义sessionDAO会话 |
||||
*/ |
||||
@Bean |
||||
public OnlineSessionDAO sessionDAO() |
||||
{ |
||||
OnlineSessionDAO sessionDAO = new OnlineSessionDAO(); |
||||
return sessionDAO; |
||||
} |
||||
|
||||
/** |
||||
* 自定义sessionFactory会话 |
||||
*/ |
||||
@Bean |
||||
public OnlineSessionFactory sessionFactory() |
||||
{ |
||||
OnlineSessionFactory sessionFactory = new OnlineSessionFactory(); |
||||
return sessionFactory; |
||||
} |
||||
|
||||
/** |
||||
* 自定义sessionFactory调度器 |
||||
*/ |
||||
@Bean |
||||
public SpringSessionValidationScheduler sessionValidationScheduler() |
||||
{ |
||||
SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler(); |
||||
// 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||
sessionValidationScheduler.setSessionValidationInterval(validationInterval * 60 * 1000); |
||||
// 设置会话验证调度器进行会话验证时的会话管理器
|
||||
sessionValidationScheduler.setSessionManager(sessionValidationManager()); |
||||
return sessionValidationScheduler; |
||||
} |
||||
|
||||
/** |
||||
* 会话管理器 |
||||
*/ |
||||
@Bean |
||||
public OnlineWebSessionManager sessionValidationManager() |
||||
{ |
||||
OnlineWebSessionManager manager = new OnlineWebSessionManager(); |
||||
// 加入缓存管理器
|
||||
manager.setCacheManager(getEhCacheManager()); |
||||
// 删除过期的session
|
||||
manager.setDeleteInvalidSessions(true); |
||||
// 设置全局session超时时间
|
||||
manager.setGlobalSessionTimeout(expireTime * 60 * 1000); |
||||
// 去掉 JSESSIONID
|
||||
manager.setSessionIdUrlRewritingEnabled(false); |
||||
// 是否定时检查session
|
||||
manager.setSessionValidationSchedulerEnabled(true); |
||||
// 自定义SessionDao
|
||||
manager.setSessionDAO(sessionDAO()); |
||||
// 自定义sessionFactory
|
||||
manager.setSessionFactory(sessionFactory()); |
||||
return manager; |
||||
} |
||||
|
||||
/** |
||||
* 会话管理器 |
||||
*/ |
||||
@Bean |
||||
public OnlineWebSessionManager sessionManager() |
||||
{ |
||||
OnlineWebSessionManager manager = new OnlineWebSessionManager(); |
||||
// 加入缓存管理器
|
||||
manager.setCacheManager(getEhCacheManager()); |
||||
// 删除过期的session
|
||||
manager.setDeleteInvalidSessions(true); |
||||
// 设置全局session超时时间
|
||||
manager.setGlobalSessionTimeout(expireTime * 60 * 1000); |
||||
// 去掉 JSESSIONID
|
||||
manager.setSessionIdUrlRewritingEnabled(false); |
||||
// 定义要使用的无效的Session定时调度器
|
||||
manager.setSessionValidationScheduler(sessionValidationScheduler()); |
||||
// 是否定时检查session
|
||||
manager.setSessionValidationSchedulerEnabled(true); |
||||
// 自定义SessionDao
|
||||
manager.setSessionDAO(sessionDAO()); |
||||
// 自定义sessionFactory
|
||||
manager.setSessionFactory(sessionFactory()); |
||||
return manager; |
||||
} |
||||
|
||||
/** |
||||
* 安全管理器 |
||||
*/ |
||||
@Bean |
||||
public SecurityManager securityManager(UserRealm userRealm) |
||||
{ |
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); |
||||
// 设置realm.
|
||||
securityManager.setRealm(userRealm); |
||||
// 记住我
|
||||
securityManager.setRememberMeManager(rememberMeManager()); |
||||
// 注入缓存管理器;
|
||||
securityManager.setCacheManager(getEhCacheManager()); |
||||
// session管理器
|
||||
securityManager.setSessionManager(sessionManager()); |
||||
return securityManager; |
||||
} |
||||
|
||||
/** |
||||
* 退出过滤器 |
||||
*/ |
||||
public LogoutFilter logoutFilter() |
||||
{ |
||||
LogoutFilter logoutFilter = new LogoutFilter(); |
||||
logoutFilter.setLoginUrl(loginUrl); |
||||
return logoutFilter; |
||||
} |
||||
|
||||
/** |
||||
* Shiro过滤器配置 |
||||
*/ |
||||
@Bean |
||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) |
||||
{ |
||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); |
||||
// Shiro的核心安全接口,这个属性是必须的
|
||||
shiroFilterFactoryBean.setSecurityManager(securityManager); |
||||
// 身份认证失败,则跳转到登录页面的配置
|
||||
shiroFilterFactoryBean.setLoginUrl(loginUrl); |
||||
// 权限认证失败,则跳转到指定页面
|
||||
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl); |
||||
// Shiro连接约束配置,即过滤链的定义
|
||||
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); |
||||
// 对静态资源设置匿名访问
|
||||
filterChainDefinitionMap.put("/favicon.ico**", "anon"); |
||||
filterChainDefinitionMap.put("/ruoyi.png**", "anon"); |
||||
filterChainDefinitionMap.put("/css/**", "anon"); |
||||
filterChainDefinitionMap.put("/docs/**", "anon"); |
||||
filterChainDefinitionMap.put("/fonts/**", "anon"); |
||||
filterChainDefinitionMap.put("/img/**", "anon"); |
||||
filterChainDefinitionMap.put("/ajax/**", "anon"); |
||||
filterChainDefinitionMap.put("/js/**", "anon"); |
||||
filterChainDefinitionMap.put("/ruoyi/**", "anon"); |
||||
filterChainDefinitionMap.put("/druid/**", "anon"); |
||||
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon"); |
||||
// 退出 logout地址,shiro去清除session
|
||||
filterChainDefinitionMap.put("/logout", "logout"); |
||||
// 不需要拦截的访问
|
||||
filterChainDefinitionMap.put("/login", "anon,captchaValidate"); |
||||
// 系统权限列表
|
||||
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
||||
|
||||
Map<String, Filter> filters = new LinkedHashMap<>(); |
||||
filters.put("onlineSession", onlineSessionFilter()); |
||||
filters.put("syncOnlineSession", syncOnlineSessionFilter()); |
||||
filters.put("captchaValidate", captchaValidateFilter()); |
||||
// 注销成功,则跳转到指定页面
|
||||
filters.put("logout", logoutFilter()); |
||||
shiroFilterFactoryBean.setFilters(filters); |
||||
|
||||
// 所有请求需要认证
|
||||
filterChainDefinitionMap.put("/**", "user"); |
||||
// 系统请求记录当前会话
|
||||
filterChainDefinitionMap.put("/main", "onlineSession,syncOnlineSession"); |
||||
filterChainDefinitionMap.put("/system/**", "onlineSession,syncOnlineSession"); |
||||
filterChainDefinitionMap.put("/monitor/**", "onlineSession,syncOnlineSession"); |
||||
filterChainDefinitionMap.put("/tool/**", "onlineSession,syncOnlineSession"); |
||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); |
||||
|
||||
return shiroFilterFactoryBean; |
||||
} |
||||
|
||||
/** |
||||
* 自定义在线用户处理过滤器 |
||||
*/ |
||||
@Bean |
||||
public OnlineSessionFilter onlineSessionFilter() |
||||
{ |
||||
OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter(); |
||||
onlineSessionFilter.setLoginUrl(loginUrl); |
||||
return onlineSessionFilter; |
||||
} |
||||
|
||||
/** |
||||
* 自定义在线用户同步过滤器 |
||||
*/ |
||||
@Bean |
||||
public SyncOnlineSessionFilter syncOnlineSessionFilter() |
||||
{ |
||||
SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter(); |
||||
return syncOnlineSessionFilter; |
||||
} |
||||
|
||||
/** |
||||
* 自定义验证码过滤器 |
||||
*/ |
||||
@Bean |
||||
public CaptchaValidateFilter captchaValidateFilter() |
||||
{ |
||||
CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter(); |
||||
captchaValidateFilter.setCaptchaEbabled(captchaEbabled); |
||||
captchaValidateFilter.setCaptchaType(captchaType); |
||||
return captchaValidateFilter; |
||||
} |
||||
|
||||
/** |
||||
* cookie 属性设置 |
||||
*/ |
||||
public SimpleCookie rememberMeCookie() |
||||
{ |
||||
SimpleCookie cookie = new SimpleCookie("rememberMe"); |
||||
cookie.setDomain(domain); |
||||
cookie.setPath(path); |
||||
cookie.setHttpOnly(httpOnly); |
||||
cookie.setMaxAge(maxAge * 24 * 60 * 60); |
||||
return cookie; |
||||
} |
||||
|
||||
/** |
||||
* 记住我 |
||||
*/ |
||||
public CookieRememberMeManager rememberMeManager() |
||||
{ |
||||
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); |
||||
cookieRememberMeManager.setCookie(rememberMeCookie()); |
||||
cookieRememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ==")); |
||||
return cookieRememberMeManager; |
||||
} |
||||
|
||||
/** |
||||
* 开启Shiro代理 |
||||
*/ |
||||
@Bean |
||||
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() |
||||
{ |
||||
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator(); |
||||
proxyCreator.setProxyTargetClass(true); |
||||
return proxyCreator; |
||||
} |
||||
|
||||
/** |
||||
* thymeleaf模板引擎和shiro框架的整合 |
||||
*/ |
||||
@Bean |
||||
public ShiroDialect shiroDialect() |
||||
{ |
||||
return new ShiroDialect(); |
||||
} |
||||
|
||||
/** |
||||
* 开启Shiro注解通知器 |
||||
*/ |
||||
@Bean |
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor( |
||||
@Qualifier("securityManager") SecurityManager securityManager) |
||||
{ |
||||
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); |
||||
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); |
||||
return authorizationAttributeSourceAdvisor; |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
package com.ruoyi.framework.config; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import springfox.documentation.builders.ApiInfoBuilder; |
||||
import springfox.documentation.builders.PathSelectors; |
||||
import springfox.documentation.builders.RequestHandlerSelectors; |
||||
import springfox.documentation.service.ApiInfo; |
||||
import springfox.documentation.service.Contact; |
||||
import springfox.documentation.spi.DocumentationType; |
||||
import springfox.documentation.spring.web.plugins.Docket; |
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2; |
||||
|
||||
/** |
||||
* Swagger2的接口配置 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Configuration |
||||
@EnableSwagger2 |
||||
public class SwaggerConfig |
||||
{ |
||||
/** 系统基础配置 */ |
||||
@Autowired |
||||
private RuoYiConfig ruoYiConfig; |
||||
|
||||
/** |
||||
* 创建API |
||||
*/ |
||||
@Bean |
||||
public Docket createRestApi() |
||||
{ |
||||
return new Docket(DocumentationType.SWAGGER_2) |
||||
// 详细定制
|
||||
.apiInfo(apiInfo()) |
||||
.select() |
||||
// 指定当前包路径
|
||||
.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) |
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any()) |
||||
.build(); |
||||
} |
||||
|
||||
/** |
||||
* 添加摘要信息 |
||||
*/ |
||||
private ApiInfo apiInfo() |
||||
{ |
||||
// 用ApiInfoBuilder进行定制
|
||||
return new ApiInfoBuilder() |
||||
.title("标题:若依管理系统_接口文档") |
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") |
||||
.contact(new Contact(ruoYiConfig.getName(), null, null)) |
||||
.version("版本号:" + ruoYiConfig.getVersion()) |
||||
.build(); |
||||
} |
||||
} |
@ -0,0 +1,126 @@
|
||||
package com.ruoyi.framework.shiro.realm; |
||||
|
||||
import org.apache.shiro.SecurityUtils; |
||||
import org.apache.shiro.authc.AuthenticationException; |
||||
import org.apache.shiro.authc.AuthenticationInfo; |
||||
import org.apache.shiro.authc.AuthenticationToken; |
||||
import org.apache.shiro.authc.ExcessiveAttemptsException; |
||||
import org.apache.shiro.authc.IncorrectCredentialsException; |
||||
import org.apache.shiro.authc.LockedAccountException; |
||||
import org.apache.shiro.authc.SimpleAuthenticationInfo; |
||||
import org.apache.shiro.authc.UnknownAccountException; |
||||
import org.apache.shiro.authc.UsernamePasswordToken; |
||||
import org.apache.shiro.authz.AuthorizationInfo; |
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo; |
||||
import org.apache.shiro.realm.AuthorizingRealm; |
||||
import org.apache.shiro.subject.PrincipalCollection; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
||||
import com.ruoyi.common.exception.user.CaptchaException; |
||||
import com.ruoyi.common.exception.user.RoleBlockedException; |
||||
import com.ruoyi.common.exception.user.UserBlockedException; |
||||
import com.ruoyi.common.exception.user.UserNotExistsException; |
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException; |
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.framework.shiro.service.LoginService; |
||||
import com.ruoyi.project.system.menu.service.IMenuService; |
||||
import com.ruoyi.project.system.role.service.IRoleService; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* 自定义Realm 处理登录 权限 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class UserRealm extends AuthorizingRealm |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(UserRealm.class); |
||||
|
||||
@Autowired |
||||
private IMenuService menuService; |
||||
|
||||
@Autowired |
||||
private IRoleService roleService; |
||||
|
||||
@Autowired |
||||
private LoginService loginService; |
||||
|
||||
/** |
||||
* 授权 |
||||
*/ |
||||
@Override |
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) |
||||
{ |
||||
Long userId = ShiroUtils.getUserId(); |
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); |
||||
// 角色加入AuthorizationInfo认证对象
|
||||
info.setRoles(roleService.selectRoleKeys(userId)); |
||||
// 权限加入AuthorizationInfo认证对象
|
||||
info.setStringPermissions(menuService.selectPermsByUserId(userId)); |
||||
return info; |
||||
} |
||||
|
||||
/** |
||||
* 登录认证 |
||||
*/ |
||||
@Override |
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException |
||||
{ |
||||
UsernamePasswordToken upToken = (UsernamePasswordToken) token; |
||||
String username = upToken.getUsername(); |
||||
String password = ""; |
||||
if (upToken.getPassword() != null) |
||||
{ |
||||
password = new String(upToken.getPassword()); |
||||
} |
||||
|
||||
User user = null; |
||||
try |
||||
{ |
||||
user = loginService.login(username, password); |
||||
} |
||||
catch (CaptchaException e) |
||||
{ |
||||
throw new AuthenticationException(e.getMessage(), e); |
||||
} |
||||
catch (UserNotExistsException e) |
||||
{ |
||||
throw new UnknownAccountException(e.getMessage(), e); |
||||
} |
||||
catch (UserPasswordNotMatchException e) |
||||
{ |
||||
throw new IncorrectCredentialsException(e.getMessage(), e); |
||||
} |
||||
catch (UserPasswordRetryLimitExceedException e) |
||||
{ |
||||
throw new ExcessiveAttemptsException(e.getMessage(), e); |
||||
} |
||||
catch (UserBlockedException e) |
||||
{ |
||||
throw new LockedAccountException(e.getMessage(), e); |
||||
} |
||||
catch (RoleBlockedException e) |
||||
{ |
||||
throw new LockedAccountException(e.getMessage(), e); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage()); |
||||
throw new AuthenticationException(e.getMessage(), e); |
||||
} |
||||
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName()); |
||||
return info; |
||||
} |
||||
|
||||
/** |
||||
* 清理缓存权限 |
||||
*/ |
||||
public void clearCachedAuthorizationInfo() |
||||
{ |
||||
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,128 @@
|
||||
package com.ruoyi.framework.shiro.service; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
import org.springframework.util.StringUtils; |
||||
import com.ruoyi.common.constant.Constants; |
||||
import com.ruoyi.common.constant.ShiroConstants; |
||||
import com.ruoyi.common.constant.UserConstants; |
||||
import com.ruoyi.common.exception.user.CaptchaException; |
||||
import com.ruoyi.common.exception.user.UserBlockedException; |
||||
import com.ruoyi.common.exception.user.UserNotExistsException; |
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException; |
||||
import com.ruoyi.common.utils.DateUtils; |
||||
import com.ruoyi.common.utils.MessageUtils; |
||||
import com.ruoyi.common.utils.ServletUtils; |
||||
import com.ruoyi.common.utils.SystemLogUtils; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
import com.ruoyi.project.system.user.domain.UserStatus; |
||||
import com.ruoyi.project.system.user.service.IUserService; |
||||
|
||||
/** |
||||
* 登录校验方法 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class LoginService |
||||
{ |
||||
@Autowired |
||||
private PasswordService passwordService; |
||||
|
||||
@Autowired |
||||
private IUserService userService; |
||||
|
||||
/** |
||||
* 登录 |
||||
*/ |
||||
public User login(String username, String password) |
||||
{ |
||||
// 验证码校验
|
||||
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA))) |
||||
{ |
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); |
||||
throw new CaptchaException(); |
||||
} |
||||
// 用户名或密码为空 错误
|
||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) |
||||
{ |
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")); |
||||
throw new UserNotExistsException(); |
||||
} |
||||
// 密码如果不在指定范围内 错误
|
||||
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH |
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) |
||||
{ |
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")); |
||||
throw new UserPasswordNotMatchException(); |
||||
} |
||||
|
||||
// 用户名不在指定范围内 错误
|
||||
if (username.length() < UserConstants.USERNAME_MIN_LENGTH |
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) |
||||
{ |
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")); |
||||
throw new UserPasswordNotMatchException(); |
||||
} |
||||
|
||||
// 查询用户信息
|
||||
User user = userService.selectUserByLoginName(username); |
||||
|
||||
if (user == null && maybeMobilePhoneNumber(username)) |
||||
{ |
||||
user = userService.selectUserByPhoneNumber(username); |
||||
} |
||||
|
||||
if (user == null && maybeEmail(username)) |
||||
{ |
||||
user = userService.selectUserByEmail(username); |
||||
} |
||||
|
||||
if (user == null || UserStatus.DELETED.getCode().equals(user.getDelFlag())) |
||||
{ |
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")); |
||||
throw new UserNotExistsException(); |
||||
} |
||||
|
||||
passwordService.validate(user, password); |
||||
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) |
||||
{ |
||||
SystemLogUtils.log(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())); |
||||
throw new UserBlockedException(user.getRemark()); |
||||
} |
||||
SystemLogUtils.log(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); |
||||
recordLoginInfo(user); |
||||
return user; |
||||
} |
||||
|
||||
private boolean maybeEmail(String username) |
||||
{ |
||||
if (!username.matches(UserConstants.EMAIL_PATTERN)) |
||||
{ |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private boolean maybeMobilePhoneNumber(String username) |
||||
{ |
||||
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN)) |
||||
{ |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 记录登录信息 |
||||
*/ |
||||
public void recordLoginInfo(User user) |
||||
{ |
||||
user.setLoginIp(ShiroUtils.getIp()); |
||||
user.setLoginDate(DateUtils.getNowDate()); |
||||
userService.updateUser(user); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,101 @@
|
||||
package com.ruoyi.framework.shiro.service; |
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger; |
||||
import javax.annotation.PostConstruct; |
||||
import org.apache.shiro.cache.Cache; |
||||
import org.apache.shiro.cache.CacheManager; |
||||
import org.apache.shiro.crypto.hash.Md5Hash; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import com.ruoyi.common.constant.Constants; |
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException; |
||||
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; |
||||
import com.ruoyi.common.utils.MessageUtils; |
||||
import com.ruoyi.common.utils.SystemLogUtils; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* 登录密码方法 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class PasswordService |
||||
{ |
||||
|
||||
@Autowired |
||||
private CacheManager cacheManager; |
||||
|
||||
private Cache<String, AtomicInteger> loginRecordCache; |
||||
|
||||
@Value(value = "${user.password.maxRetryCount}") |
||||
private String maxRetryCount; |
||||
|
||||
@PostConstruct |
||||
public void init() |
||||
{ |
||||
loginRecordCache = cacheManager.getCache("loginRecordCache"); |
||||
} |
||||
|
||||
public void validate(User user, String password) |
||||
{ |
||||
String loginName = user.getLoginName(); |
||||
|
||||
AtomicInteger retryCount = loginRecordCache.get(loginName); |
||||
|
||||
if (retryCount == null) |
||||
{ |
||||
retryCount = new AtomicInteger(0); |
||||
loginRecordCache.put(loginName, retryCount); |
||||
} |
||||
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue()) |
||||
{ |
||||
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount)); |
||||
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue()); |
||||
} |
||||
|
||||
if (!matches(user, password)) |
||||
{ |
||||
SystemLogUtils.log(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount, password)); |
||||
loginRecordCache.put(loginName, retryCount); |
||||
throw new UserPasswordNotMatchException(); |
||||
} |
||||
else |
||||
{ |
||||
clearLoginRecordCache(loginName); |
||||
} |
||||
} |
||||
|
||||
public boolean matches(User user, String newPassword) |
||||
{ |
||||
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt())); |
||||
} |
||||
|
||||
public void clearLoginRecordCache(String username) |
||||
{ |
||||
loginRecordCache.remove(username); |
||||
} |
||||
|
||||
public String encryptPassword(String username, String password, String salt) |
||||
{ |
||||
return new Md5Hash(username + password + salt).toHex().toString(); |
||||
} |
||||
|
||||
public static void main(String[] args) |
||||
{ |
||||
//System.out.println(new PasswordService().encryptPassword("admin", "admin123", "111111"));
|
||||
//System.out.println(new PasswordService().encryptPassword("ry", "admin123", "222222"));
|
||||
System.out.println(new PasswordService().encryptPassword("ly", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("ce", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("zs", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("ls", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("ww", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("zl", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("sq", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("zb", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("wj", "admin123", "123456")); |
||||
System.out.println(new PasswordService().encryptPassword("ys", "admin123", "123456")); |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
package com.ruoyi.framework.shiro.service; |
||||
|
||||
import org.apache.shiro.SecurityUtils; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* RuoYi首创 js调用 thymeleaf 实现按钮权限可见性 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class PermissionService |
||||
{ |
||||
public String hasPermi(String permission) |
||||
{ |
||||
return isPermittedOperator(permission) ? "" : "hidden"; |
||||
} |
||||
|
||||
private boolean isPermittedOperator(String permission) |
||||
{ |
||||
if (SecurityUtils.getSubject().isPermitted(permission)) |
||||
{ |
||||
return true; |
||||
} |
||||
else |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,115 @@
|
||||
package com.ruoyi.framework.shiro.session; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
import org.apache.shiro.session.Session; |
||||
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession; |
||||
import com.ruoyi.project.monitor.online.domain.UserOnline; |
||||
import com.ruoyi.project.monitor.online.service.IUserOnlineService; |
||||
|
||||
/** |
||||
* 针对自定义的ShiroSession的db操作 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO |
||||
{ |
||||
/** |
||||
* 同步session到数据库的周期 单位为毫秒(默认1分钟) |
||||
*/ |
||||
@Value("${shiro.session.dbSyncPeriod}") |
||||
private int dbSyncPeriod; |
||||
|
||||
/** |
||||
* 上次同步数据库的时间戳 |
||||
*/ |
||||
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP"; |
||||
|
||||
@Autowired |
||||
private IUserOnlineService onlineService; |
||||
|
||||
@Autowired |
||||
private OnlineSessionFactory onlineSessionFactory; |
||||
|
||||
public OnlineSessionDAO() |
||||
{ |
||||
super(); |
||||
} |
||||
|
||||
public OnlineSessionDAO(long expireTime) |
||||
{ |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* 根据会话ID获取会话 |
||||
* |
||||
* @param sessionId 会话ID |
||||
* @return ShiroSession |
||||
*/ |
||||
@Override |
||||
protected Session doReadSession(Serializable sessionId) |
||||
{ |
||||
UserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId)); |
||||
if (userOnline == null) |
||||
{ |
||||
return null; |
||||
} |
||||
return onlineSessionFactory.createSession(userOnline); |
||||
} |
||||
|
||||
/** |
||||
* 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用 |
||||
*/ |
||||
public void syncToDb(OnlineSession onlineSession) |
||||
{ |
||||
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP); |
||||
if (lastSyncTimestamp != null) |
||||
{ |
||||
boolean needSync = true; |
||||
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime(); |
||||
if (deltaTime < dbSyncPeriod * 60 * 1000) |
||||
{ |
||||
// 时间差不足 无需同步
|
||||
needSync = false; |
||||
} |
||||
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L; |
||||
|
||||
// session 数据变更了 同步
|
||||
if (isGuest == false && onlineSession.isAttributeChanged()) |
||||
{ |
||||
needSync = true; |
||||
} |
||||
|
||||
if (needSync == false) |
||||
{ |
||||
return; |
||||
} |
||||
} |
||||
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime()); |
||||
// 更新完后 重置标识
|
||||
if (onlineSession.isAttributeChanged()) |
||||
{ |
||||
onlineSession.resetAttributeChanged(); |
||||
} |
||||
onlineService.saveOnline(UserOnline.fromOnlineSession(onlineSession)); |
||||
} |
||||
|
||||
/** |
||||
* 当会话过期/停止(如用户退出时)属性等会调用 |
||||
*/ |
||||
@Override |
||||
protected void doDelete(Session session) |
||||
{ |
||||
OnlineSession onlineSession = (OnlineSession) session; |
||||
if (null == onlineSession) |
||||
{ |
||||
return; |
||||
} |
||||
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line); |
||||
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId())); |
||||
} |
||||
} |
@ -0,0 +1,56 @@
|
||||
package com.ruoyi.framework.shiro.session; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import org.apache.shiro.session.Session; |
||||
import org.apache.shiro.session.mgt.SessionContext; |
||||
import org.apache.shiro.session.mgt.SessionFactory; |
||||
import org.apache.shiro.web.session.mgt.WebSessionContext; |
||||
import org.springframework.stereotype.Component; |
||||
import com.ruoyi.common.utils.ServletUtils; |
||||
import com.ruoyi.common.utils.IpUtils; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession; |
||||
import com.ruoyi.project.monitor.online.domain.UserOnline; |
||||
import eu.bitwalker.useragentutils.UserAgent; |
||||
|
||||
/** |
||||
* 自定义sessionFactory会话 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class OnlineSessionFactory implements SessionFactory |
||||
{ |
||||
public Session createSession(UserOnline userOnline) |
||||
{ |
||||
OnlineSession onlineSession = userOnline.getSession(); |
||||
if (StringUtils.isNotNull(onlineSession) && onlineSession.getId() == null) |
||||
{ |
||||
onlineSession.setId(userOnline.getSessionId()); |
||||
} |
||||
return userOnline.getSession(); |
||||
} |
||||
|
||||
@Override |
||||
public Session createSession(SessionContext initData) |
||||
{ |
||||
OnlineSession session = new OnlineSession(); |
||||
if (initData != null && initData instanceof WebSessionContext) |
||||
{ |
||||
WebSessionContext sessionContext = (WebSessionContext) initData; |
||||
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest(); |
||||
if (request != null) |
||||
{ |
||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); |
||||
// 获取客户端操作系统
|
||||
String os = userAgent.getOperatingSystem().getName(); |
||||
// 获取客户端浏览器
|
||||
String browser = userAgent.getBrowser().getName(); |
||||
session.setHost(IpUtils.getIpAddr(request)); |
||||
session.setBrowser(browser); |
||||
session.setOs(os); |
||||
} |
||||
} |
||||
return session; |
||||
} |
||||
} |
@ -0,0 +1,86 @@
|
||||
package com.ruoyi.framework.shiro.web.filter; |
||||
|
||||
import javax.servlet.ServletRequest; |
||||
import javax.servlet.ServletResponse; |
||||
import org.apache.shiro.session.SessionException; |
||||
import org.apache.shiro.subject.Subject; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import com.ruoyi.common.constant.Constants; |
||||
import com.ruoyi.common.utils.MessageUtils; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.common.utils.SystemLogUtils; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* 退出过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class); |
||||
|
||||
/** |
||||
* 退出后重定向的地址 |
||||
*/ |
||||
private String loginUrl; |
||||
|
||||
public String getLoginUrl() |
||||
{ |
||||
return loginUrl; |
||||
} |
||||
|
||||
public void setLoginUrl(String loginUrl) |
||||
{ |
||||
this.loginUrl = loginUrl; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception |
||||
{ |
||||
try |
||||
{ |
||||
Subject subject = getSubject(request, response); |
||||
String redirectUrl = getRedirectUrl(request, response, subject); |
||||
try |
||||
{ |
||||
User user = (User) ShiroUtils.getSubjct().getPrincipal(); |
||||
if (StringUtils.isNotNull(user)) |
||||
{ |
||||
String loginName = user.getLoginName(); |
||||
// 记录用户退出日志
|
||||
SystemLogUtils.log(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")); |
||||
} |
||||
// 退出登录
|
||||
subject.logout(); |
||||
} |
||||
catch (SessionException ise) |
||||
{ |
||||
log.error("logout fail.", ise); |
||||
} |
||||
issueRedirect(request, response, redirectUrl); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.debug("Encountered session exception during logout. This can generally safely be ignored.", e); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 退出跳转URL |
||||
*/ |
||||
@Override |
||||
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) |
||||
{ |
||||
String url = getLoginUrl(); |
||||
if (StringUtils.isNotEmpty(url)) |
||||
{ |
||||
return url; |
||||
} |
||||
return super.getRedirectUrl(request, response, subject); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,78 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.captcha; |
||||
|
||||
import javax.servlet.ServletRequest; |
||||
import javax.servlet.ServletResponse; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import org.apache.shiro.web.filter.AccessControlFilter; |
||||
import com.google.code.kaptcha.Constants; |
||||
import com.ruoyi.common.constant.ShiroConstants; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
|
||||
/** |
||||
* 验证码过滤器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class CaptchaValidateFilter extends AccessControlFilter |
||||
{ |
||||
|
||||
/** |
||||
* 是否开启验证码 |
||||
*/ |
||||
private boolean captchaEbabled = true; |
||||
|
||||
/** |
||||
* 验证码类型 |
||||
*/ |
||||
private String captchaType = "math"; |
||||
|
||||
public void setCaptchaEbabled(boolean captchaEbabled) |
||||
{ |
||||
this.captchaEbabled = captchaEbabled; |
||||
} |
||||
|
||||
public void setCaptchaType(String captchaType) |
||||
{ |
||||
this.captchaType = captchaType; |
||||
} |
||||
|
||||
@Override |
||||
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception |
||||
{ |
||||
request.setAttribute(ShiroConstants.CURRENT_EBABLED, captchaEbabled); |
||||
request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType); |
||||
return super.onPreHandle(request, response, mappedValue); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) |
||||
throws Exception |
||||
{ |
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request; |
||||
// 验证码禁用 或不是表单提交 允许访问
|
||||
if (captchaEbabled == false || !"post".equals(httpServletRequest.getMethod().toLowerCase())) |
||||
{ |
||||
return true; |
||||
} |
||||
return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE)); |
||||
} |
||||
|
||||
public boolean validateResponse(HttpServletRequest request, String validateCode) |
||||
{ |
||||
Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); |
||||
String code = String.valueOf(obj != null ? obj : ""); |
||||
if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code)) |
||||
{ |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception |
||||
{ |
||||
request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR); |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,97 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.online; |
||||
|
||||
import java.io.IOException; |
||||
import javax.servlet.ServletRequest; |
||||
import javax.servlet.ServletResponse; |
||||
import org.apache.shiro.session.Session; |
||||
import org.apache.shiro.subject.Subject; |
||||
import org.apache.shiro.web.filter.AccessControlFilter; |
||||
import org.apache.shiro.web.util.WebUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
|
||||
import com.ruoyi.common.constant.ShiroConstants; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO; |
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* 自定义访问控制 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class OnlineSessionFilter extends AccessControlFilter |
||||
{ |
||||
|
||||
/** |
||||
* 强制退出后重定向的地址 |
||||
*/ |
||||
@Value("${shiro.user.loginUrl}") |
||||
private String loginUrl; |
||||
|
||||
@Autowired |
||||
private OnlineSessionDAO onlineSessionDAO; |
||||
|
||||
/** |
||||
* 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false; |
||||
*/ |
||||
@Override |
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) |
||||
throws Exception |
||||
{ |
||||
Subject subject = getSubject(request, response); |
||||
if (subject == null || subject.getSession() == null) |
||||
{ |
||||
return true; |
||||
} |
||||
Session session = onlineSessionDAO.readSession(subject.getSession().getId()); |
||||
if (session != null && session instanceof OnlineSession) |
||||
{ |
||||
OnlineSession onlineSession = (OnlineSession) session; |
||||
request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession); |
||||
// 把user对象设置进去
|
||||
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L; |
||||
if (isGuest == true) |
||||
{ |
||||
User user = ShiroUtils.getUser(); |
||||
if (user != null) |
||||
{ |
||||
onlineSession.setUserId(user.getUserId()); |
||||
onlineSession.setLoginName(user.getLoginName()); |
||||
onlineSession.setDeptName(user.getDept().getDeptName()); |
||||
onlineSession.markAttributeChanged(); |
||||
} |
||||
} |
||||
|
||||
if (onlineSession.getStatus() == OnlineSession.OnlineStatus.off_line) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。 |
||||
*/ |
||||
@Override |
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception |
||||
{ |
||||
Subject subject = getSubject(request, response); |
||||
if (subject != null) |
||||
{ |
||||
subject.logout(); |
||||
} |
||||
saveRequestAndRedirectToLogin(request, response); |
||||
return true; |
||||
} |
||||
|
||||
// 跳转到登录页
|
||||
@Override |
||||
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException |
||||
{ |
||||
WebUtils.issueRedirect(request, response, loginUrl); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,42 @@
|
||||
package com.ruoyi.framework.shiro.web.filter.sync; |
||||
|
||||
import javax.servlet.ServletRequest; |
||||
import javax.servlet.ServletResponse; |
||||
import org.apache.shiro.web.filter.PathMatchingFilter; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
||||
import com.ruoyi.common.constant.ShiroConstants; |
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO; |
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession; |
||||
|
||||
/** |
||||
* 同步Session数据到Db |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class SyncOnlineSessionFilter extends PathMatchingFilter |
||||
{ |
||||
@Autowired |
||||
private OnlineSessionDAO onlineSessionDAO; |
||||
|
||||
/** |
||||
* 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前 |
||||
* |
||||
* @param request |
||||
* @param response |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
@Override |
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception |
||||
{ |
||||
OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION); |
||||
// 如果session stop了 也不同步
|
||||
// session停止时间,如果stopTimestamp不为null,则代表已停止
|
||||
if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) |
||||
{ |
||||
onlineSessionDAO.syncToDb(session); |
||||
} |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,155 @@
|
||||
package com.ruoyi.framework.shiro.web.session; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import org.apache.commons.lang3.time.DateUtils; |
||||
import org.apache.shiro.session.ExpiredSessionException; |
||||
import org.apache.shiro.session.InvalidSessionException; |
||||
import org.apache.shiro.session.Session; |
||||
import org.apache.shiro.session.mgt.DefaultSessionKey; |
||||
import org.apache.shiro.session.mgt.SessionKey; |
||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import com.ruoyi.common.constant.ShiroConstants; |
||||
import com.ruoyi.common.utils.spring.SpringUtils; |
||||
import com.ruoyi.project.monitor.online.domain.OnlineSession; |
||||
import com.ruoyi.project.monitor.online.domain.UserOnline; |
||||
import com.ruoyi.project.monitor.online.service.UserOnlineServiceImpl; |
||||
|
||||
/** |
||||
* 主要是在此如果会话的属性修改了 就标识下其修改了 然后方便 OnlineSessionDao同步 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class OnlineWebSessionManager extends DefaultWebSessionManager |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class); |
||||
|
||||
@Override |
||||
public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException |
||||
{ |
||||
super.setAttribute(sessionKey, attributeKey, value); |
||||
if (value != null && needMarkAttributeChanged(attributeKey)) |
||||
{ |
||||
OnlineSession s = (OnlineSession) doGetSession(sessionKey); |
||||
s.markAttributeChanged(); |
||||
} |
||||
} |
||||
|
||||
private boolean needMarkAttributeChanged(Object attributeKey) |
||||
{ |
||||
if (attributeKey == null) |
||||
{ |
||||
return false; |
||||
} |
||||
String attributeKeyStr = attributeKey.toString(); |
||||
// 优化 flash属性没必要持久化
|
||||
if (attributeKeyStr.startsWith("org.springframework")) |
||||
{ |
||||
return false; |
||||
} |
||||
if (attributeKeyStr.startsWith("javax.servlet")) |
||||
{ |
||||
return false; |
||||
} |
||||
if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME)) |
||||
{ |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException |
||||
{ |
||||
Object removed = super.removeAttribute(sessionKey, attributeKey); |
||||
if (removed != null) |
||||
{ |
||||
OnlineSession s = (OnlineSession) doGetSession(sessionKey); |
||||
s.markAttributeChanged(); |
||||
} |
||||
|
||||
return removed; |
||||
} |
||||
|
||||
/** |
||||
* 验证session是否有效 用于删除过期session |
||||
*/ |
||||
@Override |
||||
public void validateSessions() |
||||
{ |
||||
if (log.isInfoEnabled()) |
||||
{ |
||||
log.info("invalidation sessions..."); |
||||
} |
||||
|
||||
int invalidCount = 0; |
||||
|
||||
int timeout = (int) this.getGlobalSessionTimeout(); |
||||
Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout); |
||||
UserOnlineServiceImpl userOnlineService = SpringUtils.getBean(UserOnlineServiceImpl.class); |
||||
List<UserOnline> userOnlineList = userOnlineService.selectOnlineByExpired(expiredDate); |
||||
// 批量过期删除
|
||||
List<String> needOfflineIdList = new ArrayList<String>(); |
||||
for (UserOnline userOnline : userOnlineList) |
||||
{ |
||||
try |
||||
{ |
||||
SessionKey key = new DefaultSessionKey(userOnline.getSessionId()); |
||||
Session session = retrieveSession(key); |
||||
if (session != null) |
||||
{ |
||||
throw new InvalidSessionException(); |
||||
} |
||||
} |
||||
catch (InvalidSessionException e) |
||||
{ |
||||
if (log.isDebugEnabled()) |
||||
{ |
||||
boolean expired = (e instanceof ExpiredSessionException); |
||||
String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]" |
||||
+ (expired ? " (expired)" : " (stopped)"); |
||||
log.debug(msg); |
||||
} |
||||
invalidCount++; |
||||
needOfflineIdList.add(userOnline.getSessionId()); |
||||
} |
||||
|
||||
} |
||||
if (needOfflineIdList.size() > 0) |
||||
{ |
||||
try |
||||
{ |
||||
userOnlineService.batchDeleteOnline(needOfflineIdList); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.error("batch delete db session error.", e); |
||||
} |
||||
} |
||||
|
||||
if (log.isInfoEnabled()) |
||||
{ |
||||
String msg = "Finished invalidation session."; |
||||
if (invalidCount > 0) |
||||
{ |
||||
msg += " [" + invalidCount + "] sessions were stopped."; |
||||
} |
||||
else |
||||
{ |
||||
msg += " No sessions were stopped."; |
||||
} |
||||
log.info(msg); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Override |
||||
protected Collection<Session> getActiveSessions() |
||||
{ |
||||
throw new UnsupportedOperationException("getActiveSessions method not supported"); |
||||
} |
||||
} |
@ -0,0 +1,141 @@
|
||||
package com.ruoyi.framework.shiro.web.session; |
||||
|
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.ScheduledExecutorService; |
||||
import java.util.concurrent.TimeUnit; |
||||
import org.apache.shiro.session.mgt.DefaultSessionManager; |
||||
import org.apache.shiro.session.mgt.SessionValidationScheduler; |
||||
import org.apache.shiro.session.mgt.ValidatingSessionManager; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* 自定义任务调度器完成 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class SpringSessionValidationScheduler implements SessionValidationScheduler |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class); |
||||
|
||||
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL; |
||||
|
||||
/** |
||||
* 定时器,用于处理超时的挂起请求,也用于连接断开时的重连。 |
||||
*/ |
||||
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); |
||||
|
||||
private volatile boolean enabled = false; |
||||
|
||||
/** |
||||
* The session manager used to validate sessions. |
||||
*/ |
||||
private ValidatingSessionManager sessionManager; |
||||
|
||||
/** |
||||
* The session validation interval in milliseconds. |
||||
*/ |
||||
private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL; |
||||
|
||||
/** |
||||
* Default constructor. |
||||
*/ |
||||
public SpringSessionValidationScheduler() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Constructor that specifies the session manager that should be used for validating sessions. |
||||
* |
||||
* @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions. |
||||
*/ |
||||
public SpringSessionValidationScheduler(ValidatingSessionManager sessionManager) |
||||
{ |
||||
this.sessionManager = sessionManager; |
||||
} |
||||
|
||||
public void setSessionManager(ValidatingSessionManager sessionManager) |
||||
{ |
||||
this.sessionManager = sessionManager; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isEnabled() |
||||
{ |
||||
return this.enabled; |
||||
} |
||||
|
||||
/** |
||||
* Specifies how frequently (in milliseconds) this Scheduler will call the |
||||
* {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions() |
||||
* ValidatingSessionManager#validateSessions()} method. |
||||
* |
||||
* <p> |
||||
* Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}. |
||||
* |
||||
* @param sessionValidationInterval |
||||
*/ |
||||
public void setSessionValidationInterval(long sessionValidationInterval) |
||||
{ |
||||
this.sessionValidationInterval = sessionValidationInterval; |
||||
} |
||||
|
||||
/** |
||||
* Starts session validation by creating a spring PeriodicTrigger. |
||||
*/ |
||||
@Override |
||||
public void enableSessionValidation() |
||||
{ |
||||
|
||||
enabled = true; |
||||
|
||||
if (log.isDebugEnabled()) |
||||
{ |
||||
log.debug("Scheduling session validation job using Spring Scheduler with " |
||||
+ "session validation interval of [" + sessionValidationInterval + "]ms..."); |
||||
} |
||||
|
||||
try |
||||
{ |
||||
executorService.scheduleAtFixedRate(new Runnable() |
||||
{ |
||||
@Override |
||||
public void run() |
||||
{ |
||||
if (enabled) |
||||
{ |
||||
sessionManager.validateSessions(); |
||||
} |
||||
} |
||||
}, 1000, sessionValidationInterval, TimeUnit.MILLISECONDS); |
||||
|
||||
this.enabled = true; |
||||
|
||||
if (log.isDebugEnabled()) |
||||
{ |
||||
log.debug("Session validation job successfully scheduled with Spring Scheduler."); |
||||
} |
||||
|
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
if (log.isErrorEnabled()) |
||||
{ |
||||
log.error( |
||||
"Error starting the Spring Scheduler session validation job. Session validation may not occur.", |
||||
e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void disableSessionValidation() |
||||
{ |
||||
if (log.isDebugEnabled()) |
||||
{ |
||||
log.debug("Stopping Spring Scheduler session validation job..."); |
||||
} |
||||
|
||||
this.enabled = false; |
||||
} |
||||
} |
@ -0,0 +1,131 @@
|
||||
package com.ruoyi.framework.web.controller; |
||||
|
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import org.springframework.beans.propertyeditors.CustomDateEditor; |
||||
import org.springframework.web.bind.WebDataBinder; |
||||
import org.springframework.web.bind.annotation.InitBinder; |
||||
import com.github.pagehelper.PageHelper; |
||||
import com.github.pagehelper.PageInfo; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.framework.web.domain.AjaxResult; |
||||
import com.ruoyi.framework.web.page.PageDomain; |
||||
import com.ruoyi.framework.web.page.TableDataInfo; |
||||
import com.ruoyi.framework.web.page.TableSupport; |
||||
import com.ruoyi.project.system.user.domain.User; |
||||
|
||||
/** |
||||
* web层通用数据处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class BaseController |
||||
{ |
||||
/** |
||||
* 将前台传递过来的日期格式的字符串,自动转化为Date类型 |
||||
*/ |
||||
@InitBinder |
||||
public void initBinder(WebDataBinder binder) |
||||
{ |
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
||||
dateFormat.setLenient(false); |
||||
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); |
||||
} |
||||
|
||||
/** |
||||
* 设置请求分页数据 |
||||
*/ |
||||
protected void startPage() |
||||
{ |
||||
PageDomain pageDomain = TableSupport.buildPageRequest(); |
||||
Integer pageNum = pageDomain.getPageNum(); |
||||
Integer pageSize = pageDomain.getPageSize(); |
||||
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) |
||||
{ |
||||
String orderBy = pageDomain.getOrderBy(); |
||||
PageHelper.startPage(pageNum, pageSize, orderBy); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 响应请求分页数据 |
||||
*/ |
||||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
||||
protected TableDataInfo getDataTable(List<?> list) |
||||
{ |
||||
TableDataInfo rspData = new TableDataInfo(); |
||||
rspData.setRows(list); |
||||
rspData.setTotal(new PageInfo(list).getTotal()); |
||||
return rspData; |
||||
} |
||||
|
||||
/** |
||||
* 返回成功 |
||||
*/ |
||||
public AjaxResult success() |
||||
{ |
||||
return AjaxResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 返回失败消息 |
||||
*/ |
||||
public AjaxResult error() |
||||
{ |
||||
return AjaxResult.error(); |
||||
} |
||||
|
||||
/** |
||||
* 返回成功消息 |
||||
*/ |
||||
public AjaxResult success(String message) |
||||
{ |
||||
return AjaxResult.success(message); |
||||
} |
||||
|
||||
/** |
||||
* 返回失败消息 |
||||
*/ |
||||
public AjaxResult error(String message) |
||||
{ |
||||
return AjaxResult.error(message); |
||||
} |
||||
|
||||
/** |
||||
* 返回错误码消息 |
||||
*/ |
||||
public AjaxResult error(int code, String message) |
||||
{ |
||||
return AjaxResult.error(code, message); |
||||
} |
||||
|
||||
/** |
||||
* 页面跳转 |
||||
*/ |
||||
public String redirect(String url) |
||||
{ |
||||
return StringUtils.format("redirect:{}", url); |
||||
} |
||||
|
||||
public User getUser() |
||||
{ |
||||
return ShiroUtils.getUser(); |
||||
} |
||||
|
||||
public void setUser(User user) |
||||
{ |
||||
ShiroUtils.setUser(user); |
||||
} |
||||
|
||||
public Long getUserId() |
||||
{ |
||||
return getUser().getUserId(); |
||||
} |
||||
|
||||
public String getLoginName() |
||||
{ |
||||
return getUser().getLoginName(); |
||||
} |
||||
} |
@ -0,0 +1,94 @@
|
||||
package com.ruoyi.framework.web.domain; |
||||
|
||||
import java.util.HashMap; |
||||
|
||||
/** |
||||
* 操作消息提醒 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class AjaxResult extends HashMap<String, Object> |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* 初始化一个新创建的 Message 对象 |
||||
*/ |
||||
public AjaxResult() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* 返回错误消息 |
||||
* |
||||
* @return 错误消息 |
||||
*/ |
||||
public static AjaxResult error() |
||||
{ |
||||
return error(1, "操作失败"); |
||||
} |
||||
|
||||
/** |
||||
* 返回错误消息 |
||||
* |
||||
* @param msg 内容 |
||||
* @return 错误消息 |
||||
*/ |
||||
public static AjaxResult error(String msg) |
||||
{ |
||||
return error(500, msg); |
||||
} |
||||
|
||||
/** |
||||
* 返回错误消息 |
||||
* |
||||
* @param code 错误码 |
||||
* @param msg 内容 |
||||
* @return 错误消息 |
||||
*/ |
||||
public static AjaxResult error(int code, String msg) |
||||
{ |
||||
AjaxResult json = new AjaxResult(); |
||||
json.put("code", code); |
||||
json.put("msg", msg); |
||||
return json; |
||||
} |
||||
|
||||
/** |
||||
* 返回成功消息 |
||||
* |
||||
* @param msg 内容 |
||||
* @return 成功消息 |
||||
*/ |
||||
public static AjaxResult success(String msg) |
||||
{ |
||||
AjaxResult json = new AjaxResult(); |
||||
json.put("msg", msg); |
||||
json.put("code", 0); |
||||
return json; |
||||
} |
||||
|
||||
/** |
||||
* 返回成功消息 |
||||
* |
||||
* @return 成功消息 |
||||
*/ |
||||
public static AjaxResult success() |
||||
{ |
||||
return AjaxResult.success("操作成功"); |
||||
} |
||||
|
||||
/** |
||||
* 返回成功消息 |
||||
* |
||||
* @param key 键值 |
||||
* @param value 内容 |
||||
* @return 成功消息 |
||||
*/ |
||||
@Override |
||||
public AjaxResult put(String key, Object value) |
||||
{ |
||||
super.put(key, value); |
||||
return this; |
||||
} |
||||
} |
@ -0,0 +1,98 @@
|
||||
package com.ruoyi.framework.web.domain; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Date; |
||||
import com.ruoyi.common.utils.DateUtils; |
||||
|
||||
/** |
||||
* Entity基类 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class BaseEntity implements Serializable |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
/** 搜索值 */ |
||||
private String searchValue; |
||||
/** 创建者 */ |
||||
private String createBy; |
||||
/** 创建时间 */ |
||||
private Date createTime; |
||||
/** 更新者 */ |
||||
private String updateBy; |
||||
/** 更新时间 */ |
||||
private Date updateTime; |
||||
/** 备注 */ |
||||
private String remark; |
||||
|
||||
public String getSearchValue() |
||||
{ |
||||
return searchValue; |
||||
} |
||||
|
||||
public void setSearchValue(String searchValue) |
||||
{ |
||||
this.searchValue = searchValue; |
||||
} |
||||
|
||||
public String getCreateBy() |
||||
{ |
||||
return createBy; |
||||
} |
||||
|
||||
public void setCreateBy(String createBy) |
||||
{ |
||||
this.createBy = createBy; |
||||
} |
||||
|
||||
public String getCreateTimeStr() |
||||
{ |
||||
return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, createTime) : ""; |
||||
} |
||||
|
||||
public String getCreateDateTimeStr() |
||||
{ |
||||
return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime) : ""; |
||||
} |
||||
|
||||
public void setCreateTime(Date createTime) |
||||
{ |
||||
this.createTime = createTime; |
||||
} |
||||
|
||||
public String getUpdateBy() |
||||
{ |
||||
return updateBy; |
||||
} |
||||
|
||||
public void setUpdateBy(String updateBy) |
||||
{ |
||||
this.updateBy = updateBy; |
||||
} |
||||
|
||||
public String getUpdateTimeStr() |
||||
{ |
||||
return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, updateTime) : ""; |
||||
} |
||||
|
||||
public String getUpdateDateTimeStr() |
||||
{ |
||||
return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, updateTime) : ""; |
||||
} |
||||
|
||||
public void setUpdateTime(Date updateTime) |
||||
{ |
||||
this.updateTime = updateTime; |
||||
} |
||||
|
||||
public String getRemark() |
||||
{ |
||||
return remark; |
||||
} |
||||
|
||||
public void setRemark(String remark) |
||||
{ |
||||
this.remark = remark; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,72 @@
|
||||
package com.ruoyi.framework.web.exception; |
||||
|
||||
import org.apache.shiro.authz.AuthorizationException; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.web.HttpRequestMethodNotSupportedException; |
||||
import org.springframework.web.bind.annotation.ExceptionHandler; |
||||
import org.springframework.web.bind.annotation.RestControllerAdvice; |
||||
|
||||
import com.ruoyi.common.exception.DemoModeException; |
||||
import com.ruoyi.framework.web.domain.AjaxResult; |
||||
|
||||
/** |
||||
* 自定义异常处理器 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@RestControllerAdvice |
||||
public class DefaultExceptionHandler |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class); |
||||
|
||||
/** |
||||
* 权限校验失败 |
||||
*/ |
||||
@ExceptionHandler(AuthorizationException.class) |
||||
public AjaxResult handleAuthorizationException(AuthorizationException e) |
||||
{ |
||||
log.error(e.getMessage(), e); |
||||
return AjaxResult.error("您没有数据的权限,请联系管理员添加"); |
||||
} |
||||
|
||||
/** |
||||
* 请求方式不支持 |
||||
*/ |
||||
@ExceptionHandler({ HttpRequestMethodNotSupportedException.class }) |
||||
public AjaxResult handleException(HttpRequestMethodNotSupportedException e) |
||||
{ |
||||
log.error(e.getMessage(), e); |
||||
return AjaxResult.error("不支持' " + e.getMethod() + "'请求"); |
||||
} |
||||
|
||||
/** |
||||
* 拦截未知的运行时异常 |
||||
*/ |
||||
@ExceptionHandler(RuntimeException.class) |
||||
public AjaxResult notFount(RuntimeException e) |
||||
{ |
||||
log.error("运行时异常:", e); |
||||
return AjaxResult.error("运行时异常:" + e.getMessage()); |
||||
} |
||||
|
||||
/** |
||||
* 系统异常 |
||||
*/ |
||||
@ExceptionHandler(Exception.class) |
||||
public AjaxResult handleException(Exception e) |
||||
{ |
||||
log.error(e.getMessage(), e); |
||||
return AjaxResult.error("服务器错误,请联系管理员"); |
||||
} |
||||
|
||||
/** |
||||
* 演示模式异常 |
||||
*/ |
||||
@ExceptionHandler(DemoModeException.class) |
||||
public AjaxResult demoModeException(DemoModeException e) |
||||
{ |
||||
return AjaxResult.error("演示模式,不允许操作"); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,70 @@
|
||||
package com.ruoyi.framework.web.page; |
||||
|
||||
import com.ruoyi.common.utils.StringUtils; |
||||
|
||||
/** |
||||
* 分页数据 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class PageDomain |
||||
{ |
||||
/** 当前记录起始索引 */ |
||||
private Integer pageNum; |
||||
/** 每页显示记录数 */ |
||||
private Integer pageSize; |
||||
/** 排序列 */ |
||||
private String orderByColumn; |
||||
/** 排序的方向 "desc" 或者 "asc". */ |
||||
private String isAsc; |
||||
|
||||
public String getOrderBy() |
||||
{ |
||||
if (StringUtils.isEmpty(orderByColumn)) |
||||
{ |
||||
return ""; |
||||
} |
||||
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; |
||||
} |
||||
|
||||
public Integer getPageNum() |
||||
{ |
||||
return pageNum; |
||||
} |
||||
|
||||
public void setPageNum(Integer pageNum) |
||||
{ |
||||
this.pageNum = pageNum; |
||||
} |
||||
|
||||
public Integer getPageSize() |
||||
{ |
||||
return pageSize; |
||||
} |
||||
|
||||
public void setPageSize(Integer pageSize) |
||||
{ |
||||
this.pageSize = pageSize; |
||||
} |
||||
|
||||
public String getOrderByColumn() |
||||
{ |
||||
return orderByColumn; |
||||
} |
||||
|
||||
public void setOrderByColumn(String orderByColumn) |
||||
{ |
||||
this.orderByColumn = orderByColumn; |
||||
} |
||||
|
||||
public String getIsAsc() |
||||
{ |
||||
return isAsc; |
||||
} |
||||
|
||||
public void setIsAsc(String isAsc) |
||||
{ |
||||
this.isAsc = isAsc; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,58 @@
|
||||
package com.ruoyi.framework.web.page; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 表格分页数据对象 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class TableDataInfo implements Serializable |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
/** 总记录数 */ |
||||
private long total; |
||||
/** 列表数据 */ |
||||
private List<?> rows; |
||||
|
||||
/** |
||||
* 表格数据对象 |
||||
*/ |
||||
public TableDataInfo() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* 分页 |
||||
* |
||||
* @param list 列表数据 |
||||
* @param total 总记录数 |
||||
*/ |
||||
public TableDataInfo(List<?> list, int total) |
||||
{ |
||||
this.rows = list; |
||||
this.total = total; |
||||
} |
||||
|
||||
public long getTotal() |
||||
{ |
||||
return total; |
||||
} |
||||
|
||||
public void setTotal(long total) |
||||
{ |
||||
this.total = total; |
||||
} |
||||
|
||||
public List<?> getRows() |
||||
{ |
||||
return rows; |
||||
} |
||||
|
||||
public void setRows(List<?> rows) |
||||
{ |
||||
this.rows = rows; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,31 @@
|
||||
package com.ruoyi.framework.web.page; |
||||
|
||||
import com.ruoyi.common.utils.ServletUtils; |
||||
import com.ruoyi.common.constant.Constants; |
||||
|
||||
/** |
||||
* 表格数据处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class TableSupport |
||||
{ |
||||
/** |
||||
* 封装分页对象 |
||||
*/ |
||||
public static PageDomain getPageDomain() |
||||
{ |
||||
PageDomain pageDomain = new PageDomain(); |
||||
pageDomain.setPageNum(ServletUtils.getParameterToInt(Constants.PAGENUM)); |
||||
pageDomain.setPageSize(ServletUtils.getParameterToInt(Constants.PAGESIZE)); |
||||
pageDomain.setOrderByColumn(ServletUtils.getParameter(Constants.ORDERBYCOLUMN)); |
||||
pageDomain.setIsAsc(ServletUtils.getParameter(Constants.ISASC)); |
||||
return pageDomain; |
||||
} |
||||
|
||||
public static PageDomain buildPageRequest() |
||||
{ |
||||
return getPageDomain(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,29 @@
|
||||
package com.ruoyi.framework.web.service; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
import com.ruoyi.project.system.config.service.IConfigService; |
||||
|
||||
/** |
||||
* RuoYi首创 html调用 thymeleaf 实现参数管理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class ConfigService |
||||
{ |
||||
@Autowired |
||||
private IConfigService configService; |
||||
|
||||
/** |
||||
* 根据键名查询参数配置信息 |
||||
* |
||||
* @param configName 参数名称 |
||||
* @return 参数键值 |
||||
*/ |
||||
public String selectConfigByKey(String configKey) |
||||
{ |
||||
return configService.selectConfigByKey(configKey); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,30 @@
|
||||
package com.ruoyi.framework.web.service; |
||||
|
||||
import java.util.List; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
import com.ruoyi.project.system.dict.domain.DictData; |
||||
import com.ruoyi.project.system.dict.service.IDictDataService; |
||||
|
||||
/** |
||||
* RuoYi首创 html调用 thymeleaf 实现字典读取 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component |
||||
public class DictService |
||||
{ |
||||
@Autowired |
||||
private IDictDataService dictDataService; |
||||
|
||||
/** |
||||
* 根据字典类型查询字典数据信息 |
||||
* |
||||
* @param dictType 字典类型 |
||||
* @return 参数键值 |
||||
*/ |
||||
public List<DictData> selectDictData(String dictType) |
||||
{ |
||||
return dictDataService.selectDictDataByType(dictType); |
||||
} |
||||
} |
@ -0,0 +1,84 @@
|
||||
package com.ruoyi.project.common; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URLEncoder; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.util.ResourceUtils; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
||||
/** |
||||
* 通用请求处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Controller |
||||
public class CommonController |
||||
{ |
||||
@RequestMapping("common/download") |
||||
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) |
||||
{ |
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); |
||||
try |
||||
{ |
||||
String filePath = ResourceUtils.getURL("classpath:").getPath() + "static/file/" + fileName; |
||||
|
||||
response.setCharacterEncoding("utf-8"); |
||||
response.setContentType("multipart/form-data"); |
||||
response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName)); |
||||
File file = new File(filePath); |
||||
InputStream inputStream = new FileInputStream(file); |
||||
OutputStream os = response.getOutputStream(); |
||||
byte[] b = new byte[1024]; |
||||
int length; |
||||
while ((length = inputStream.read(b)) > 0) |
||||
{ |
||||
os.write(b, 0, length); |
||||
} |
||||
os.close(); |
||||
inputStream.close(); |
||||
if (delete && file.exists()) |
||||
{ |
||||
file.delete(); |
||||
} |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException |
||||
{ |
||||
final String agent = request.getHeader("USER-AGENT"); |
||||
String filename = fileName; |
||||
if (agent.contains("MSIE")) |
||||
{ |
||||
// IE浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8"); |
||||
filename = filename.replace("+", " "); |
||||
} |
||||
else if (agent.contains("Firefox")) |
||||
{ |
||||
// 火狐浏览器
|
||||
filename = new String(fileName.getBytes(), "ISO8859-1"); |
||||
} |
||||
else if (agent.contains("Chrome")) |
||||
{ |
||||
// google浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8"); |
||||
} |
||||
else |
||||
{ |
||||
// 其它浏览器
|
||||
filename = URLEncoder.encode(filename, "utf-8"); |
||||
} |
||||
return filename; |
||||
|
||||
} |
||||
} |
@ -0,0 +1,26 @@
|
||||
package com.ruoyi.project.monitor.druid; |
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import com.ruoyi.framework.web.controller.BaseController; |
||||
|
||||
/** |
||||
* druid 监控 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Controller |
||||
@RequestMapping("/monitor/data") |
||||
public class DruidController extends BaseController |
||||
{ |
||||
private String prefix = "/monitor/druid"; |
||||
|
||||
@RequiresPermissions("monitor:data:view") |
||||
@GetMapping() |
||||
public String index() |
||||
{ |
||||
return redirect(prefix + "/index"); |
||||
} |
||||
} |
@ -0,0 +1,159 @@
|
||||
package com.ruoyi.project.monitor.job.controller; |
||||
|
||||
import java.util.List; |
||||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.ui.Model; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
import com.ruoyi.common.utils.poi.ExcelUtil; |
||||
import com.ruoyi.framework.aspectj.lang.annotation.Log; |
||||
import com.ruoyi.framework.aspectj.lang.constant.BusinessType; |
||||
import com.ruoyi.framework.web.controller.BaseController; |
||||
import com.ruoyi.framework.web.domain.AjaxResult; |
||||
import com.ruoyi.framework.web.page.TableDataInfo; |
||||
import com.ruoyi.project.monitor.job.domain.Job; |
||||
import com.ruoyi.project.monitor.job.service.IJobService; |
||||
|
||||
/** |
||||
* 调度任务信息操作处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Controller |
||||
@RequestMapping("/monitor/job") |
||||
public class JobController extends BaseController |
||||
{ |
||||
private String prefix = "monitor/job"; |
||||
|
||||
@Autowired |
||||
private IJobService jobService; |
||||
|
||||
@RequiresPermissions("monitor:job:view") |
||||
@GetMapping() |
||||
public String job() |
||||
{ |
||||
return prefix + "/job"; |
||||
} |
||||
|
||||
@RequiresPermissions("monitor:job:list") |
||||
@PostMapping("/list") |
||||
@ResponseBody |
||||
public TableDataInfo list(Job job) |
||||
{ |
||||
startPage(); |
||||
List<Job> list = jobService.selectJobList(job); |
||||
return getDataTable(list); |
||||
} |
||||
|
||||
@Log(title = "定时任务", action = BusinessType.EXPORT) |
||||
@PostMapping("/export") |
||||
@ResponseBody |
||||
public AjaxResult export(Job job) throws Exception |
||||
{ |
||||
try |
||||
{ |
||||
List<Job> list = jobService.selectJobList(job); |
||||
ExcelUtil<Job> util = new ExcelUtil<Job>(Job.class); |
||||
return util.exportExcel(list, "job"); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
return error("导出Excel失败,请联系网站管理员!"); |
||||
} |
||||
} |
||||
|
||||
@Log(title = "定时任务", action = BusinessType.DELETE) |
||||
@RequiresPermissions("monitor:job:remove") |
||||
@PostMapping("/remove") |
||||
@ResponseBody |
||||
public AjaxResult remove(String ids) |
||||
{ |
||||
try |
||||
{ |
||||
jobService.deleteJobByIds(ids); |
||||
return success(); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
e.printStackTrace(); |
||||
return error(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 任务调度状态修改 |
||||
*/ |
||||
@Log(title = "定时任务", action = BusinessType.UPDATE) |
||||
@RequiresPermissions("monitor:job:changeStatus") |
||||
@PostMapping("/changeStatus") |
||||
@ResponseBody |
||||
public AjaxResult changeStatus(Job job) |
||||
{ |
||||
if (jobService.changeStatus(job) > 0) |
||||
{ |
||||
return success(); |
||||
} |
||||
return error(); |
||||
} |
||||
|
||||
/** |
||||
* 任务调度立即执行一次 |
||||
*/ |
||||
@Log(title = "定时任务", action = BusinessType.UPDATE) |
||||
@RequiresPermissions("monitor:job:changeStatus") |
||||
@PostMapping("/run") |
||||
@ResponseBody |
||||
public AjaxResult run(Job job) |
||||
{ |
||||
if (jobService.run(job) > 0) |
||||
{ |
||||
return success(); |
||||
} |
||||
return error(); |
||||
} |
||||
|
||||
/** |
||||
* 新增调度 |
||||
*/ |
||||
@Log(title = "定时任务", action = BusinessType.INSERT) |
||||
@RequiresPermissions("monitor:job:add") |
||||
@GetMapping("/add") |
||||
public String add(Model model) |
||||
{ |
||||
return prefix + "/add"; |
||||
} |
||||
|
||||
/** |
||||
* 修改调度 |
||||
*/ |
||||
@Log(title = "定时任务", action = BusinessType.UPDATE) |
||||
@RequiresPermissions("monitor:job:edit") |
||||
@GetMapping("/edit/{jobId}") |
||||
public String edit(@PathVariable("jobId") Long jobId, Model model) |
||||
{ |
||||
Job job = jobService.selectJobById(jobId); |
||||
model.addAttribute("job", job); |
||||
return prefix + "/edit"; |
||||
} |
||||
|
||||
/** |
||||
* 保存调度 |
||||
*/ |
||||
@Log(title = "定时任务", action = BusinessType.SAVE) |
||||
@RequiresPermissions("monitor:job:save") |
||||
@PostMapping("/save") |
||||
@ResponseBody |
||||
public AjaxResult save(Job job) |
||||
{ |
||||
if (jobService.saveJobCron(job) > 0) |
||||
{ |
||||
return success(); |
||||
} |
||||
return error(); |
||||
} |
||||
} |
@ -0,0 +1,85 @@
|
||||
package com.ruoyi.project.monitor.job.controller; |
||||
|
||||
import java.util.List; |
||||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.PostMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
import com.ruoyi.common.utils.poi.ExcelUtil; |
||||
import com.ruoyi.framework.aspectj.lang.annotation.Log; |
||||
import com.ruoyi.framework.aspectj.lang.constant.BusinessType; |
||||
import com.ruoyi.framework.web.controller.BaseController; |
||||
import com.ruoyi.framework.web.domain.AjaxResult; |
||||
import com.ruoyi.framework.web.page.TableDataInfo; |
||||
import com.ruoyi.project.monitor.job.domain.JobLog; |
||||
import com.ruoyi.project.monitor.job.service.IJobLogService; |
||||
|
||||
/** |
||||
* 调度日志操作处理 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Controller |
||||
@RequestMapping("/monitor/jobLog") |
||||
public class JobLogController extends BaseController |
||||
{ |
||||
private String prefix = "monitor/job"; |
||||
|
||||
@Autowired |
||||
private IJobLogService jobLogService; |
||||
|
||||
@RequiresPermissions("monitor:job:view") |
||||
@GetMapping() |
||||
public String jobLog() |
||||
{ |
||||
return prefix + "/jobLog"; |
||||
} |
||||
|
||||
@RequiresPermissions("monitor:job:list") |
||||
@PostMapping("/list") |
||||
@ResponseBody |
||||
public TableDataInfo list(JobLog jobLog) |
||||
{ |
||||
startPage(); |
||||
List<JobLog> list = jobLogService.selectJobLogList(jobLog); |
||||
return getDataTable(list); |
||||
} |
||||
|
||||
@Log(title = "调度日志", action = BusinessType.EXPORT) |
||||
@PostMapping("/export") |
||||
@ResponseBody |
||||
public AjaxResult export(JobLog jobLog) throws Exception |
||||
{ |
||||
try |
||||
{ |
||||
List<JobLog> list = jobLogService.selectJobLogList(jobLog); |
||||
ExcelUtil<JobLog> util = new ExcelUtil<JobLog>(JobLog.class); |
||||
return util.exportExcel(list, "jobLog"); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
return error("导出Excel失败,请联系网站管理员!"); |
||||
} |
||||
} |
||||
|
||||
@Log(title = "调度日志", action = BusinessType.DELETE) |
||||
@RequiresPermissions("monitor:job:remove") |
||||
@PostMapping("/remove") |
||||
@ResponseBody |
||||
public AjaxResult remove(String ids) |
||||
{ |
||||
try |
||||
{ |
||||
jobLogService.deleteJobLogByIds(ids); |
||||
return success(); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
e.printStackTrace(); |
||||
return error(e.getMessage()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,122 @@
|
||||
package com.ruoyi.project.monitor.job.domain; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
||||
import com.ruoyi.framework.web.domain.BaseEntity; |
||||
|
||||
/** |
||||
* 定时任务调度信息 sys_job |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class Job extends BaseEntity implements Serializable |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** 任务ID */ |
||||
@Excel(name = "任务序号", column = "A") |
||||
private Long jobId; |
||||
|
||||
/** 任务名称 */ |
||||
@Excel(name = "任务名称", column = "B") |
||||
private String jobName; |
||||
|
||||
/** 任务组名 */ |
||||
@Excel(name = "任务组名", column = "C") |
||||
private String jobGroup; |
||||
|
||||
/** 任务方法 */ |
||||
@Excel(name = "任务方法", column = "D") |
||||
private String methodName; |
||||
|
||||
/** 方法参数 */ |
||||
@Excel(name = "方法参数", column = "E") |
||||
private String params; |
||||
|
||||
/** cron执行表达式 */ |
||||
@Excel(name = "执行表达式 ", column = "F") |
||||
private String cronExpression; |
||||
|
||||
/** 任务状态(0正常 1暂停) */ |
||||
@Excel(name = "任务状态", column = "G") |
||||
private String status; |
||||
|
||||
public Long getJobId() |
||||
{ |
||||
return jobId; |
||||
} |
||||
|
||||
public void setJobId(Long jobId) |
||||
{ |
||||
this.jobId = jobId; |
||||
} |
||||
|
||||
public String getJobName() |
||||
{ |
||||
return jobName; |
||||
} |
||||
|
||||
public void setJobName(String jobName) |
||||
{ |
||||
this.jobName = jobName; |
||||
} |
||||
|
||||
public String getJobGroup() |
||||
{ |
||||
return jobGroup; |
||||
} |
||||
|
||||
public void setJobGroup(String jobGroup) |
||||
{ |
||||
this.jobGroup = jobGroup; |
||||
} |
||||
|
||||
public String getMethodName() |
||||
{ |
||||
return methodName; |
||||
} |
||||
|
||||
public void setMethodName(String methodName) |
||||
{ |
||||
this.methodName = methodName; |
||||
} |
||||
|
||||
public String getParams() |
||||
{ |
||||
return params; |
||||
} |
||||
|
||||
public void setParams(String params) |
||||
{ |
||||
this.params = params; |
||||
} |
||||
|
||||
public String getCronExpression() |
||||
{ |
||||
return cronExpression; |
||||
} |
||||
|
||||
public void setCronExpression(String cronExpression) |
||||
{ |
||||
this.cronExpression = cronExpression; |
||||
} |
||||
|
||||
public String getStatus() |
||||
{ |
||||
return status; |
||||
} |
||||
|
||||
public void setStatus(String status) |
||||
{ |
||||
this.status = status; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() |
||||
{ |
||||
return "Job [jobId=" + jobId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName=" + methodName |
||||
+ ", params=" + params + ", cronExpression=" + cronExpression + ", status=" + status + "]"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,135 @@
|
||||
package com.ruoyi.project.monitor.job.domain; |
||||
|
||||
import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
||||
import com.ruoyi.framework.web.domain.BaseEntity; |
||||
|
||||
/** |
||||
* 定时任务调度日志信息 sys_job_log |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public class JobLog extends BaseEntity |
||||
{ |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** ID */ |
||||
@Excel(name = "日志序号", column = "A") |
||||
private Long jobLogId; |
||||
|
||||
/** 任务名称 */ |
||||
@Excel(name = "任务名称", column = "B") |
||||
private String jobName; |
||||
|
||||
/** 任务组名 */ |
||||
@Excel(name = "任务组名", column = "C") |
||||
private String jobGroup; |
||||
|
||||
/** 任务方法 */ |
||||
@Excel(name = "任务方法", column = "D") |
||||
private String methodName; |
||||
|
||||
/** 方法参数 */ |
||||
@Excel(name = "方法参数", column = "E") |
||||
private String params; |
||||
|
||||
/** 日志信息 */ |
||||
@Excel(name = "日志信息", column = "F") |
||||
private String jobMessage; |
||||
|
||||
/** 执行状态(0正常 1失败) */ |
||||
@Excel(name = "执行状态", column = "G") |
||||
private String status; |
||||
|
||||
/** 异常信息 */ |
||||
@Excel(name = "异常信息", column = "H") |
||||
private String exceptionInfo; |
||||
|
||||
public Long getJobLogId() |
||||
{ |
||||
return jobLogId; |
||||
} |
||||
|
||||
public void setJobLogId(Long jobLogId) |
||||
{ |
||||
this.jobLogId = jobLogId; |
||||
} |
||||
|
||||
public String getJobName() |
||||
{ |
||||
return jobName; |
||||
} |
||||
|
||||
public void setJobName(String jobName) |
||||
{ |
||||
this.jobName = jobName; |
||||
} |
||||
|
||||
public String getJobGroup() |
||||
{ |
||||
return jobGroup; |
||||
} |
||||
|
||||
public void setJobGroup(String jobGroup) |
||||
{ |
||||
this.jobGroup = jobGroup; |
||||
} |
||||
|
||||
public String getMethodName() |
||||
{ |
||||
return methodName; |
||||
} |
||||
|
||||
public void setMethodName(String methodName) |
||||
{ |
||||
this.methodName = methodName; |
||||
} |
||||
|
||||
public String getParams() |
||||
{ |
||||
return params; |
||||
} |
||||
|
||||
public void setParams(String params) |
||||
{ |
||||
this.params = params; |
||||
} |
||||
|
||||
public String getJobMessage() |
||||
{ |
||||
return jobMessage; |
||||
} |
||||
|
||||
public void setJobMessage(String jobMessage) |
||||
{ |
||||
this.jobMessage = jobMessage; |
||||
} |
||||
|
||||
public String getStatus() |
||||
{ |
||||
return status; |
||||
} |
||||
|
||||
public void setStatus(String status) |
||||
{ |
||||
this.status = status; |
||||
} |
||||
|
||||
public String getExceptionInfo() |
||||
{ |
||||
return exceptionInfo; |
||||
} |
||||
|
||||
public void setExceptionInfo(String exceptionInfo) |
||||
{ |
||||
this.exceptionInfo = exceptionInfo; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() |
||||
{ |
||||
return "JobLog [jobLogId=" + jobLogId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName=" |
||||
+ methodName + ", params=" + params + ", jobMessage=" + jobMessage + ", status=" + status |
||||
+ ", exceptionInfo=" + exceptionInfo + "]"; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.ruoyi.project.monitor.job.mapper; |
||||
|
||||
import java.util.List; |
||||
import com.ruoyi.project.monitor.job.domain.JobLog; |
||||
|
||||
/** |
||||
* 调度任务日志信息 数据层 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface JobLogMapper |
||||
{ |
||||
|
||||
/** |
||||
* 获取quartz调度器日志的计划任务 |
||||
* |
||||
* @param jobLog 调度日志信息 |
||||
* @return 调度任务日志集合 |
||||
*/ |
||||
public List<JobLog> selectJobLogList(JobLog jobLog); |
||||
|
||||
/** |
||||
* 通过调度任务日志ID查询调度信息 |
||||
* |
||||
* @param jobLogId 调度任务日志ID |
||||
* @return 调度任务日志对象信息 |
||||
*/ |
||||
public JobLog selectJobLogById(Long jobLogId); |
||||
|
||||
/** |
||||
* 新增任务日志 |
||||
* |
||||
* @param jobLog 调度日志信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int insertJobLog(JobLog jobLog); |
||||
|
||||
/** |
||||
* 批量删除调度日志信息 |
||||
* |
||||
* @param ids 需要删除的数据ID |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJobLogByIds(String[] ids); |
||||
|
||||
/** |
||||
* 删除任务日志 |
||||
* |
||||
* @param jobId 调度日志ID |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJobLogById(Long jobId); |
||||
|
||||
} |
@ -0,0 +1,69 @@
|
||||
package com.ruoyi.project.monitor.job.mapper; |
||||
|
||||
import java.util.List; |
||||
import com.ruoyi.project.monitor.job.domain.Job; |
||||
|
||||
/** |
||||
* 调度任务信息 数据层 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface JobMapper |
||||
{ |
||||
|
||||
/** |
||||
* 查询调度任务日志集合 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 操作日志集合 |
||||
*/ |
||||
public List<Job> selectJobList(Job job); |
||||
|
||||
/** |
||||
* 查询所有调度任务 |
||||
* |
||||
* @return 调度任务列表 |
||||
*/ |
||||
public List<Job> selectJobAll(); |
||||
|
||||
/** |
||||
* 通过调度ID查询调度任务信息 |
||||
* |
||||
* @param jobId 调度ID |
||||
* @return 角色对象信息 |
||||
*/ |
||||
public Job selectJobById(Long jobId); |
||||
|
||||
/** |
||||
* 通过调度ID删除调度任务信息 |
||||
* |
||||
* @param jobId 调度ID |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJobById(Job job); |
||||
|
||||
/** |
||||
* 批量删除调度任务信息 |
||||
* |
||||
* @param ids 需要删除的数据ID |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJobLogByIds(Long[] ids); |
||||
|
||||
/** |
||||
* 修改调度任务信息 |
||||
* |
||||
* @param job 调度任务信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int updateJob(Job job); |
||||
|
||||
/** |
||||
* 新增调度任务信息 |
||||
* |
||||
* @param job 调度任务信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int insertJob(Job job); |
||||
|
||||
} |
@ -0,0 +1,53 @@
|
||||
package com.ruoyi.project.monitor.job.service; |
||||
|
||||
import java.util.List; |
||||
import com.ruoyi.project.monitor.job.domain.JobLog; |
||||
|
||||
/** |
||||
* 定时任务调度日志信息信息 服务层 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface IJobLogService |
||||
{ |
||||
|
||||
/** |
||||
* 获取quartz调度器日志的计划任务 |
||||
* |
||||
* @param jobLog 调度日志信息 |
||||
* @return 调度任务日志集合 |
||||
*/ |
||||
public List<JobLog> selectJobLogList(JobLog jobLog); |
||||
|
||||
/** |
||||
* 通过调度任务日志ID查询调度信息 |
||||
* |
||||
* @param jobLogId 调度任务日志ID |
||||
* @return 调度任务日志对象信息 |
||||
*/ |
||||
public JobLog selectJobLogById(Long jobLogId); |
||||
|
||||
/** |
||||
* 新增任务日志 |
||||
* |
||||
* @param jobLog 调度日志信息 |
||||
*/ |
||||
public void addJobLog(JobLog jobLog); |
||||
|
||||
/** |
||||
* 批量删除调度日志信息 |
||||
* |
||||
* @param ids 需要删除的数据ID |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJobLogByIds(String ids); |
||||
|
||||
/** |
||||
* 删除任务日志 |
||||
* |
||||
* @param jobId 调度日志ID |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJobLogById(Long jobId); |
||||
|
||||
} |
@ -0,0 +1,101 @@
|
||||
package com.ruoyi.project.monitor.job.service; |
||||
|
||||
import java.util.List; |
||||
import com.ruoyi.project.monitor.job.domain.Job; |
||||
|
||||
/** |
||||
* 定时任务调度信息信息 服务层 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
public interface IJobService |
||||
{ |
||||
|
||||
/** |
||||
* 获取quartz调度器的计划任务 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 调度任务集合 |
||||
*/ |
||||
public List<Job> selectJobList(Job job); |
||||
|
||||
/** |
||||
* 通过调度任务ID查询调度信息 |
||||
* |
||||
* @param jobId 调度任务ID |
||||
* @return 调度任务对象信息 |
||||
*/ |
||||
public Job selectJobById(Long jobId); |
||||
|
||||
/** |
||||
* 暂停任务 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int pauseJob(Job job); |
||||
|
||||
/** |
||||
* 恢复任务 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int resumeJob(Job job); |
||||
|
||||
/** |
||||
* 删除任务后,所对应的trigger也将被删除 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int deleteJob(Job job); |
||||
|
||||
/** |
||||
* 批量删除调度信息 |
||||
* |
||||
* @param ids 需要删除的数据ID |
||||
* @return 结果 |
||||
*/ |
||||
public void deleteJobByIds(String ids); |
||||
|
||||
/** |
||||
* 任务调度状态修改 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int changeStatus(Job job); |
||||
|
||||
/** |
||||
* 立即运行任务 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int run(Job job); |
||||
|
||||
/** |
||||
* 新增任务表达式 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int addJobCron(Job job); |
||||
|
||||
/** |
||||
* 更新任务的时间表达式 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int updateJobCron(Job job); |
||||
|
||||
/** |
||||
* 保存任务的时间表达式 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return 结果 |
||||
*/ |
||||
public int saveJobCron(Job job); |
||||
} |
@ -0,0 +1,80 @@
|
||||
package com.ruoyi.project.monitor.job.service; |
||||
|
||||
import java.util.List; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import com.ruoyi.common.support.Convert; |
||||
import com.ruoyi.project.monitor.job.domain.JobLog; |
||||
import com.ruoyi.project.monitor.job.mapper.JobLogMapper; |
||||
|
||||
/** |
||||
* 定时任务调度日志信息 服务层 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Service("jobLogService") |
||||
public class JobLogServiceImpl implements IJobLogService |
||||
{ |
||||
|
||||
@Autowired |
||||
private JobLogMapper jobLogMapper; |
||||
|
||||
/** |
||||
* 获取quartz调度器日志的计划任务 |
||||
* |
||||
* @param jobLog 调度日志信息 |
||||
* @return 调度任务日志集合 |
||||
*/ |
||||
@Override |
||||
public List<JobLog> selectJobLogList(JobLog jobLog) |
||||
{ |
||||
return jobLogMapper.selectJobLogList(jobLog); |
||||
} |
||||
|
||||
/** |
||||
* 通过调度任务日志ID查询调度信息 |
||||
* |
||||
* @param jobId 调度任务日志ID |
||||
* @return 调度任务日志对象信息 |
||||
*/ |
||||
@Override |
||||
public JobLog selectJobLogById(Long jobLogId) |
||||
{ |
||||
return jobLogMapper.selectJobLogById(jobLogId); |
||||
} |
||||
|
||||
/** |
||||
* 新增任务日志 |
||||
* |
||||
* @param jobLog 调度日志信息 |
||||
*/ |
||||
@Override |
||||
public void addJobLog(JobLog jobLog) |
||||
{ |
||||
jobLogMapper.insertJobLog(jobLog); |
||||
} |
||||
|
||||
/** |
||||
* 批量删除调度日志信息 |
||||
* |
||||
* @param ids 需要删除的数据ID |
||||
* @return 结果 |
||||
*/ |
||||
@Override |
||||
public int deleteJobLogByIds(String ids) |
||||
{ |
||||
return jobLogMapper.deleteJobLogByIds(Convert.toStrArray(ids)); |
||||
} |
||||
|
||||
/** |
||||
* 删除任务日志 |
||||
* |
||||
* @param jobId 调度日志ID |
||||
*/ |
||||
@Override |
||||
public int deleteJobLogById(Long jobId) |
||||
{ |
||||
return jobLogMapper.deleteJobLogById(jobId); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,236 @@
|
||||
package com.ruoyi.project.monitor.job.service; |
||||
|
||||
import java.util.List; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
|
||||
import org.quartz.CronTrigger; |
||||
import org.quartz.Scheduler; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import com.ruoyi.common.constant.ScheduleConstants; |
||||
import com.ruoyi.common.support.Convert; |
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.common.utils.security.ShiroUtils; |
||||
import com.ruoyi.project.monitor.job.domain.Job; |
||||
import com.ruoyi.project.monitor.job.mapper.JobMapper; |
||||
import com.ruoyi.project.monitor.job.util.ScheduleUtils; |
||||
|
||||
/** |
||||
* 定时任务调度信息 服务层 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Service("jobService") |
||||
public class JobServiceImpl implements IJobService |
||||
{ |
||||
@Autowired |
||||
private Scheduler scheduler; |
||||
|
||||
@Autowired |
||||
private JobMapper jobMapper; |
||||
|
||||
/** |
||||
* 项目启动时,初始化定时器 |
||||
*/ |
||||
@PostConstruct |
||||
public void init() |
||||
{ |
||||
List<Job> jobList = jobMapper.selectJobAll(); |
||||
for (Job job : jobList) |
||||
{ |
||||
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, job.getJobId()); |
||||
// 如果不存在,则创建
|
||||
if (cronTrigger == null) |
||||
{ |
||||
ScheduleUtils.createScheduleJob(scheduler, job); |
||||
} |
||||
else |
||||
{ |
||||
ScheduleUtils.updateScheduleJob(scheduler, job); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取quartz调度器的计划任务列表 |
||||
* |
||||
* @param job 调度信息 |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public List<Job> selectJobList(Job job) |
||||
{ |
||||
return jobMapper.selectJobList(job); |
||||
} |
||||
|
||||
/** |
||||
* 通过调度任务ID查询调度信息 |
||||
* |
||||
* @param jobId 调度任务ID |
||||
* @return 调度任务对象信息 |
||||
*/ |
||||
@Override |
||||
public Job selectJobById(Long jobId) |
||||
{ |
||||
return jobMapper.selectJobById(jobId); |
||||
} |
||||
|
||||
/** |
||||
* 暂停任务 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int pauseJob(Job job) |
||||
{ |
||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); |
||||
job.setUpdateBy(ShiroUtils.getLoginName()); |
||||
int rows = jobMapper.updateJob(job); |
||||
if (rows > 0) |
||||
{ |
||||
ScheduleUtils.pauseJob(scheduler, job.getJobId()); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
/** |
||||
* 恢复任务 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int resumeJob(Job job) |
||||
{ |
||||
job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); |
||||
job.setUpdateBy(ShiroUtils.getLoginName()); |
||||
int rows = jobMapper.updateJob(job); |
||||
if (rows > 0) |
||||
{ |
||||
ScheduleUtils.resumeJob(scheduler, job.getJobId()); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
/** |
||||
* 删除任务后,所对应的trigger也将被删除 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int deleteJob(Job job) |
||||
{ |
||||
int rows = jobMapper.deleteJobById(job); |
||||
if (rows > 0) |
||||
{ |
||||
ScheduleUtils.deleteScheduleJob(scheduler, job.getJobId()); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
/** |
||||
* 批量删除调度信息 |
||||
* |
||||
* @param ids 需要删除的数据ID |
||||
* @return 结果 |
||||
*/ |
||||
@Override |
||||
public void deleteJobByIds(String ids) |
||||
{ |
||||
Long[] jobIds = Convert.toLongArray(ids); |
||||
for (Long jobId : jobIds) |
||||
{ |
||||
Job job = jobMapper.selectJobById(jobId); |
||||
deleteJob(job); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 任务调度状态修改 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int changeStatus(Job job) |
||||
{ |
||||
int rows = 0; |
||||
String status = job.getStatus(); |
||||
if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) |
||||
{ |
||||
rows = resumeJob(job); |
||||
} |
||||
else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) |
||||
{ |
||||
rows = pauseJob(job); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
/** |
||||
* 立即运行任务 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int run(Job job) |
||||
{ |
||||
return ScheduleUtils.run(scheduler, selectJobById(job.getJobId())); |
||||
} |
||||
|
||||
/** |
||||
* 新增任务 |
||||
* |
||||
* @param job 调度信息 调度信息 |
||||
*/ |
||||
@Override |
||||
public int addJobCron(Job job) |
||||
{ |
||||
job.setCreateBy(ShiroUtils.getLoginName()); |
||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); |
||||
int rows = jobMapper.insertJob(job); |
||||
if (rows > 0) |
||||
{ |
||||
ScheduleUtils.createScheduleJob(scheduler, job); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
/** |
||||
* 更新任务的时间表达式 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int updateJobCron(Job job) |
||||
{ |
||||
int rows = jobMapper.updateJob(job); |
||||
if (rows > 0) |
||||
{ |
||||
ScheduleUtils.updateScheduleJob(scheduler, job); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
/** |
||||
* 保存任务的时间表达式 |
||||
* |
||||
* @param job 调度信息 |
||||
*/ |
||||
@Override |
||||
public int saveJobCron(Job job) |
||||
{ |
||||
Long jobId = job.getJobId(); |
||||
int rows = 0; |
||||
if (StringUtils.isNotNull(jobId)) |
||||
{ |
||||
rows = updateJobCron(job); |
||||
} |
||||
else |
||||
{ |
||||
rows = addJobCron(job); |
||||
} |
||||
return rows; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,24 @@
|
||||
package com.ruoyi.project.monitor.job.task; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* 定时任务调度测试 |
||||
* |
||||
* @author ruoyi |
||||
*/ |
||||
@Component("ryTask") |
||||
public class RyTask |
||||
{ |
||||
|
||||
public void ryParams(String params) |
||||
{ |
||||
System.out.println("执行有参方法:" + params); |
||||
} |
||||
|
||||
public void ryNoParams() |
||||
{ |
||||
System.out.println("执行无参方法"); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,88 @@
|
||||
package com.ruoyi.project.monitor.job.util; |
||||
|
||||
import java.util.Date; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.Future; |
||||
import org.apache.commons.beanutils.PropertyUtils; |
||||
import org.quartz.JobDataMap; |
||||
import org.quartz.JobExecutionContext; |
||||
import org.quartz.JobExecutionException; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.scheduling.quartz.QuartzJobBean; |
||||
import com.ruoyi.common.constant.Constants; |
||||
import com.ruoyi.common.constant.ScheduleConstants; |
||||
import com.ruoyi.common.utils.spring.SpringUtils; |
||||
import com.ruoyi.project.monitor.job.domain.Job; |
||||
import com.ruoyi.project.monitor.job.domain.JobLog; |
||||
import com.ruoyi.project.monitor.job.service.IJobLogService; |
||||
|
||||
/** |
||||
* 定时任务 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
public class ScheduleJob extends QuartzJobBean |
||||
{ |
||||
private static final Logger log = LoggerFactory.getLogger(ScheduleJob.class); |
||||
|
||||
private ExecutorService service = Executors.newSingleThreadExecutor(); |
||||
|
||||
@Override |
||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException |
||||
{ |
||||
// Job job = (Job) context.getMergedJobDataMap().get(ScheduleConstants.JOB_PARAM_KEY);
|
||||
JobDataMap jobDataMap = context.getMergedJobDataMap(); |
||||
Job job = new Job(); |
||||
try |
||||
{ |
||||
PropertyUtils.copyProperties(job, jobDataMap.get(ScheduleConstants.JOB_PARAM_KEY)); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.error("copyProperties执行异常 - :", e); |
||||
} |
||||
|
||||
IJobLogService jobLogService = (IJobLogService) SpringUtils.getBean(IJobLogService.class); |
||||
|
||||
JobLog jobLog = new JobLog(); |
||||
jobLog.setJobName(job.getJobName()); |
||||
jobLog.setJobGroup(job.getJobGroup()); |
||||
jobLog.setMethodName(job.getMethodName()); |
||||
jobLog.setParams(job.getParams()); |
||||
jobLog.setCreateTime(new Date()); |
||||
|
||||
long startTime = System.currentTimeMillis(); |
||||
|
||||
try |
||||
{ |
||||
// 执行任务
|
||||
log.info("任务开始执行 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName()); |
||||
ScheduleRunnable task = new ScheduleRunnable(job.getJobName(), job.getMethodName(), job.getParams()); |
||||
Future<?> future = service.submit(task); |
||||
future.get(); |
||||
long times = System.currentTimeMillis() - startTime; |
||||
// 任务状态 0:成功 1:失败
|
||||
jobLog.setStatus(Constants.SUCCESS); |
||||
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒"); |
||||
|
||||
log.info("任务执行结束 - 名称:{} 耗时:{} 毫秒", job.getJobName(), times); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
log.info("任务执行失败 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName()); |
||||
log.error("任务执行异常 - :", e); |
||||
long times = System.currentTimeMillis() - startTime; |
||||
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒"); |
||||
// 任务状态 0:成功 1:失败
|
||||
jobLog.setStatus(Constants.FAIL); |
||||
jobLog.setExceptionInfo(e.toString()); |
||||
} |
||||
finally |
||||
{ |
||||
jobLogService.addJobLog(jobLog); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,59 @@
|
||||
package com.ruoyi.project.monitor.job.util; |
||||
|
||||
import java.lang.reflect.Method; |
||||
|
||||
import org.springframework.util.ReflectionUtils; |
||||
|
||||
import com.ruoyi.common.utils.StringUtils; |
||||
import com.ruoyi.common.utils.spring.SpringUtils; |
||||
|
||||
/** |
||||
* 执行定时任务 |
||||
* |
||||
* @author ruoyi |
||||
* |
||||
*/ |
||||
public class ScheduleRunnable implements Runnable |
||||
{ |
||||
private Object target; |
||||
private Method method; |
||||
private String params; |
||||
|
||||
public ScheduleRunnable(String beanName, String methodName, String params) |
||||
throws NoSuchMethodException, SecurityException |
||||
{ |
||||
this.target = SpringUtils.getBean(beanName); |
||||
this.params = params; |
||||
|
||||
if (StringUtils.isNotEmpty(params)) |
||||
{ |
||||
this.method = target.getClass().getDeclaredMethod(methodName, String.class); |
||||
} |
||||
else |
||||
{ |
||||
this.method = target.getClass().getDeclaredMethod(methodName); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
try |
||||
{ |
||||
ReflectionUtils.makeAccessible(method); |
||||
if (StringUtils.isNotEmpty(params)) |
||||
{ |
||||
method.invoke(target, params); |
||||
} |
||||
else |
||||
{ |
||||
method.invoke(target); |
||||
} |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue