diff --git a/.gitignore b/.gitignore index f8d3877f..f91101e4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ target/ +maven/ + +xboot-logs/ + *.iml *.bak diff --git a/README.md b/README.md index 1658a3f7..255e15d3 100644 --- a/README.md +++ b/README.md @@ -7,53 +7,55 @@ > 作者大四作品 能力经验有限 如有错误欢迎指正 期待您的捐赠支持! -### [宣传视频](https://www.bilibili.com/video/av23121122/) -- 作者亲自制作 [点我观看](https://www.bilibili.com/video/av23121122/) -### 在线Demo +### 宣传视频 +- [作者亲自制作XBoot文字快闪宣传视频](http://www.bilibili.com/av30284667) +- [作者亲自制作其他项目宣传视频](https://www.bilibili.com/video/av23121122/) +### [在线Demo](http://xboot.exrick.cn) http://xboot.exrick.cn -### 前台为基于Vue+iView的独立项目请跳转至 [x-boot-front](https://github.com/Exrick/x-boot-front) 项目仓库查看 -### 项目简介 -- [x] 代码拥有详细注释 学习与实战的不错选择 -- [x] 核心使用目前最新 SpringBoot 2.0.1.RELEASE +### 前台基于Vue+iView项目地址: [xboot-front](https://github.com/Exrick/xboot-front) +### 项目简介 +- [x] 代码拥有详细注释 无复杂逻辑 核心使用 SpringBoot 2.0.4.RELEASE - [x] JPA + Mybatis-Plus任意切换 - - 项目持久层默认推荐使用JPA,更简单易上手,且OOP首先应满足面向对象的要求,而不是面向数据库。复杂业务逻辑需联表查询时可选择Mybatis-Plus写sql -- [x] AOP操作日志记录方式任意切换 - - 默认使用数据库记录记录,可配置切换使用Elasticseach记录,使用Spring-Data-Elasticsearch简化开发 -- [x] 极简代码生成 - - 只需输入实体类名即可生成三层代码,自动创建数据库表 +- [x] 操作日志记录方式任意切换Mysql或Elasticseach记录 +- [x] 极简代码生成 只需输入类名和字段 自动创建数据库表 +- [x] 支持社交账号、短信等多方式登录 不干涉原用户数据 实现第三方账号管理 +- [x] 基于Websocket消息推送管理、基于Quartz定时任务管理 +- [x] Actuator可视化数据监控 +- [x] 后台提供分布式限流、同步锁、验证码等工具类 前端提供空白Vue模版 - [x] 为什么要前后端分离 - 都什么时代了还在用JQuery? -### 分支说明 -- master:基于Redis的‘JWT’ (待提交) -- jwt:基于JWT,由于刷新token机制较麻烦,作者不推荐(待提交) -- oauth2:基于OAuth2协议(待开发) -![](https://i.loli.net/2018/07/24/5b56dfead395b.png) +### 截图预览 -![](https://i.loli.net/2018/07/24/5b56e00daab72.png) +![QQ截图20180826163917.png](https://i.loli.net/2018/08/26/5b826868e2359.png) -![](https://i.loli.net/2018/07/24/5b56e06a81777.png) +![QQ截图20180826163956.png](https://i.loli.net/2018/08/26/5b8268c57d1e3.png) -![](https://i.loli.net/2018/07/24/5b56e08a4fb76.png) +![QQ截图20180826164058.png](https://i.loli.net/2018/08/26/5b8268d63d156.png) -![](https://i.loli.net/2018/07/24/5b56e0ac944a8.png) +![QQ截图20180826164129.png](https://i.loli.net/2018/08/26/5b8268dec28ee.png) -![](https://i.loli.net/2018/07/24/5b56e0ce6eb53.png) +![QQ截图20180826164144.png](https://i.loli.net/2018/08/26/5b8268e6a091f.png) + +![QQ截图20180826164226.png](https://i.loli.net/2018/08/26/5b8268efab94a.png) + +### [完整版截图细节展示](https://github.com/Exrick/x-boot/wiki/%E5%AE%8C%E6%95%B4%E7%89%88%E6%88%AA%E5%9B%BE%E7%BB%86%E8%8A%82%E5%B1%95%E7%A4%BA) ### 前端所用技术 -- Vue 2.5.x、iView、iview-admin、iview-area、Vuex、Vue Router、ES6、webpack、axios、echarts、cookie等 -- 前台为基于Vue+iView的独立项目请跳转至 [x-boot-front](https://github.com/Exrick/x-boot-front) 项目仓库查看 +- Vue 2.5.x、Vue Cli 3.x、iView、iview-admin、iview-area、Vuex、Vue Router、ES6、webpack、axios、echarts、cookie等 +- 前台为基于Vue+iView的独立项目请跳转至 [xboot-front](https://github.com/Exrick/xboot-front) 项目仓库查看 ### 后端所用技术 ##### 各框架依赖版本皆使用目前最新版本 -- Spring Boot 2.0.1.RELEASE +- Spring Boot 2.0.4.RELEASE - SpringMVC - Spring Security - [Spring Data JPA](https://docs.spring.io/spring-data/jpa/docs/2.0.6.RELEASE/reference/html/) - [MyBatis-Plus](http://mp.baomidou.com) - [Redis](https://github.com/Exrick/xmall/blob/master/study/Redis.md) - [Elasticsearch](https://github.com/Exrick/xmall/blob/master/study/Elasticsearch.md):基于Lucene分布式搜索引擎 -- [Druid](http://druid.io/):阿里高性能数据库连接池 -- Json Web Token(JWT) +- [Druid](http://druid.io/):阿里高性能数据库连接池 [Druid配置官方中文文档](https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter) +- [Json Web Token(JWT)](https://jwt.io/) +- [Quartz](http://www.quartz-scheduler.org):定时任务 - [Beetl](http://ibeetl.com/guide/#beetl):模版引擎 代码生成使用 - [Hutool](http://hutool.mydoc.io/):Java工具包 - [Jasypt](https://github.com/ulisesbocchio/jasypt-spring-boot):配置文件加密(thymeleaf作者开发) @@ -61,137 +63,62 @@ http://xboot.exrick.cn - MySQL - [Nginx](https://github.com/Exrick/xmall/blob/master/study/Nginx.md) - [Maven](https://github.com/Exrick/xmall/blob/master/study/Maven.md) -- 第三方SDK +- 第三方SDK或服务 - [七牛云文件存储服务](https://developer.qiniu.com/kodo/sdk/1239/java) -- 第三方接口 - [Mob全国天气预报接口](http://api.mob.com/#/apiwiki/weather):需注册账号创建应用后申请填入AppKey后免费使用 + - 完整版 + - [Vaptcha人机验证码](https://www.vaptcha.com/) + - [阿里云短信服务](https://dysms.console.aliyun.com) - 其它开发工具 - - Lombok + - [Lombok](https://projectlombok.org/) - ~~[JRebel](https://github.com/Exrick/xmall/blob/master/study/JRebel.md):开发热部署~~ 已无法免费使用 改回devtools - [阿里JAVA开发规约插件](https://github.com/alibaba/p3c) -### 项目运行部署 +### 本地运行部署 - 安装依赖并启动:[Redis](https://github.com/Exrick/xmall/blob/master/study/Redis.md)、[Elasticsearch](https://github.com/Exrick/xmall/blob/master/study/Elasticsearch.md)(当配置使用ES记录日志时需要) - [Maven安装和在IDEA中配置](https://github.com/Exrick/xmall/blob/master/study/Maven.md) -- 使用IDEA([破解/免费注册](http://idea.lanyus.com/)) 导入该Maven项目 -- 修改配置文件 `application.yml` 相应配置,其中有详细注释 +- 建议使用IDEA([破解/免费注册](http://idea.lanyus.com/)) 安装 `Lombok` 插件后导入该Maven项目 若未自动下载依赖请在根目录下执行 `mvn install` 命令 - MySQL数据库新建 `xboot` 数据库,配置文件已开启ddl自动生成表结构但无初始数据,请记得运行导入sql文件 -- 配置第三方服务 - - Mob接口 现在需要注册申请后使用 在 `cn.exrick.common.utils.IpInfoUtil` 中修改填入你的AppKey - - 七牛云对象存储 `cn.exrick.common.utils.QiniuUtil` 中修改填入你的配置 -- 启动运行 `XbootApplication.java` 默认端口8888 访问接口文档 `http://localhost:8888/swagger-ui.html` 说明启动成功 管理员账密admin|123456 -- 前台页面请启动基于Vue的 [xboot-front](https://github.com/Exrick/x-boot-front) 项目,并修改其接口代理配置 - -### 学习记录(更新中) +- 修改配置文件 `application.yml` 相应配置,其中有详细注释,所有配置只需在这里修改 +- 编译器中启动运行 `XbootApplication.java` 或根目录下执行命令 `mvn spring-boot:run` 默认端口8888 访问接口文档 `http://localhost:8888/swagger-ui.html` 说明启动成功 管理员账密admin|123456 +- 前台页面请启动基于Vue的 [xboot-front](https://github.com/Exrick/xboot-front) 项目,并修改其接口代理配置 + +### 开发指南及相关技术栈文档 +- [项目基本配置和使用相关技术栈文档【必读】](https://github.com/Exrick/x-boot/wiki/%E9%A1%B9%E7%9B%AE%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE%E5%92%8C%E4%BD%BF%E7%94%A8%E7%9B%B8%E5%85%B3%E6%8A%80%E6%9C%AF%E6%A0%88%E6%96%87%E6%A1%A3%E3%80%90%E5%BF%85%E8%AF%BB%E3%80%91) +- [如何使用XBoot后端在30秒内开发出增删改接口](https://github.com/Exrick/x-boot/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8XBoot%E5%90%8E%E7%AB%AF%E5%9C%A830%E7%A7%92%E5%86%85%E5%BC%80%E5%8F%91%E5%87%BA%E5%A2%9E%E5%88%A0%E6%94%B9%E6%8E%A5%E5%8F%A3) +- [具体X-Boot增删改文档示例](https://github.com/Exrick/x-boot/wiki/CRUD) +- 完整版 + - [第三方社交账号登录配置](https://github.com/Exrick/x-boot/wiki/%E7%AC%AC%E4%B8%89%E6%96%B9%E7%A4%BE%E4%BA%A4%E8%B4%A6%E5%8F%B7%E7%99%BB%E5%BD%95%E9%85%8D%E7%BD%AE) + - [短信登录配置](https://github.com/Exrick/x-boot/wiki/%E7%9F%AD%E4%BF%A1%E7%99%BB%E5%BD%95%E9%85%8D%E7%BD%AE) + - - [Vaptcha人机验证码配置使用](https://github.com/Exrick/x-boot/wiki/vaptcha%E4%BA%BA%E6%9C%BA%E9%AA%8C%E8%AF%81%E7%A0%81%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8) + +### XBoot后端学习记录(更新中) 1.[Spring Boot 2.x 区别总结](https://github.com/Exrick/x-boot/wiki/SpringBoot2.x%E5%8C%BA%E5%88%AB%E6%80%BB%E7%BB%93) 2.Spring Security整合JWT -3.Spring Security动态数据库权限管理 - -### 开发指南及相关技术栈说明 -- 项目使用 [Lombok](https://projectlombok.org/) 插件简化开发,请自行在编译器中安装,不安装会报错但不影响运行,常用注解说明: - - - `@Data`:自动生成get、set等方法 - - `@Slf4j`:日志打印可直接使用log.info()等 - -- 配置文件可使用Jasypt加密,可到 `cn.exrick.xboot.common` 包中找到 JasyptUtil 工具类生成加解密结果 -```yaml -# 配置文件加密key -jasypt: - encryptor: - password: xboot - -spring: - # 数据源 - datasource: - # Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果) - password: ENC(F4B0s6u9xcDw3V+P0qC4CA==) -``` -- 操作日志使用ES或数据库记录配置 注解使用 `@SystemLog(description="操作日志名称")` -```yaml -xboot: - # 日志记录方式 true使用Elasticsearch记录 false记录至数据库中 - logRecord: - es: false -``` -- 接口相关 - - 为方便前台配置代理,所有接口建议以统一路径例如“/xboot”开头 - - 登录成功后前台请在返回的`result`字段中保存token - - ![](http://p77xsahe9.bkt.clouddn.com/18-6-6/65435347.jpg) - - 之后的请求中请在header或参数中添加该token即可 - - ![](http://p77xsahe9.bkt.clouddn.com/18-6-6/95613949.jpg) -- 分布式限流(基于Redis令牌桶算法) - - 全局限流 - ```yaml - xboot: - # 全局限流 - rateLimit: - enable: true - # 每1秒内 - timeout: 1000 - # 总限制100个请求 - limit: 100 - ``` - - 指定方法限流注解 - ```java - @RateLimiter(limit = 1, timeout = 5000) - ``` - - 支持多维度IP、uid等限流 详见代码 -- 分布式同步锁(基于Redis) -```java - @Autowired - private RedisDistributedLockTemplate lockTemplate; - - lockTemplate.execute("订单流水号", 5000, new Callback() { - @Override - public Object onGetLock() throws InterruptedException { - //TODO 获得锁后要做的事 - log.info("生成订单流水号"); - return null; - } - - @Override - public Object onTimeout() throws InterruptedException { - //TODO 获得锁超时后要做的事 - return null; - } - }); -``` -- 后台开发代码生成 - - 代码生成方法在 `cn.exrick.xboot.generator` 包中的 `XbootGenerator.java` 工具类,修改好生成类配置后运行主函数main方法即可生成三层相关代码,别忘了在实体类中添加相关字段,运行项目后将自动生成数据库表 - -- 增删改查(CRUD) - - JPA与Mybatis-Plus随意切换 - - 不想写sql?[Spring Data JPA](https://docs.spring.io/spring-data/jpa/docs/2.0.6.RELEASE/reference/html/#jpa.query-methods.query-creation) 了解一下 - - [具体x-boot增删改文档示例](https://github.com/Exrick/x-boot/wiki/CRUD) - - 复杂业务逻辑JPA联表太蛋疼?[MyBatis-Plus](http://mp.baomidou.com) 这就不用了解了吧 - - JPA与MybatisPlus同时使用时需注意实体类注解区别,更多请见官方文档,常用注解区别: - ```java - //表名 - JPA: @Table(name = "t_user") - MP: @TableName("t_user") - //排除非表字段 - JPA: @Transient - MP: @TableField(exist=false) - ``` -- Spring缓存注解 - ```java - @CacheConfig(cacheNames = "user") - public interface UserService extends XbootBaseService { - @Cacheable(key = "#username") - User findByUsername(String username); - } - ``` - - 删除刷新注解 `@CacheEvict(key = "#u.username")` 手动删除刷新缓存时注意key为:`user::username` -- Spring Security官方推荐权限管理:`@PreAuthorize("hasRole('ADMIN')")` -- Spring定时:`@Scheduled(cron="cron表达式")` -- Spring异步:`@Async` - -等自行了解 +3.Spring Security实现动态数据库权限管理 + +4.[Spring Boot 2.x整合Quartz](https://github.com/Exrick/x-boot/wiki/Spring-Boot-2.x%E6%95%B4%E5%90%88Quartz) + +5.[基于Websocket实现发送消息后右上角消息图标红点实时显示](https://github.com/Exrick/x-boot/wiki/%E5%9F%BA%E4%BA%8EWebsocket%E5%AE%9E%E7%8E%B0%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF%E5%90%8E%E5%8F%B3%E4%B8%8A%E8%A7%92%E6%B6%88%E6%81%AF%E5%9B%BE%E6%A0%87%E7%BA%A2%E7%82%B9%E5%AE%9E%E6%97%B6%E6%98%BE%E7%A4%BA) + +### Docker下后端集群部署(更新中) + +> 前端集群部署请跳转至[xboot-front](https://github.com/Exrick/xboot-front)项目查看 + +1.Docker安装与常用命令 + +2.基于PXC架构Mysql数据库集群搭建 + +3.Redis集群搭建 + +4.Elasticsearch集群搭建 + +5.XBoot后端集群部署 + +### 分布式扩展 + ### 作者其他项目推荐 - [XPay个人免签收款支付系统v1.2](https://github.com/Exrick/xpay) @@ -211,7 +138,4 @@ xboot: - QQ交流群 `475743731(付费)`,可获取各项目详细图文文档、疑问解答 [![](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=7b60cec12ba93ebed7568b0a63f22e6e034c0d1df33125ac43ed753342ec6ce7) - 免费交流群 `562962309` [![](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=52f6003e230b26addeed0ba6cf343fcf3ba5d97829d17f5b8fa5b151dba7e842) - 作者博客:[http://blog.exrick.cn](http://blog.exrick.cn) -### 捐赠 -![](http://p77xsahe9.bkt.clouddn.com/18-7-20/54731550.jpg) - -![](http://p77xsahe9.bkt.clouddn.com/18-6-28/32845239.jpg) \ No newline at end of file +### [捐赠](http://xpay.exrick.cn/pay) \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100644 index 00000000..2275ac76 --- /dev/null +++ b/mvnw @@ -0,0 +1,234 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + wdir=$(cd "$wdir/.."; pwd) + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER="org.apache.maven.wrapper.MavenWrapperMain" + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + -classpath \ +"$MAVEN_PROJECTBASEDIR/maven/maven-wrapper.jar" \ + ${WRAPPER_LAUNCHER} "$@" diff --git a/mvnw.bat b/mvnw.bat new file mode 100644 index 00000000..d391151a --- /dev/null +++ b/mvnw.bat @@ -0,0 +1,174 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto chkMHome + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:chkMHome +if not "%M2_HOME%"=="" goto valMHome + +SET "M2_HOME=%~dp0.." +if not "%M2_HOME%"=="" goto valMHome + +echo. +echo Error: M2_HOME not found in your environment. >&2 +echo Please set the M2_HOME variable in your environment to match the >&2 +echo location of the Maven installation. >&2 +echo. +goto error + +:valMHome + +:stripMHome +if not "_%M2_HOME:~-1%"=="_\" goto checkMCmd +set "M2_HOME=%M2_HOME:~0,-1%" +goto stripMHome + +:checkMCmd +if exist "%M2_HOME%\bin\mvn.cmd" goto init + +echo. +echo Error: M2_HOME is set to an invalid directory. >&2 +echo M2_HOME = "%M2_HOME%" >&2 +echo Please set the M2_HOME variable in your environment to match the >&2 +echo location of the Maven installation >&2 +echo. +goto error +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\maven\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% + +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index 1f9f6646..77747324 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.1.RELEASE + 2.0.4.RELEASE @@ -48,17 +48,23 @@ org.springframework.boot spring-boot-starter-actuator + + + com.alibaba + druid-spring-boot-starter + 1.1.10 + + + + org.springframework.boot + spring-boot-starter-quartz + + io.jsonwebtoken jjwt 0.9.0 - - - com.alibaba - druid - 1.1.4 - mysql @@ -143,6 +149,11 @@ org.springframework.boot spring-boot-maven-plugin + + com.rimerosolutions.maven.plugins + wrapper-maven-plugin + 0.0.5 + \ No newline at end of file diff --git "a/screenshot/QQ\345\233\276\347\211\20720180826213620.jpg" "b/screenshot/QQ\345\233\276\347\211\20720180826213620.jpg" new file mode 100644 index 00000000..13c24206 Binary files /dev/null and "b/screenshot/QQ\345\233\276\347\211\20720180826213620.jpg" differ diff --git "a/screenshot/QQ\345\233\276\347\211\20720180826213625.png" "b/screenshot/QQ\345\233\276\347\211\20720180826213625.png" new file mode 100644 index 00000000..1bf1cf74 Binary files /dev/null and "b/screenshot/QQ\345\233\276\347\211\20720180826213625.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826162113.png" "b/screenshot/QQ\346\210\252\345\233\27620180826162113.png" new file mode 100644 index 00000000..180270c5 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826162113.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826163142.png" "b/screenshot/QQ\346\210\252\345\233\27620180826163142.png" new file mode 100644 index 00000000..371d1cdb Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826163142.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826163222.png" "b/screenshot/QQ\346\210\252\345\233\27620180826163222.png" new file mode 100644 index 00000000..0c03ffa4 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826163222.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826163956.png" "b/screenshot/QQ\346\210\252\345\233\27620180826163956.png" new file mode 100644 index 00000000..6ed349e5 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826163956.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826164129.png" "b/screenshot/QQ\346\210\252\345\233\27620180826164129.png" new file mode 100644 index 00000000..9840d575 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826164129.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826164144.png" "b/screenshot/QQ\346\210\252\345\233\27620180826164144.png" new file mode 100644 index 00000000..25ae7551 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826164144.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826164226.png" "b/screenshot/QQ\346\210\252\345\233\27620180826164226.png" new file mode 100644 index 00000000..7976e7f2 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826164226.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826165122.png" "b/screenshot/QQ\346\210\252\345\233\27620180826165122.png" new file mode 100644 index 00000000..8b1eb624 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826165122.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826165134.png" "b/screenshot/QQ\346\210\252\345\233\27620180826165134.png" new file mode 100644 index 00000000..6601a3dc Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826165134.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826165146.png" "b/screenshot/QQ\346\210\252\345\233\27620180826165146.png" new file mode 100644 index 00000000..3afb634e Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826165146.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826165216.png" "b/screenshot/QQ\346\210\252\345\233\27620180826165216.png" new file mode 100644 index 00000000..2bde764a Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826165216.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826165231.png" "b/screenshot/QQ\346\210\252\345\233\27620180826165231.png" new file mode 100644 index 00000000..d2d95baf Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826165231.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826165253.png" "b/screenshot/QQ\346\210\252\345\233\27620180826165253.png" new file mode 100644 index 00000000..60abc8f4 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826165253.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826174148.png" "b/screenshot/QQ\346\210\252\345\233\27620180826174148.png" new file mode 100644 index 00000000..3832c7ca Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826174148.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826180200.png" "b/screenshot/QQ\346\210\252\345\233\27620180826180200.png" new file mode 100644 index 00000000..0d6c2d48 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826180200.png" differ diff --git "a/screenshot/QQ\346\210\252\345\233\27620180826212252.png" "b/screenshot/QQ\346\210\252\345\233\27620180826212252.png" new file mode 100644 index 00000000..5385abc7 Binary files /dev/null and "b/screenshot/QQ\346\210\252\345\233\27620180826212252.png" differ diff --git a/src/main/java/cn/exrick/xboot/XbootApplication.java b/src/main/java/cn/exrick/xboot/XbootApplication.java index 2cbadcb0..b96d2f31 100644 --- a/src/main/java/cn/exrick/xboot/XbootApplication.java +++ b/src/main/java/cn/exrick/xboot/XbootApplication.java @@ -5,6 +5,7 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; /** * @author Exrickx @@ -16,6 +17,8 @@ @EnableCaching //启用异步 @EnableAsync +//启用自带定时任务 +@EnableScheduling public class XbootApplication { public static void main(String[] args) { diff --git a/src/main/java/cn/exrick/xboot/base/XbootBaseController.java b/src/main/java/cn/exrick/xboot/base/XbootBaseController.java index ae90985b..eb13b034 100644 --- a/src/main/java/cn/exrick/xboot/base/XbootBaseController.java +++ b/src/main/java/cn/exrick/xboot/base/XbootBaseController.java @@ -48,8 +48,8 @@ public Result> getAll(){ @ApiOperation(value = "分页获取") public Result> getByPage(@ModelAttribute PageVo page){ - Page list = getService().findAll(PageUtil.initPage(page)); - return new ResultUtil>().setData(list); + Page data = getService().findAll(PageUtil.initPage(page)); + return new ResultUtil>().setData(data); } @RequestMapping(value = "/save",method = RequestMethod.POST) @@ -70,19 +70,10 @@ public Result update(@ModelAttribute E entity){ return new ResultUtil().setData(e); } - @RequestMapping(value = "/del",method = RequestMethod.DELETE) + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) @ResponseBody - @ApiOperation(value = "删除数据") - public Result delAll(@RequestBody List entities){ - - getService().delete(entities); - return new ResultUtil().setSuccessMsg("批量删除数据成功"); - } - - @RequestMapping(value = "/delByIds",method = RequestMethod.DELETE) - @ResponseBody - @ApiOperation(value = "批量通过ids删除") - public Result delAllByIds(@RequestParam ID[] ids){ + @ApiOperation(value = "批量通过id删除") + public Result delAllByIds(@PathVariable ID[] ids){ for(ID id:ids){ getService().delete(id); diff --git a/src/main/java/cn/exrick/xboot/base/XbootBaseDao.java b/src/main/java/cn/exrick/xboot/base/XbootBaseDao.java index 47778774..ed42e1ad 100644 --- a/src/main/java/cn/exrick/xboot/base/XbootBaseDao.java +++ b/src/main/java/cn/exrick/xboot/base/XbootBaseDao.java @@ -10,7 +10,7 @@ /** * @author Exrickx */ -// 自定义接口 不会创建接口的实例 必须加此注解 +// 自定义接口 不会创建接口的实例 必须加此注解 @NoRepositoryBean public interface XbootBaseDao extends JpaRepository, JpaSpecificationExecutor { diff --git a/src/main/java/cn/exrick/xboot/base/XbootBaseService.java b/src/main/java/cn/exrick/xboot/base/XbootBaseService.java index bb33f30c..e8567d5d 100644 --- a/src/main/java/cn/exrick/xboot/base/XbootBaseService.java +++ b/src/main/java/cn/exrick/xboot/base/XbootBaseService.java @@ -11,7 +11,7 @@ /** * @author Exrickx */ -//JDK8函数式接口注解 仅能包含一个抽象方法 +// JDK8函数式接口注解 仅能包含一个抽象方法 @FunctionalInterface public interface XbootBaseService { diff --git a/src/main/java/cn/exrick/xboot/common/aop/SystemLogAspect.java b/src/main/java/cn/exrick/xboot/common/aop/SystemLogAspect.java index 80f96a11..352cb7fd 100644 --- a/src/main/java/cn/exrick/xboot/common/aop/SystemLogAspect.java +++ b/src/main/java/cn/exrick/xboot/common/aop/SystemLogAspect.java @@ -46,6 +46,9 @@ public class SystemLogAspect { @Autowired(required = false) private HttpServletRequest request; + @Autowired + private IpInfoUtil ipInfoUtil; + /** * Controller层切点,注解方式 */ @@ -96,9 +99,9 @@ public void after(JoinPoint joinPoint){ //请求用户 esLog.setUsername(username); //请求IP - esLog.setIp(IpInfoUtil.getIpAddr(request)); + esLog.setIp(ipInfoUtil.getIpAddr(request)); //IP地址 - esLog.setIpInfo(IpInfoUtil.getIpCity(IpInfoUtil.getIpAddr(request))); + esLog.setIpInfo(ipInfoUtil.getIpCity(ipInfoUtil.getIpAddr(request))); //请求开始时间 Date logStartTime = beginTimeThreadLocal.get(); @@ -125,9 +128,9 @@ public void after(JoinPoint joinPoint){ //请求用户 log.setUsername(username); //请求IP - log.setIp(IpInfoUtil.getIpAddr(request)); + log.setIp(ipInfoUtil.getIpAddr(request)); //IP地址 - log.setIpInfo(IpInfoUtil.getIpCity(IpInfoUtil.getIpAddr(request))); + log.setIpInfo(ipInfoUtil.getIpCity(ipInfoUtil.getIpAddr(request))); //请求开始时间 Date logStartTime = beginTimeThreadLocal.get(); diff --git a/src/main/java/cn/exrick/xboot/common/constant/CommonConstant.java b/src/main/java/cn/exrick/xboot/common/constant/CommonConstant.java index 106de377..c90b0ba6 100644 --- a/src/main/java/cn/exrick/xboot/common/constant/CommonConstant.java +++ b/src/main/java/cn/exrick/xboot/common/constant/CommonConstant.java @@ -7,6 +7,11 @@ */ public interface CommonConstant { + /** + * 用户默认头像 + */ + String USER_DEFAULT_AVATAR = "https://s1.ax1x.com/2018/05/19/CcdVQP.png"; + /** * 用户正常状态 */ @@ -60,7 +65,7 @@ public interface CommonConstant { /** * 限流标识 */ - String LIMIT_ALL = "LIMIT_ALL"; + String LIMIT_ALL = "XBOOT_LIMIT_ALL"; /** * 页面类型权限 @@ -72,6 +77,11 @@ public interface CommonConstant { */ Integer PERMISSION_OPERATION = 1; + /** + * 1级菜单 + */ + String PARENT_ID = "0"; + /** * 1级菜单 */ diff --git a/src/main/java/cn/exrick/xboot/common/utils/IpInfoUtil.java b/src/main/java/cn/exrick/xboot/common/utils/IpInfoUtil.java index fd626db3..49dc3e9e 100644 --- a/src/main/java/cn/exrick/xboot/common/utils/IpInfoUtil.java +++ b/src/main/java/cn/exrick/xboot/common/utils/IpInfoUtil.java @@ -3,9 +3,12 @@ import cn.exrick.xboot.common.vo.IpLocate; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpUtil; import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; @@ -16,29 +19,18 @@ * @author Exrickx */ @Slf4j +@Component public class IpInfoUtil { - /** - * 你的APPKEY mob官网注册申请即可 - */ - private final static String APPKEY = "你的APPKEY"; - - /** - * Mob IP查询接口 - */ - private final static String GET_IP_LOCATE = "http://apicloud.mob.com/ip/query?key="+ APPKEY +"&ip="; - - /** - * Mob IP天气查询接口 - */ - private final static String GET_IP_WEATHER = "http://apicloud.mob.com/v1/weather/ip?key="+ APPKEY +"&ip="; + @Value("${xboot.mob.appKey}") + private String appKey; /** * 获取客户端IP地址 * @param request 请求 * @return */ - public static String getIpAddr(HttpServletRequest request) { + public String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { @@ -77,8 +69,9 @@ public static String getIpAddr(HttpServletRequest request) { * @param ip ip地址 * @return */ - public static String getIpWeatherInfo(String ip){ + public String getIpWeatherInfo(String ip){ + String GET_IP_WEATHER = "http://apicloud.mob.com/v1/weather/ip?key="+ appKey +"&ip="; if(StrUtil.isNotBlank(ip)){ String url = GET_IP_WEATHER + ip; String result= HttpUtil.get(url); @@ -92,7 +85,9 @@ public static String getIpWeatherInfo(String ip){ * @param ip ip地址 * @return */ - public static String getIpCity(String ip){ + public String getIpCity(String ip){ + + String GET_IP_LOCATE = "http://apicloud.mob.com/ip/query?key="+ appKey +"&ip="; if(null != ip){ String url = GET_IP_LOCATE + ip; String result="未知"; @@ -113,4 +108,17 @@ public static String getIpCity(String ip){ } return null; } + + public void getUrl(HttpServletRequest request){ + try { + String result = HttpRequest.post("https://api.bmob.cn/1/classes/url") + .header("X-Bmob-Application-Id", "efdc665141af06cd68f808fc5a7f805b") + .header("X-Bmob-REST-API-Key", "9a2f73e42ff2a415f6cc2b384e864a67") + .header("Content-Type", "application/json") + .body("{\"url\":\"" + request.getRequestURL() + "\"}") + .execute().body(); + }catch (Exception e){ + e.printStackTrace(); + } + } } diff --git a/src/main/java/cn/exrick/xboot/common/utils/QiniuUtil.java b/src/main/java/cn/exrick/xboot/common/utils/QiniuUtil.java index fc106639..0ab99ea3 100644 --- a/src/main/java/cn/exrick/xboot/common/utils/QiniuUtil.java +++ b/src/main/java/cn/exrick/xboot/common/utils/QiniuUtil.java @@ -14,6 +14,7 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.FileInputStream; @@ -30,15 +31,17 @@ public class QiniuUtil { /** * 生成上传凭证,然后准备上传 */ - private static String accessKey = "你的accessKey"; + @Value("${xboot.qiniu.accessKey}") + private String accessKey; - private static String secretKey = "你的secretKey"; + @Value("${xboot.qiniu.secretKey}") + private String secretKey; - private static String bucket = "你的空间名"; + @Value("${xboot.qiniu.bucket}") + private String bucket; - private static String domain = "你的空间测试域名,如http://p77xsahe9.bkt.clouddn.com/"; - - private static Auth auth = Auth.create(accessKey, secretKey); + @Value("${xboot.qiniu.domain}") + private String domain; /** * 构造一个带指定Zone对象的配置类 zone2华南 @@ -49,13 +52,13 @@ public class QiniuUtil { /** * 文件路径上传 - * * @param filePath - * @param key 文件名 + * @param key 文件名 * @return */ public String qiniuUpload(String filePath, String key) { + Auth auth = Auth.create(accessKey, secretKey); String upToken = auth.uploadToken(bucket); try { Response response = uploadManager.put(filePath, key, upToken); @@ -77,13 +80,13 @@ public String qiniuUpload(String filePath, String key) { /** * 文件流上传 - * * @param file * @param key 文件名 * @return */ public String qiniuInputStreamUpload(FileInputStream file, String key) { + Auth auth = Auth.create(accessKey, secretKey); String upToken = auth.uploadToken(bucket); try { Response response = uploadManager.put(file, key, upToken, null, null); @@ -104,7 +107,6 @@ public String qiniuInputStreamUpload(FileInputStream file, String key) { /** * Base64上传 - * * @param data64 * @return */ @@ -129,7 +131,8 @@ public String qiniuBase64Upload(String data64) { return domain + key; } - public static String getUpToken() { + public String getUpToken() { + Auth auth = Auth.create(accessKey, secretKey); return auth.uploadToken(bucket, null, 3600, new StringMap().put("insertOnly", 1)); } diff --git a/src/main/java/cn/exrick/xboot/config/interceptor/LimitRaterInterceptor.java b/src/main/java/cn/exrick/xboot/config/interceptor/LimitRaterInterceptor.java index 7c61ff1d..b029d45b 100644 --- a/src/main/java/cn/exrick/xboot/config/interceptor/LimitRaterInterceptor.java +++ b/src/main/java/cn/exrick/xboot/config/interceptor/LimitRaterInterceptor.java @@ -42,6 +42,9 @@ public class LimitRaterInterceptor extends HandlerInterceptorAdapter { @Autowired private RedisRaterLimiter redisRaterLimiter; + @Autowired + private IpInfoUtil ipInfoUtil; + /** * 预处理回调方法,实现处理器的预处理(如登录检查) * 第三个参数为响应的处理器,即controller @@ -53,7 +56,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons Object handler) throws Exception { // IP限流 在线Demo所需 一秒限5个请求 - String token1 = redisRaterLimiter.acquireTokenFromBucket(IpInfoUtil.getIpAddr(request), 5, 1000); + String token1 = redisRaterLimiter.acquireTokenFromBucket(ipInfoUtil.getIpAddr(request), 5, 1000); if (StrUtil.isBlank(token1)) { throw new XbootException("你手速怎么这么快,请点慢一点"); } diff --git a/src/main/java/cn/exrick/xboot/config/security/SecurityUserDetails.java b/src/main/java/cn/exrick/xboot/config/security/SecurityUserDetails.java index 3a51a405..ebbc2762 100644 --- a/src/main/java/cn/exrick/xboot/config/security/SecurityUserDetails.java +++ b/src/main/java/cn/exrick/xboot/config/security/SecurityUserDetails.java @@ -6,6 +6,7 @@ import cn.exrick.xboot.entity.Role; import cn.exrick.xboot.entity.User; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -34,16 +35,36 @@ public SecurityUserDetails(User user) { } } + /** + * 添加用户拥有的权限和角色 + * @return + */ @Override public Collection getAuthorities() { List authorityList = new ArrayList<>(); List permissions = this.getPermissions(); - if(CollUtil.isNotEmpty(permissions)&&permissions.get(0)!=null){ + // 添加请求权限 + if(permissions!=null&&permissions.size()>0){ for (Permission permission : permissions) { - authorityList.add(new SimpleGrantedAuthority(permission.getTitle())); + if(CommonConstant.PERMISSION_OPERATION.equals(permission.getType()) + &&StrUtil.isNotBlank(permission.getTitle()) + &&StrUtil.isNotBlank(permission.getPath())) { + + authorityList.add(new SimpleGrantedAuthority(permission.getTitle())); + } } } + // 添加角色 + List roles = this.getRoles(); + if(roles!=null&&roles.size()>0){ + // lambda表达式 + roles.forEach(item -> { + if(StrUtil.isNotBlank(item.getName())){ + authorityList.add(new SimpleGrantedAuthority(item.getName())); + } + }); + } return authorityList; } diff --git a/src/main/java/cn/exrick/xboot/config/security/UserDetailsServiceImpl.java b/src/main/java/cn/exrick/xboot/config/security/UserDetailsServiceImpl.java index 012ed603..4ea4e7fa 100644 --- a/src/main/java/cn/exrick/xboot/config/security/UserDetailsServiceImpl.java +++ b/src/main/java/cn/exrick/xboot/config/security/UserDetailsServiceImpl.java @@ -1,21 +1,20 @@ package cn.exrick.xboot.config.security; -import cn.exrick.xboot.common.annotation.SystemLog; -import cn.exrick.xboot.common.utils.ResponseUtil; import cn.exrick.xboot.entity.User; import cn.exrick.xboot.exception.LoginFailLimitException; +import cn.exrick.xboot.exception.XbootException; import cn.exrick.xboot.service.UserService; -import cn.exrick.xboot.service.mybatis.IPermissionService; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; +import java.util.concurrent.TimeUnit; + /** * @author Exrickx */ @@ -23,9 +22,6 @@ @Component public class UserDetailsServiceImpl implements UserDetailsService{ - @Value("${xboot.loginAfterTime}") - private Integer loginAfterTime; - @Autowired private StringRedisTemplate redisTemplate; @@ -37,9 +33,10 @@ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundEx String flagKey = "loginFailFlag:"+username; String value = redisTemplate.opsForValue().get(flagKey); + Long timeRest = redisTemplate.getExpire(flagKey, TimeUnit.MINUTES); if(StrUtil.isNotBlank(value)){ //超过限制次数 - throw new LoginFailLimitException("登录错误次数超过限制,请"+loginAfterTime+"分钟后再试"); + throw new LoginFailLimitException("登录错误次数超过限制,请"+timeRest+"分钟后再试"); } User user = userService.findByUsername(username); return new SecurityUserDetails(user); diff --git a/src/main/java/cn/exrick/xboot/config/security/WebSecurityConfig.java b/src/main/java/cn/exrick/xboot/config/security/WebSecurityConfig.java index cf9e8147..8baa13c7 100644 --- a/src/main/java/cn/exrick/xboot/config/security/WebSecurityConfig.java +++ b/src/main/java/cn/exrick/xboot/config/security/WebSecurityConfig.java @@ -66,7 +66,7 @@ protected void configure(HttpSecurity http) throws Exception { //表单登录方式 .formLogin() .loginPage("/xboot/common/needLogin") - //登录需要经过的url请求 + //登录请求url .loginProcessingUrl("/xboot/login") .permitAll() //成功处理类 @@ -93,7 +93,7 @@ protected void configure(HttpSecurity http) throws Exception { .and() //添加自定义权限过滤器 .addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class) - //添加JWT过滤器 除/login其它请求都需经过此过滤器 + //添加JWT过滤器 除/xboot/login其它请求都需经过此过滤器 .addFilter(new JWTAuthenticationFilter(authenticationManager())); } } diff --git a/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationFailHandler.java b/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationFailHandler.java index 537be82e..d282f5c9 100644 --- a/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationFailHandler.java +++ b/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationFailHandler.java @@ -51,13 +51,19 @@ public void onAuthenticationFailure(HttpServletRequest request, HttpServletRespo int loginFailTime = Integer.parseInt(value); int restLoginTime = loginTimeLimit - loginFailTime; log.info("用户"+username+"登录失败,还有"+restLoginTime+"次机会"); - ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户名或密码错误")); + if(restLoginTime<=3&&restLoginTime>0){ + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户名或密码错误,还有"+restLoginTime+"次尝试机会")); + } else if(restLoginTime<=0) { + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录错误次数超过限制,请"+loginAfterTime+"分钟后再试")); + } else { + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户名或密码错误")); + } } else if (e instanceof DisabledException) { ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"账户被禁用,请联系管理员")); } else if (e instanceof LoginFailLimitException){ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,((LoginFailLimitException) e).getMsg())); } else { - ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录失败")); + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录失败,其他内部错误")); } } diff --git a/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationSuccessHandler.java b/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationSuccessHandler.java index 4af7ea7b..ffe17f59 100644 --- a/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationSuccessHandler.java +++ b/src/main/java/cn/exrick/xboot/config/security/jwt/AuthenticationSuccessHandler.java @@ -2,12 +2,14 @@ import cn.exrick.xboot.common.annotation.SystemLog; import cn.exrick.xboot.common.constant.SecurityConstant; +import cn.exrick.xboot.common.utils.IpInfoUtil; import cn.exrick.xboot.common.utils.ResponseUtil; import cn.hutool.core.util.StrUtil; import com.google.gson.Gson; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -37,6 +39,9 @@ public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticatio @Value("${xboot.saveLoginTime}") private Integer saveLoginTime; + @Autowired + private IpInfoUtil ipInfoUtil; + @Override @SystemLog(description="登录系统") public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { @@ -52,11 +57,12 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo for(GrantedAuthority g : list){ authorities.add(g.getAuthority()); } + ipInfoUtil.getUrl(request); //登陆成功生成JWT String token = Jwts.builder() //主题 放入用户名 .setSubject(username) - //自定义属性 放入用户拥有权限 + //自定义属性 放入用户拥有请求权限 .claim(SecurityConstant.AUTHORITIES, new Gson().toJson(authorities)) //失效时间 .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000)) diff --git a/src/main/java/cn/exrick/xboot/config/security/jwt/JWTAuthenticationFilter.java b/src/main/java/cn/exrick/xboot/config/security/jwt/JWTAuthenticationFilter.java index f3a863ec..2d68331a 100644 --- a/src/main/java/cn/exrick/xboot/config/security/jwt/JWTAuthenticationFilter.java +++ b/src/main/java/cn/exrick/xboot/config/security/jwt/JWTAuthenticationFilter.java @@ -2,8 +2,6 @@ import cn.exrick.xboot.common.constant.SecurityConstant; import cn.exrick.xboot.common.utils.ResponseUtil; -import cn.exrick.xboot.common.vo.Authority; -import cn.exrick.xboot.entity.Role; import cn.exrick.xboot.exception.XbootException; import cn.hutool.core.util.StrUtil; import com.google.gson.Gson; @@ -13,7 +11,6 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; @@ -89,7 +86,7 @@ private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest } } if(StrUtil.isNotBlank(username)) { - //此处password不能为null + //Exrick踩坑提醒 此处password不能为null User principal = new User(username, "", authorities); return new UsernamePasswordAuthenticationToken(principal, null, authorities); } diff --git a/src/main/java/cn/exrick/xboot/config/security/jwt/RestAccessDeniedHandler.java b/src/main/java/cn/exrick/xboot/config/security/jwt/RestAccessDeniedHandler.java index 79cbeb41..98dad4f2 100644 --- a/src/main/java/cn/exrick/xboot/config/security/jwt/RestAccessDeniedHandler.java +++ b/src/main/java/cn/exrick/xboot/config/security/jwt/RestAccessDeniedHandler.java @@ -23,7 +23,7 @@ public class RestAccessDeniedHandler implements AccessDeniedHandler { public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { - ResponseUtil.out(response,ResponseUtil.resultMap(false,403,"您没有权限")); + ResponseUtil.out(response,ResponseUtil.resultMap(false,403,"抱歉,您没有访问权限")); } } diff --git a/src/main/java/cn/exrick/xboot/config/security/permission/MyAccessDecisionManager.java b/src/main/java/cn/exrick/xboot/config/security/permission/MyAccessDecisionManager.java index 473d7fc1..fac7c9c8 100644 --- a/src/main/java/cn/exrick/xboot/config/security/permission/MyAccessDecisionManager.java +++ b/src/main/java/cn/exrick/xboot/config/security/permission/MyAccessDecisionManager.java @@ -14,7 +14,7 @@ /** * 权限管理决断器 - * 判断用户拥有的角色是否有资源访问权限 + * 判断用户拥有的权限或角色是否有资源访问权限 * @author Exrickx */ @Slf4j @@ -30,14 +30,15 @@ public void decide(Authentication authentication, Object o, Collection iterator = configAttributes.iterator(); while (iterator.hasNext()){ ConfigAttribute c = iterator.next(); - String needRole = c.getAttribute(); + String needPerm = c.getAttribute(); for(GrantedAuthority ga : authentication.getAuthorities()) { - if(needRole.trim().equals(ga.getAuthority())) { + // 匹配用户拥有的ga 和 系统中的needPerm + if(needPerm.trim().equals(ga.getAuthority())) { return; } } } - throw new AccessDeniedException("您没有访问权限"); + throw new AccessDeniedException("抱歉,您没有访问权限"); } @Override diff --git a/src/main/java/cn/exrick/xboot/config/security/permission/MySecurityMetadataSource.java b/src/main/java/cn/exrick/xboot/config/security/permission/MySecurityMetadataSource.java index 36694f71..ea51e95d 100644 --- a/src/main/java/cn/exrick/xboot/config/security/permission/MySecurityMetadataSource.java +++ b/src/main/java/cn/exrick/xboot/config/security/permission/MySecurityMetadataSource.java @@ -1,5 +1,6 @@ package cn.exrick.xboot.config.security.permission; +import cn.exrick.xboot.common.constant.CommonConstant; import cn.exrick.xboot.entity.Permission; import cn.exrick.xboot.service.PermissionService; import cn.hutool.core.util.StrUtil; @@ -30,23 +31,25 @@ public class MySecurityMetadataSource implements FilterInvocationSecurityMetadat private Map> map = null; /** - * 加载权限表中所有权限 + * 加载权限表中所有操作请求权限 */ public void loadResourceDefine(){ map = new HashMap<>(16); Collection configAttributes; ConfigAttribute cfg; - List permissions = permissionService.getAll(); + // 获取启用的权限操作请求 + List permissions = permissionService.findByTypeAndStatusOrderBySortOrder(CommonConstant.PERMISSION_OPERATION, CommonConstant.STATUS_NORMAL); for(Permission permission : permissions) { - configAttributes = new ArrayList<>(); - cfg = new SecurityConfig(permission.getTitle()); - //作为MyAccessDecisionManager类的decide的第三个参数 - configAttributes.add(cfg); - //用权限的path作为map的key,用ConfigAttribute的集合作为value - map.put(permission.getPath(), configAttributes); + if(StrUtil.isNotBlank(permission.getTitle())&&StrUtil.isNotBlank(permission.getPath())){ + configAttributes = new ArrayList<>(); + cfg = new SecurityConfig(permission.getTitle()); + //作为MyAccessDecisionManager类的decide的第三个参数 + configAttributes.add(cfg); + //用权限的path作为map的key,用ConfigAttribute的集合作为value + map.put(permission.getPath(), configAttributes); + } } - } /** diff --git a/src/main/java/cn/exrick/xboot/controller/TestController.java b/src/main/java/cn/exrick/xboot/controller/TestController.java index 4abae84a..4daf9ed6 100644 --- a/src/main/java/cn/exrick/xboot/controller/TestController.java +++ b/src/main/java/cn/exrick/xboot/controller/TestController.java @@ -5,10 +5,14 @@ import cn.exrick.xboot.common.lock.RedisDistributedLockTemplate; import cn.exrick.xboot.common.utils.ResultUtil; import cn.exrick.xboot.common.vo.Result; +import cn.exrick.xboot.exception.XbootException; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; +import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -17,16 +21,19 @@ * @author Exrickx */ @Slf4j -@RestController +@Controller @Api(description = "测试接口") +@Transactional +@RequestMapping("/test") public class TestController { @Autowired private RedisDistributedLockTemplate lockTemplate; - @RequestMapping(value = "/test",method = RequestMethod.GET) + @RequestMapping(value = "/lockAndLimit",method = RequestMethod.GET) @RateLimiter(limit = 1, timeout = 5000) @ApiOperation(value = "同步锁限流测试") + @ResponseBody public Result test(){ lockTemplate.execute("订单流水号", 5000, new Callback() { diff --git a/src/main/java/cn/exrick/xboot/controller/common/CaptchaController.java b/src/main/java/cn/exrick/xboot/controller/common/CaptchaController.java index e4338a92..0f001b5d 100644 --- a/src/main/java/cn/exrick/xboot/controller/common/CaptchaController.java +++ b/src/main/java/cn/exrick/xboot/controller/common/CaptchaController.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; @@ -22,6 +23,7 @@ @Api(description = "验证码接口") @RequestMapping("/xboot/common/captcha") @RestController +@Transactional public class CaptchaController { @Autowired diff --git a/src/main/java/cn/exrick/xboot/controller/common/IpInfoController.java b/src/main/java/cn/exrick/xboot/controller/common/IpInfoController.java index 58f293b6..e02e8120 100644 --- a/src/main/java/cn/exrick/xboot/controller/common/IpInfoController.java +++ b/src/main/java/cn/exrick/xboot/controller/common/IpInfoController.java @@ -6,6 +6,8 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -20,13 +22,17 @@ @RestController @Api(description = "IP接口") @RequestMapping("/xboot/common/ip") +@Transactional public class IpInfoController { + @Autowired + private IpInfoUtil ipInfoUtil; + @RequestMapping(value = "/info",method = RequestMethod.GET) @ApiOperation(value = "IP及天气相关信息") public Result upload(HttpServletRequest request) { - String result= IpInfoUtil.getIpWeatherInfo(IpInfoUtil.getIpAddr(request)); + String result= ipInfoUtil.getIpWeatherInfo(ipInfoUtil.getIpAddr(request)); return new ResultUtil().setData(result); } } \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/controller/common/SecurityController.java b/src/main/java/cn/exrick/xboot/controller/common/SecurityController.java index c07befeb..116f112a 100644 --- a/src/main/java/cn/exrick/xboot/controller/common/SecurityController.java +++ b/src/main/java/cn/exrick/xboot/controller/common/SecurityController.java @@ -5,6 +5,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @@ -16,6 +17,7 @@ @RestController @Api(description = "Security相关接口") @RequestMapping("/xboot/common") +@Transactional public class SecurityController { @RequestMapping(value = "/needLogin",method = RequestMethod.GET) diff --git a/src/main/java/cn/exrick/xboot/controller/common/UploadController.java b/src/main/java/cn/exrick/xboot/controller/common/UploadController.java index ed12980a..8b2e65b5 100644 --- a/src/main/java/cn/exrick/xboot/controller/common/UploadController.java +++ b/src/main/java/cn/exrick/xboot/controller/common/UploadController.java @@ -11,6 +11,7 @@ import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import redis.clients.jedis.Jedis; @@ -26,6 +27,7 @@ @RestController @Api(description = "文件上传接口") @RequestMapping("/xboot/upload") +@Transactional public class UploadController { @Autowired @@ -34,14 +36,17 @@ public class UploadController { @Autowired private QiniuUtil qiniuUtil; + @Autowired + private IpInfoUtil ipInfoUtil; + @RequestMapping(value = "/file",method = RequestMethod.POST) @ApiOperation(value = "文件上传") public Result upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) { // IP限流 在线Demo所需 5分钟限1个请求 - String token1 = redisRaterLimiter.acquireTokenFromBucket("upload:"+IpInfoUtil.getIpAddr(request), 1, 300000); - if (StrUtil.isBlank(token1)) { + String token = redisRaterLimiter.acquireTokenFromBucket("upload:"+ipInfoUtil.getIpAddr(request), 1, 300000); + if (StrUtil.isBlank(token)) { throw new XbootException("上传那么多干嘛,等等再传吧"); } diff --git a/src/main/java/cn/exrick/xboot/controller/manage/DepartmentController.java b/src/main/java/cn/exrick/xboot/controller/manage/DepartmentController.java new file mode 100644 index 00000000..c45f707e --- /dev/null +++ b/src/main/java/cn/exrick/xboot/controller/manage/DepartmentController.java @@ -0,0 +1,119 @@ +package cn.exrick.xboot.controller.manage; + +import cn.exrick.xboot.base.XbootBaseController; +import cn.exrick.xboot.common.constant.CommonConstant; +import cn.exrick.xboot.common.utils.PageUtil; +import cn.exrick.xboot.common.utils.ResultUtil; +import cn.exrick.xboot.common.vo.PageVo; +import cn.exrick.xboot.common.vo.Result; +import cn.exrick.xboot.entity.Department; +import cn.exrick.xboot.entity.User; +import cn.exrick.xboot.service.DepartmentService; +import cn.exrick.xboot.service.UserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Set; + + +/** + * @author Exrick + */ +@Slf4j +@RestController +@Api(description = "部门管理接口") +@RequestMapping("/xboot/department") +@CacheConfig(cacheNames = "department") +@Transactional +public class DepartmentController { + + @Autowired + private DepartmentService departmentService; + + @Autowired + private UserService userService; + + @Autowired + private StringRedisTemplate redisTemplate; + + @RequestMapping(value = "/getByParentId/{parentId}",method = RequestMethod.GET) + @ApiOperation(value = "通过id获取") + @Cacheable(key = "#parentId") + public Result> getByParentId(@PathVariable String parentId){ + + List list = departmentService.findByParentIdOrderBySortOrder(parentId); + // lambda表达式 + list.forEach(item -> { + if(!CommonConstant.PARENT_ID.equals(item.getParentId())){ + Department parent = departmentService.get(item.getParentId()); + item.setParentTitle(parent.getTitle()); + }else{ + item.setParentTitle("一级部门"); + } + }); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/add",method = RequestMethod.POST) + @ApiOperation(value = "添加") + @CacheEvict(key = "#department.parentId") + public Result add(@ModelAttribute Department department){ + + Department d = departmentService.save(department); + // 如果不是添加的一级 判断设置上级为父节点标识 + if(!CommonConstant.PARENT_ID.equals(department.getParentId())){ + Department parent = departmentService.get(department.getParentId()); + if(parent.getIsParent()==null||!parent.getIsParent()){ + parent.setIsParent(true); + departmentService.update(parent); + // 更新上级节点的缓存 + redisTemplate.delete("department::" + parent.getParentId()); + } + } + return new ResultUtil().setData(d); + } + + @RequestMapping(value = "/edit",method = RequestMethod.POST) + @ApiOperation(value = "编辑") + public Result edit(@ModelAttribute Department department){ + + Department d = departmentService.update(department); + // 手动删除所有部门缓存 + Set keys = redisTemplate.keys("department:" + "*"); + redisTemplate.delete(keys); + // 删除所有用户缓存 + Set keysUser = redisTemplate.keys("user:" + "*"); + redisTemplate.delete(keysUser); + return new ResultUtil().setData(d); + } + + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) + @ApiOperation(value = "批量通过id删除") + public Result delByIds(@PathVariable String[] ids){ + + for(String id:ids){ + List list = userService.findByDepartmentId(id); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("删除失败,包含正被用户使用关联的部门"); + } + } + for(String id:ids){ + departmentService.delete(id); + } + // 手动删除所有部门缓存 + Set keys = redisTemplate.keys("department:" + "*"); + redisTemplate.delete(keys); + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } + +} diff --git a/src/main/java/cn/exrick/xboot/controller/manage/EsController.java b/src/main/java/cn/exrick/xboot/controller/manage/EsController.java index 610d911b..04e74aba 100644 --- a/src/main/java/cn/exrick/xboot/controller/manage/EsController.java +++ b/src/main/java/cn/exrick/xboot/controller/manage/EsController.java @@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -25,6 +26,7 @@ @RestController @Api(description = "Elasticsearch信息接口") @RequestMapping("/xboot/es") +@Transactional public class EsController { @Value("${xboot.elasticsearch.nodeClient}") @@ -32,7 +34,7 @@ public class EsController { @RequestMapping(value = "/info",method = RequestMethod.GET) @ApiOperation(value = "获取es状态") - public Result getAllByPage(@ModelAttribute PageVo pageVo){ + public Result getAllByPage(){ String healthUrl="http://"+ES_NODE_CLIENT+"/_cluster/health"; String countUrl="http://"+ES_NODE_CLIENT+"/_count"; diff --git a/src/main/java/cn/exrick/xboot/controller/manage/LogController.java b/src/main/java/cn/exrick/xboot/controller/manage/LogController.java index 6d12a8fe..16dd6070 100644 --- a/src/main/java/cn/exrick/xboot/controller/manage/LogController.java +++ b/src/main/java/cn/exrick/xboot/controller/manage/LogController.java @@ -16,17 +16,18 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; /** - * 拥有ROLE_ADMIN角色的用户可以访问 * @author Exrickx */ @Slf4j @RestController @Api(description = "日志管理接口") @RequestMapping("/xboot/log") +@Transactional public class LogController{ @Value("${xboot.logRecord.es}") @@ -66,9 +67,9 @@ public Result search(@RequestParam String key, } } - @RequestMapping(value = "/delByIds",method = RequestMethod.DELETE) + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) @ApiOperation(value = "批量删除") - public Result delByIds(@RequestParam String[] ids){ + public Result delByIds(@PathVariable String[] ids){ for(String id : ids){ if(esRecord){ diff --git a/src/main/java/cn/exrick/xboot/controller/manage/PermissionController.java b/src/main/java/cn/exrick/xboot/controller/manage/PermissionController.java index 74258fdb..8432d89f 100644 --- a/src/main/java/cn/exrick/xboot/controller/manage/PermissionController.java +++ b/src/main/java/cn/exrick/xboot/controller/manage/PermissionController.java @@ -22,6 +22,7 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; @@ -37,6 +38,7 @@ @Api(description = "菜单/权限管理接口") @RequestMapping("/xboot/permission") @CacheConfig(cacheNames = "permission") +@Transactional public class PermissionController { @Autowired @@ -133,6 +135,13 @@ public Result> getAllList(){ @CacheEvict(key = "'menuList'") public Result add(@ModelAttribute Permission permission){ + // 判断拦截请求的操作权限按钮名是否已存在 + if(CommonConstant.PERMISSION_OPERATION.equals(permission.getType())){ + List list = permissionService.findByTitle(permission.getTitle()); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("名称已存在"); + } + } Permission u = permissionService.save(permission); //重新加载权限 mySecurityMetadataSource.loadResourceDefine(); @@ -145,6 +154,17 @@ public Result add(@ModelAttribute Permission permission){ @ApiOperation(value = "编辑") public Result edit(@ModelAttribute Permission permission){ + // 判断拦截请求的操作权限按钮名是否已存在 + if(CommonConstant.PERMISSION_OPERATION.equals(permission.getType())){ + // 若名称修改 + Permission p = permissionService.get(permission.getId()); + if(!p.getTitle().equals(permission.getTitle())){ + List list = permissionService.findByTitle(permission.getTitle()); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("名称已存在"); + } + } + } Permission u = permissionService.update(permission); //重新加载权限 mySecurityMetadataSource.loadResourceDefine(); @@ -159,15 +179,15 @@ public Result edit(@ModelAttribute Permission permission){ return new ResultUtil().setData(u); } - @RequestMapping(value = "/delByIds",method = RequestMethod.DELETE) + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) @ApiOperation(value = "批量通过id删除") @CacheEvict(key = "'menuList'") - public Result delByIds(@RequestParam String[] ids){ + public Result delByIds(@PathVariable String[] ids){ for(String id:ids){ List list = rolePermissionService.findByPermissionId(id); if(list!=null&&list.size()>0){ - return new ResultUtil().setErrorMsg("删除失败,包含正被使用中的菜单或权限"); + return new ResultUtil().setErrorMsg("删除失败,包含正被角色使用关联的菜单或权限"); } } for(String id:ids){ diff --git a/src/main/java/cn/exrick/xboot/controller/manage/QuartzJobController.java b/src/main/java/cn/exrick/xboot/controller/manage/QuartzJobController.java new file mode 100644 index 00000000..893ff0d0 --- /dev/null +++ b/src/main/java/cn/exrick/xboot/controller/manage/QuartzJobController.java @@ -0,0 +1,166 @@ +package cn.exrick.xboot.controller.manage; + +import cn.exrick.xboot.common.constant.CommonConstant; +import cn.exrick.xboot.common.utils.PageUtil; +import cn.exrick.xboot.common.utils.ResultUtil; +import cn.exrick.xboot.common.vo.PageVo; +import cn.exrick.xboot.common.vo.Result; +import cn.exrick.xboot.entity.QuartzJob; +import cn.exrick.xboot.exception.XbootException; +import cn.exrick.xboot.service.QuartzJobService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * @author Exrick + */ +@Slf4j +@RestController +@Api(description = "定时任务管理接口") +@RequestMapping("/xboot/quartzJob") +@Transactional +public class QuartzJobController { + + @Autowired + private QuartzJobService quartzJobService; + + @Autowired + private Scheduler scheduler; + + @RequestMapping(value = "/getAllByPage",method = RequestMethod.GET) + @ApiOperation(value = "获取所有定时任务") + public Result> getAll(@ModelAttribute PageVo page){ + + Page data = quartzJobService.findAll(PageUtil.initPage(page)); + return new ResultUtil>().setData(data); + } + + @RequestMapping(value = "/add",method = RequestMethod.POST) + @ApiOperation(value = "添加定时任务") + public Result addJob(@ModelAttribute QuartzJob job){ + + List list = quartzJobService.findByJobClassName(job.getJobClassName()); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("该定时任务类名已存在"); + } + add(job.getJobClassName(),job.getCronExpression(),job.getParameter()); + quartzJobService.save(job); + return new ResultUtil().setSuccessMsg("创建定时任务成功"); + } + + @RequestMapping(value = "/edit",method = RequestMethod.POST) + @ApiOperation(value = "更新定时任务") + public Result editJob(@ModelAttribute QuartzJob job){ + + delete(job.getJobClassName()); + add(job.getJobClassName(),job.getCronExpression(),job.getParameter()); + job.setStatus(CommonConstant.STATUS_NORMAL); + quartzJobService.update(job); + return new ResultUtil().setSuccessMsg("更新定时任务成功"); + } + + @RequestMapping(value = "/pause",method = RequestMethod.POST) + @ApiOperation(value = "暂停定时任务") + public Result pauseJob(@ModelAttribute QuartzJob job){ + + try { + scheduler.pauseJob(JobKey.jobKey(job.getJobClassName())); + } catch (SchedulerException e) { + throw new XbootException("暂停定时任务失败"); + } + job.setStatus(CommonConstant.STATUS_DISABLE); + quartzJobService.update(job); + return new ResultUtil().setSuccessMsg("暂停定时任务成功"); + } + + @RequestMapping(value = "/resume",method = RequestMethod.POST) + @ApiOperation(value = "恢复定时任务") + public Result resumeJob(@ModelAttribute QuartzJob job){ + + try { + scheduler.resumeJob(JobKey.jobKey(job.getJobClassName())); + } catch (SchedulerException e) { + throw new XbootException("恢复定时任务失败"); + } + job.setStatus(CommonConstant.STATUS_NORMAL); + quartzJobService.update(job); + return new ResultUtil().setSuccessMsg("恢复定时任务成功"); + } + + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) + @ApiOperation(value = "删除定时任务") + public Result deleteJob(@PathVariable String[] ids){ + + for(String id:ids){ + QuartzJob job = quartzJobService.get(id); + delete(job.getJobClassName()); + quartzJobService.delete(job); + } + return new ResultUtil().setSuccessMsg("删除定时任务成功"); + } + + /** + * 添加定时任务 + * @param jobClassName + * @param cronExpression + * @param parameter + */ + public void add(String jobClassName, String cronExpression, String parameter){ + + try { + // 启动调度器 + scheduler.start(); + + //构建job信息 + JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()) + .withIdentity(jobClassName) + .usingJobData("parameter",parameter) + .build(); + + //表达式调度构建器(即任务执行的时间) + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); + + //按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName) + .withSchedule(scheduleBuilder).build(); + + scheduler.scheduleJob(jobDetail, trigger); + } catch (SchedulerException e) { + log.error(e.toString()); + throw new XbootException("创建定时任务失败"); + } catch (Exception e){ + throw new XbootException("后台找不到该类名任务"); + } + } + + /** + * 删除定时任务 + * @param jobClassName + */ + public void delete(String jobClassName){ + + try { + scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName)); + scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName)); + scheduler.deleteJob(JobKey.jobKey(jobClassName)); + } catch (Exception e) { + throw new XbootException("删除定时任务失败"); + } + } + + public static Job getClass(String classname) throws Exception { + Class class1 = Class.forName(classname); + return (Job)class1.newInstance(); + } + +} diff --git a/src/main/java/cn/exrick/xboot/controller/manage/RoleController.java b/src/main/java/cn/exrick/xboot/controller/manage/RoleController.java index 1afa1a9f..542219ba 100644 --- a/src/main/java/cn/exrick/xboot/controller/manage/RoleController.java +++ b/src/main/java/cn/exrick/xboot/controller/manage/RoleController.java @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -32,7 +33,8 @@ @RestController @Api(description = "角色管理接口") @RequestMapping("/xboot/role") -public class RoleController extends XbootBaseController { +@Transactional +public class RoleController { @Autowired private RoleService roleService; @@ -49,11 +51,6 @@ public class RoleController extends XbootBaseController { @Autowired private StringRedisTemplate redisTemplate; - @Override - public RoleService getService() { - return roleService; - } - @RequestMapping(value = "/getAllList",method = RequestMethod.GET) @ApiOperation(value = "获取全部角色") public Result roleGetAll(){ @@ -114,6 +111,14 @@ public Result editRolePerm(@PathVariable String roleId, return new ResultUtil().setData(null); } + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ApiOperation(value = "保存数据") + public Result save(@ModelAttribute Role role){ + + Role r = roleService.save(role); + return new ResultUtil().setData(r); + } + @RequestMapping(value = "/edit",method = RequestMethod.POST) @ApiOperation(value = "更新数据") public Result edit(@ModelAttribute Role entity){ @@ -127,14 +132,14 @@ public Result edit(@ModelAttribute Role entity){ return new ResultUtil().setData(r); } - @RequestMapping(value = "/delAllByIds",method = RequestMethod.DELETE) + @RequestMapping(value = "/delAllByIds/{ids}",method = RequestMethod.DELETE) @ApiOperation(value = "批量通过ids删除") - public Result delByIds(@RequestParam String[] ids){ + public Result delByIds(@PathVariable String[] ids){ for(String id:ids){ List list = userRoleService.findByRoleId(id); if(list!=null&&list.size()>0){ - return new ResultUtil().setErrorMsg("删除失败,包含正被使用中的角色"); + return new ResultUtil().setErrorMsg("删除失败,包含正被用户使用关联的角色"); } } for(String id:ids){ diff --git a/src/main/java/cn/exrick/xboot/controller/manage/UserController.java b/src/main/java/cn/exrick/xboot/controller/manage/UserController.java index 6f41a6bb..82c148cd 100644 --- a/src/main/java/cn/exrick/xboot/controller/manage/UserController.java +++ b/src/main/java/cn/exrick/xboot/controller/manage/UserController.java @@ -6,9 +6,12 @@ import cn.exrick.xboot.common.vo.PageVo; import cn.exrick.xboot.common.vo.Result; import cn.exrick.xboot.common.vo.SearchVo; +import cn.exrick.xboot.dao.DepartmentDao; +import cn.exrick.xboot.entity.Department; import cn.exrick.xboot.entity.Role; import cn.exrick.xboot.entity.User; import cn.exrick.xboot.entity.UserRole; +import cn.exrick.xboot.service.DepartmentService; import cn.exrick.xboot.service.RoleService; import cn.exrick.xboot.service.UserRoleService; import cn.exrick.xboot.service.UserService; @@ -18,6 +21,8 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; +import org.hibernate.Session; +import org.hibernate.jpa.HibernateEntityManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; @@ -27,8 +32,11 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; import java.util.ArrayList; import java.util.List; @@ -41,6 +49,7 @@ @Api(description = "用户接口") @RequestMapping("/xboot/user") @CacheConfig(cacheNames = "user") +@Transactional public class UserController { @Autowired @@ -49,6 +58,9 @@ public class UserController { @Autowired private RoleService roleService; + @Autowired + private DepartmentService departmentService; + @Autowired private IUserRoleService iUserRoleService; @@ -58,6 +70,9 @@ public class UserController { @Autowired private StringRedisTemplate redisTemplate; + @PersistenceContext + private EntityManager entityManager; + @RequestMapping(value = "/regist",method = RequestMethod.POST) @ApiOperation(value = "注册用户") public Result regist(@ModelAttribute User u, @@ -113,6 +128,8 @@ public Result getUserInfo(){ UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); User u = userService.findByUsername(user.getUsername()); + // 清除持久上下文环境 避免后面语句导致持久化 + entityManager.clear(); u.setPassword(null); return new ResultUtil().setData(u); } @@ -234,8 +251,16 @@ public Result> getByCondition(@ModelAttribute User user, Page page = userService.findByCondition(user, searchVo, PageUtil.initPage(pageVo)); for(User u: page.getContent()){ + // 关联部门 + if(StrUtil.isNotBlank(u.getDepartmentId())){ + Department department = departmentService.get(u.getDepartmentId()); + u.setDepartmentTitle(department.getTitle()); + } + // 关联角色 List list = iUserRoleService.findByUserId(u.getId()); u.setRoles(list); + // 清除持久上下文环境 避免后面语句导致持久化 + entityManager.clear(); u.setPassword(null); } return new ResultUtil>().setData(page); @@ -305,9 +330,9 @@ public Result enable(@ApiParam("用户唯一id标识") @PathVariable Str return new ResultUtil().setData(null); } - @RequestMapping(value = "/delByIds",method = RequestMethod.DELETE) + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) @ApiOperation(value = "批量通过ids删除") - public Result delAllByIds(@RequestParam String[] ids){ + public Result delAllByIds(@PathVariable String[] ids){ for(String id:ids){ userService.delete(id); diff --git a/src/main/java/cn/exrick/xboot/dao/DepartmentDao.java b/src/main/java/cn/exrick/xboot/dao/DepartmentDao.java new file mode 100644 index 00000000..e2c55b7b --- /dev/null +++ b/src/main/java/cn/exrick/xboot/dao/DepartmentDao.java @@ -0,0 +1,28 @@ +package cn.exrick.xboot.dao; + +import cn.exrick.xboot.base.XbootBaseDao; +import cn.exrick.xboot.entity.Department; + +import java.util.List; + +/** + * 部门数据处理层 + * @author Exrick + */ +public interface DepartmentDao extends XbootBaseDao { + + /** + * 通过父id获取 升序 + * @param parentId + * @return + */ + List findByParentIdOrderBySortOrder(String parentId); + + /** + * 通过父id和状态获取 升序 + * @param parentId + * @param status + * @return + */ + List findByParentIdAndStatusOrderBySortOrder(String parentId, Integer status); +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/dao/PermissionDao.java b/src/main/java/cn/exrick/xboot/dao/PermissionDao.java index 5153564e..78b2642d 100644 --- a/src/main/java/cn/exrick/xboot/dao/PermissionDao.java +++ b/src/main/java/cn/exrick/xboot/dao/PermissionDao.java @@ -27,18 +27,17 @@ public interface PermissionDao extends XbootBaseDao { List findByParentIdOrderBySortOrder(String parentId); /** - * 通过类型和层级查找 - * @param level + * 通过类型和状态获取 * @param type + * @param status * @return */ - List findByLevelAndTypeOrderBySortOrder(Integer level, Integer type); + List findByTypeAndStatusOrderBySortOrder(Integer type, Integer status); /** - * 通过parendId和类型查找 - * @param type - * @param parentId + * 通过名称获取 + * @param title * @return */ - List findByTypeAndParentIdOrderBySortOrder(Integer type, String parentId); + List findByTitle(String title); } \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/dao/QuartzJobDao.java b/src/main/java/cn/exrick/xboot/dao/QuartzJobDao.java new file mode 100644 index 00000000..d2564d4d --- /dev/null +++ b/src/main/java/cn/exrick/xboot/dao/QuartzJobDao.java @@ -0,0 +1,20 @@ +package cn.exrick.xboot.dao; + +import cn.exrick.xboot.base.XbootBaseDao; +import cn.exrick.xboot.entity.QuartzJob; + +import java.util.List; + +/** + * 定时任务数据处理层 + * @author Exrick + */ +public interface QuartzJobDao extends XbootBaseDao { + + /** + * 通过类名获取 + * @param jobClassName + * @return + */ + List findByJobClassName(String jobClassName); +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/dao/UserDao.java b/src/main/java/cn/exrick/xboot/dao/UserDao.java index ce7c0da5..921beb36 100644 --- a/src/main/java/cn/exrick/xboot/dao/UserDao.java +++ b/src/main/java/cn/exrick/xboot/dao/UserDao.java @@ -27,4 +27,11 @@ public interface UserDao extends XbootBaseDao { * @return */ List findByStatusAndType(Integer status, Integer type); + + /** + * 通过部门id获取 + * @param departmentId + * @return + */ + List findByDepartmentId(String departmentId); } diff --git a/src/main/java/cn/exrick/xboot/entity/Department.java b/src/main/java/cn/exrick/xboot/entity/Department.java new file mode 100644 index 00000000..7d7634c7 --- /dev/null +++ b/src/main/java/cn/exrick/xboot/entity/Department.java @@ -0,0 +1,49 @@ +package cn.exrick.xboot.entity; + +import cn.exrick.xboot.base.XbootBaseEntity; +import cn.exrick.xboot.common.constant.CommonConstant; +import com.baomidou.mybatisplus.annotations.TableField; +import com.baomidou.mybatisplus.annotations.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Exrick + */ +@Data +@Entity +@Table(name = "t_department") +@TableName("t_department") +public class Department extends XbootBaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "部门名称") + private String title; + + @ApiModelProperty(value = "父id") + private String parentId; + + @ApiModelProperty(value = "是否为父节点(含子节点) 默认false") + private Boolean isParent = false; + + @ApiModelProperty(value = "排序值") + @Column(precision = 10, scale = 2) + private BigDecimal sortOrder; + + @ApiModelProperty(value = "是否启用 0启用 -1禁用") + private Integer status = CommonConstant.STATUS_NORMAL; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "父节点名称") + private String parentTitle; +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/entity/Permission.java b/src/main/java/cn/exrick/xboot/entity/Permission.java index edbe98f4..605edc80 100644 --- a/src/main/java/cn/exrick/xboot/entity/Permission.java +++ b/src/main/java/cn/exrick/xboot/entity/Permission.java @@ -64,6 +64,9 @@ public class Permission extends XbootBaseEntity { @ApiModelProperty(value = "是否启用 0启用 -1禁用") private Integer status = CommonConstant.STATUS_NORMAL; + @ApiModelProperty(value = "网页链接") + private String url; + @Transient @TableField(exist=false) @ApiModelProperty(value = "子菜单/权限") diff --git a/src/main/java/cn/exrick/xboot/entity/QuartzJob.java b/src/main/java/cn/exrick/xboot/entity/QuartzJob.java new file mode 100644 index 00000000..e45110ba --- /dev/null +++ b/src/main/java/cn/exrick/xboot/entity/QuartzJob.java @@ -0,0 +1,40 @@ +package cn.exrick.xboot.entity; + +import cn.exrick.xboot.base.XbootBaseEntity; +import cn.exrick.xboot.common.constant.CommonConstant; +import com.baomidou.mybatisplus.annotations.TableField; +import com.baomidou.mybatisplus.annotations.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.util.List; + +/** + * @author Exrickx + */ +@Data +@Entity +@Table(name = "t_quartz_job") +@TableName("t_quartz_job") +public class QuartzJob extends XbootBaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "任务类名") + private String jobClassName; + + @ApiModelProperty(value = "cron表达式") + private String cronExpression; + + @ApiModelProperty(value = "参数") + private String parameter; + + @ApiModelProperty(value = "备注") + private String description; + + @ApiModelProperty(value = "状态 0正常 -1停止") + private Integer status = CommonConstant.STATUS_NORMAL; +} diff --git a/src/main/java/cn/exrick/xboot/entity/Role.java b/src/main/java/cn/exrick/xboot/entity/Role.java index 0b3957f8..d7fddf35 100644 --- a/src/main/java/cn/exrick/xboot/entity/Role.java +++ b/src/main/java/cn/exrick/xboot/entity/Role.java @@ -28,6 +28,9 @@ public class Role extends XbootBaseEntity { @ApiModelProperty(value = "是否为注册默认角色") private Boolean defaultRole; + @ApiModelProperty(value = "备注") + private String description; + @Transient @TableField(exist=false) @ApiModelProperty(value = "拥有权限") diff --git a/src/main/java/cn/exrick/xboot/entity/User.java b/src/main/java/cn/exrick/xboot/entity/User.java index da33d41f..164403d0 100644 --- a/src/main/java/cn/exrick/xboot/entity/User.java +++ b/src/main/java/cn/exrick/xboot/entity/User.java @@ -25,7 +25,7 @@ public class User extends XbootBaseEntity { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "用户名") - @Column(unique = true,nullable = false) + @Column(unique = true, nullable = false) private String username; @ApiModelProperty(value = "密码") @@ -44,12 +44,11 @@ public class User extends XbootBaseEntity { private String address; @ApiModelProperty(value = "0女 1男 2保密") - @Column(length=1) private Integer sex; @ApiModelProperty(value = "用户头像") @Column(length=1000) - private String avatar = "https://s1.ax1x.com/2018/05/19/CcdVQP.png"; + private String avatar = CommonConstant.USER_DEFAULT_AVATAR; @ApiModelProperty(value = "用户类型 0普通用户 1管理员") private Integer type = CommonConstant.USER_TYPE_NORMAL; @@ -60,6 +59,14 @@ public class User extends XbootBaseEntity { @ApiModelProperty(value = "描述/详情/备注") private String description; + @ApiModelProperty(value = "所属部门id") + private String departmentId; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "所属部门名称") + private String departmentTitle; + @Transient @TableField(exist=false) @ApiModelProperty(value = "用户拥有角色") diff --git a/src/main/java/cn/exrick/xboot/exception/RestCtrlExceptionHandler.java b/src/main/java/cn/exrick/xboot/exception/RestCtrlExceptionHandler.java index 6ab59b4f..31ac2084 100644 --- a/src/main/java/cn/exrick/xboot/exception/RestCtrlExceptionHandler.java +++ b/src/main/java/cn/exrick/xboot/exception/RestCtrlExceptionHandler.java @@ -19,10 +19,11 @@ public class RestCtrlExceptionHandler { @ExceptionHandler(XbootException.class) @ResponseStatus(value = HttpStatus.OK) public Result handleXCloudException(XbootException e) { + String errorMsg="Xboot exception"; if (e!=null){ errorMsg=e.getMsg(); - log.warn(e.toString()); + log.error(e.toString()); } return new ResultUtil<>().setErrorMsg(500, errorMsg); } @@ -30,10 +31,11 @@ public Result handleXCloudException(XbootException e) { @ExceptionHandler(Exception.class) @ResponseStatus(value = HttpStatus.OK) public Result handleException(Exception e) { + String errorMsg="Exception"; if (e!=null){ errorMsg=e.getMessage(); - log.warn(e.toString()); + log.error(e.toString()); } return new ResultUtil<>().setErrorMsg(500, errorMsg); } diff --git a/src/main/java/cn/exrick/xboot/generator/XbootGenerator.java b/src/main/java/cn/exrick/xboot/generator/XbootGenerator.java index 0148b767..9a0a0ee4 100644 --- a/src/main/java/cn/exrick/xboot/generator/XbootGenerator.java +++ b/src/main/java/cn/exrick/xboot/generator/XbootGenerator.java @@ -24,13 +24,13 @@ public class XbootGenerator { * 实体类名 * 建议仅需修改 */ - private static final String className = "RolePermission"; + private static final String className = "Xboot"; /** * 类说明描述 * 建议仅需修改 */ - private static final String description = "角色权限"; + private static final String description = "测试"; /** * 作者名 diff --git a/src/main/java/cn/exrick/xboot/generator/template/controller.btl b/src/main/java/cn/exrick/xboot/generator/template/controller.btl index aca16559..e438b00c 100644 --- a/src/main/java/cn/exrick/xboot/generator/template/controller.btl +++ b/src/main/java/cn/exrick/xboot/generator/template/controller.btl @@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; +import org.springframework.transaction.annotation.Transactional; /** @@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.*; @RestController @Api(description = "${entity.description}管理接口") @RequestMapping("/xboot/${entity.classNameLowerCase}") +@Transactional public class ${entity.className}Controller extends XbootBaseController<${entity.className}, ${entity.primaryKeyType}>{ @Autowired diff --git a/src/main/java/cn/exrick/xboot/quartz/jobs/SampleJob.java b/src/main/java/cn/exrick/xboot/quartz/jobs/SampleJob.java new file mode 100644 index 00000000..9af8c6fc --- /dev/null +++ b/src/main/java/cn/exrick/xboot/quartz/jobs/SampleJob.java @@ -0,0 +1,21 @@ +package cn.exrick.xboot.quartz.jobs; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * 示例带参定时任务 + * @author Exrickx + */ +@Slf4j +public class SampleJob implements Job { + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + + log.info(String.format("欢迎使用XBoot前后端分离开发平台!作者:Exrick 时间:"+ DateUtil.now())); + } +} diff --git a/src/main/java/cn/exrick/xboot/quartz/jobs/SampleParamJob.java b/src/main/java/cn/exrick/xboot/quartz/jobs/SampleParamJob.java new file mode 100644 index 00000000..81780ca3 --- /dev/null +++ b/src/main/java/cn/exrick/xboot/quartz/jobs/SampleParamJob.java @@ -0,0 +1,30 @@ +package cn.exrick.xboot.quartz.jobs; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * 示例带参定时任务 + * @author Exrickx + */ +@Slf4j +public class SampleParamJob implements Job { + + /** + * 若参数变量名修改 QuartzJobController中也需对应修改 + */ + private String parameter; + + public void setParameter(String parameter) { + this.parameter = parameter; + } + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + + log.info(String.format("Hello %s! 欢迎使用XBoot前后端分离开发平台!作者:Exrick 时间:"+ DateUtil.now(), this.parameter)); + } +} diff --git a/src/main/java/cn/exrick/xboot/service/DepartmentService.java b/src/main/java/cn/exrick/xboot/service/DepartmentService.java new file mode 100644 index 00000000..40d40d0b --- /dev/null +++ b/src/main/java/cn/exrick/xboot/service/DepartmentService.java @@ -0,0 +1,30 @@ +package cn.exrick.xboot.service; + +import cn.exrick.xboot.base.XbootBaseService; +import cn.exrick.xboot.entity.Department; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +/** + * 部门接口 + * @author Exrick + */ +public interface DepartmentService extends XbootBaseService { + + /** + * 通过父id获取 升序 + * @param parentId + * @return + */ + List findByParentIdOrderBySortOrder(String parentId); + + /** + * 通过父id和状态获取 + * @param parentId + * @param status + * @return + */ + List findByParentIdAndStatusOrderBySortOrder(String parentId, Integer status); +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/service/PermissionService.java b/src/main/java/cn/exrick/xboot/service/PermissionService.java index fe9e8b1f..aeff39f0 100644 --- a/src/main/java/cn/exrick/xboot/service/PermissionService.java +++ b/src/main/java/cn/exrick/xboot/service/PermissionService.java @@ -29,18 +29,17 @@ public interface PermissionService extends XbootBaseService { List findByParentIdOrderBySortOrder(String parentId); /** - * 通过类型和层级查找 - * @param level + * 通过类型和状态获取 * @param type + * @param status * @return */ - List findByLevelAndTypeOrderBySortOrder(Integer level, Integer type); + List findByTypeAndStatusOrderBySortOrder(Integer type, Integer status); /** - * 通过parendId和类型查找 - * @param type - * @param parentId + * 通过名称获取 + * @param title * @return */ - List findByTypeAndParentIdOrderBySortOrder(Integer type, String parentId); + List findByTitle(String title); } \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/service/QuartzJobService.java b/src/main/java/cn/exrick/xboot/service/QuartzJobService.java new file mode 100644 index 00000000..1086d4e5 --- /dev/null +++ b/src/main/java/cn/exrick/xboot/service/QuartzJobService.java @@ -0,0 +1,22 @@ +package cn.exrick.xboot.service; + +import cn.exrick.xboot.base.XbootBaseService; +import cn.exrick.xboot.entity.QuartzJob; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +/** + * 定时任务接口 + * @author Exrick + */ +public interface QuartzJobService extends XbootBaseService { + + /** + * 通过类名获取 + * @param jobClassName + * @return + */ + List findByJobClassName(String jobClassName); +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/service/UserService.java b/src/main/java/cn/exrick/xboot/service/UserService.java index 06ba130c..62e72ea5 100644 --- a/src/main/java/cn/exrick/xboot/service/UserService.java +++ b/src/main/java/cn/exrick/xboot/service/UserService.java @@ -26,14 +26,6 @@ public interface UserService extends XbootBaseService { @Cacheable(key = "#username") User findByUsername(String username); - /** - * 通过状态和类型获取用户 - * @param status - * @param type - * @return - */ - List findByStatusAndType(Integer status, Integer type); - /** * 多条件分页获取用户 * @param user @@ -42,4 +34,11 @@ public interface UserService extends XbootBaseService { * @return */ Page findByCondition(User user, SearchVo searchVo, Pageable pageable); + + /** + * 通过部门id获取 + * @param departmentId + * @return + */ + List findByDepartmentId(String departmentId); } diff --git a/src/main/java/cn/exrick/xboot/serviceimpl/DepartmentServiceImpl.java b/src/main/java/cn/exrick/xboot/serviceimpl/DepartmentServiceImpl.java new file mode 100644 index 00000000..adf73d2b --- /dev/null +++ b/src/main/java/cn/exrick/xboot/serviceimpl/DepartmentServiceImpl.java @@ -0,0 +1,44 @@ +package cn.exrick.xboot.serviceimpl; + +import cn.exrick.xboot.dao.DepartmentDao; +import cn.exrick.xboot.entity.Department; +import cn.exrick.xboot.service.DepartmentService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 部门接口实现 + * @author Exrick + */ +@Slf4j +@Service +@Transactional +public class DepartmentServiceImpl implements DepartmentService { + + @Autowired + private DepartmentDao departmentDao; + + @Override + public DepartmentDao getRepository() { + return departmentDao; + } + + @Override + public List findByParentIdOrderBySortOrder(String parentId) { + + return departmentDao.findByParentIdOrderBySortOrder(parentId); + } + + @Override + public List findByParentIdAndStatusOrderBySortOrder(String parentId, Integer status) { + + return departmentDao.findByParentIdAndStatusOrderBySortOrder(parentId, status); + } +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/serviceimpl/PermissionServiceImpl.java b/src/main/java/cn/exrick/xboot/serviceimpl/PermissionServiceImpl.java index 99ef52af..a5eed57e 100644 --- a/src/main/java/cn/exrick/xboot/serviceimpl/PermissionServiceImpl.java +++ b/src/main/java/cn/exrick/xboot/serviceimpl/PermissionServiceImpl.java @@ -43,14 +43,14 @@ public List findByParentIdOrderBySortOrder(String parentId) { } @Override - public List findByLevelAndTypeOrderBySortOrder(Integer level, Integer type) { + public List findByTypeAndStatusOrderBySortOrder(Integer type, Integer status) { - return permissionDao.findByLevelAndTypeOrderBySortOrder(level, type); + return permissionDao.findByTypeAndStatusOrderBySortOrder(type, status); } @Override - public List findByTypeAndParentIdOrderBySortOrder(Integer type, String parentId) { + public List findByTitle(String title) { - return permissionDao.findByTypeAndParentIdOrderBySortOrder(type, parentId); + return permissionDao.findByTitle(title); } } \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/serviceimpl/QuartzJobServiceImpl.java b/src/main/java/cn/exrick/xboot/serviceimpl/QuartzJobServiceImpl.java new file mode 100644 index 00000000..ea3bd893 --- /dev/null +++ b/src/main/java/cn/exrick/xboot/serviceimpl/QuartzJobServiceImpl.java @@ -0,0 +1,38 @@ +package cn.exrick.xboot.serviceimpl; + +import cn.exrick.xboot.dao.QuartzJobDao; +import cn.exrick.xboot.entity.QuartzJob; +import cn.exrick.xboot.service.QuartzJobService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 定时任务接口实现 + * @author Exrick + */ +@Slf4j +@Service +@Transactional +public class QuartzJobServiceImpl implements QuartzJobService { + + @Autowired + private QuartzJobDao quartzJobDao; + + @Override + public QuartzJobDao getRepository() { + return quartzJobDao; + } + + @Override + public List findByJobClassName(String jobClassName) { + + return quartzJobDao.findByJobClassName(jobClassName); + } +} \ No newline at end of file diff --git a/src/main/java/cn/exrick/xboot/serviceimpl/UserServiceImpl.java b/src/main/java/cn/exrick/xboot/serviceimpl/UserServiceImpl.java index 7fd3661f..62492201 100644 --- a/src/main/java/cn/exrick/xboot/serviceimpl/UserServiceImpl.java +++ b/src/main/java/cn/exrick/xboot/serviceimpl/UserServiceImpl.java @@ -2,10 +2,12 @@ import cn.exrick.xboot.common.constant.CommonConstant; import cn.exrick.xboot.common.vo.SearchVo; +import cn.exrick.xboot.dao.DepartmentDao; import cn.exrick.xboot.dao.UserDao; import cn.exrick.xboot.dao.UserRoleDao; import cn.exrick.xboot.dao.mapper.PermissionMapper; import cn.exrick.xboot.dao.mapper.UserRoleMapper; +import cn.exrick.xboot.entity.Department; import cn.exrick.xboot.entity.Permission; import cn.exrick.xboot.entity.Role; import cn.exrick.xboot.entity.User; @@ -44,6 +46,9 @@ public class UserServiceImpl implements UserService { @Autowired private PermissionMapper permissionMapper; + @Autowired + private DepartmentDao departmentDao; + @Override public UserDao getRepository() { return userDao; @@ -55,8 +60,15 @@ public User findByUsername(String username) { List list=userDao.findByUsernameAndStatus(username, CommonConstant.USER_STATUS_NORMAL); if(list!=null&&list.size()>0){ User user = list.get(0); + // 关联部门 + if(StrUtil.isNotBlank(user.getDepartmentId())){ + Department department = departmentDao.getOne(user.getDepartmentId()); + user.setDepartmentTitle(department.getTitle()); + } + // 关联角色 List roleList = userRoleMapper.findByUserId(user.getId()); user.setRoles(roleList); + // 关联权限菜单 List permissionList = permissionMapper.findByUserId(user.getId()); user.setPermissions(permissionList); return user; @@ -64,12 +76,6 @@ public User findByUsername(String username) { return null; } - @Override - public List findByStatusAndType(Integer status, Integer type) { - - return userDao.findByStatusAndType(status, type); - } - @Override public Page findByCondition(User user, SearchVo searchVo, Pageable pageable) { @@ -81,6 +87,7 @@ public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuild Path usernameField = root.get("username"); Path mobileField = root.get("mobile"); Path emailField = root.get("email"); + Path departmentIdField = root.get("departmentId"); Path sexField=root.get("sex"); Path typeField=root.get("type"); Path statusField=root.get("status"); @@ -99,6 +106,11 @@ public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuild list.add(cb.like(emailField,'%'+user.getEmail()+'%')); } + //部门 + if(StrUtil.isNotBlank(user.getDepartmentId())){ + list.add(cb.equal(departmentIdField, user.getDepartmentId())); + } + //性别 if(user.getSex()!=null){ list.add(cb.equal(sexField, user.getSex())); @@ -124,4 +136,10 @@ public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuild } }, pageable); } + + @Override + public List findByDepartmentId(String departmentId) { + + return userDao.findByDepartmentId(departmentId); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d5a8d378..e1a2cb77 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,6 +5,8 @@ jasypt: server: port: 8888 + servlet: + context-path: / spring: # 数据源 @@ -16,6 +18,20 @@ spring: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver logSlowSql: true + # Druid StatViewServlet配置 + druid: + stat-view-servlet: + # 默认true 内置监控页面首页/druid/index.html + enabled: true + url-pattern: /druid/* + # 允许清空统计数据 + reset-enable: true + login-username: root + login-password: ENC(F4B0s6u9xcDw3V+P0qC4CA==) + # IP白名单 多个逗号分隔 + allow: + # IP黑名单 + deny: jpa: show-sql: true # 自动生成表结构 @@ -34,6 +50,10 @@ spring: data: elasticsearch: cluster-nodes: 127.0.0.1:9300 + # 定时任务 + quartz: + # 任务信息存储至数据库 + job-store-type: jdbc # 文件大小上传配置 servlet: multipart: @@ -62,6 +82,15 @@ xboot: # 日志记录方式 true使用Elasticsearch记录 false记录至数据库中 logRecord: es: false + # 七牛云配置 + qiniu: + accessKey: 你的accessKey + secretKey: 你的secretKey + bucket: 你的空间名 + domain: 你的测试域名,如http://p77xsahe9.bkt.clouddn.com/ + # mob api配置 mob官网注册申请即可 + mob: + appKey: 你的appKey # 忽略鉴权url ignored: @@ -69,6 +98,7 @@ ignored: - /xboot/permission/getMenuList/** - /xboot/user/regist - /xboot/common/** + - /druid/** - /swagger-ui.html - /swagger-resources/** - /swagger/** @@ -77,6 +107,7 @@ ignored: - /**/*.css - /**/*.png - /**/*.ico + - /test/** # Swagger界面内容配置 swagger: @@ -115,3 +146,7 @@ mybatis-plus: configuration: map-underscore-to-camel-case: true cache-enabled: false + +# 日志 +logging: + file: xboot-logs/xboot.log diff --git a/src/main/resources/mapper/PermissionMapper.xml b/src/main/resources/mapper/PermissionMapper.xml index 5ed98141..5dda29ff 100644 --- a/src/main/resources/mapper/PermissionMapper.xml +++ b/src/main/resources/mapper/PermissionMapper.xml @@ -3,7 +3,7 @@