Compare commits

..

No commits in common. "develop_xxy" and "v2.1.2" have entirely different histories.

2079 changed files with 22119 additions and 187569 deletions

View File

@ -1,79 +0,0 @@
name: Create novel-plus Maven Release with ZIPs
on:
push:
# 匹配所有以'v'开头的标签
tags:
- 'v*'
jobs:
build-and-release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
# 可选默认是 temurin也可以选择其他发行版
distribution: 'temurin'
- name: Build project with Maven
run: mvn clean install -DskipTests=true -Pcentral-repo
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# 使用 tag_name 而不是 github.ref
tag_name: ${{ github.ref_name }}
release_name: novel-plus ${{ github.ref_name }}
draft: false
prerelease: false
# 使用 action 来替代直接 curl 进行上传
- name: Upload sql.zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ github.workspace }}/novel-common/target/build/sql.zip
asset_name: sql.zip
asset_content_type: application/zip
- name: Upload novel-crawl.zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ github.workspace }}/novel-crawl/target/build/novel-crawl.zip
asset_name: novel-crawl.zip
asset_content_type: application/zip
- name: Upload novel-front.zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ github.workspace }}/novel-front/target/build/novel-front.zip
asset_name: novel-front.zip
asset_content_type: application/zip
- name: Upload novel-admin.zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ github.workspace }}/novel-admin/target/build/novel-admin.zip
asset_name: novel-admin.zip
asset_content_type: application/zip

25
.gitignore vendored
View File

@ -1,7 +1,18 @@
**/logs
**/.idea
**/cachedata
**/target
**/*.iml
**/.DS_Store
/.idea
/cachedata
/logs
/novel-common/target
/novel-front/target
/novel-front/*.iml
/novel-common/*.iml
/novel-mobile/target
/novel-mobile/*.iml
/novel-front/novel-front.iml
/novel-crawl/novel-crawl.iml
/novel-crawl/target
/novel-admin/target
/*.iml
/novel-admin/*.iml
.DS_Store
/novel-admin/cachedata
/novel-admin/logs

231
README.md
View File

@ -1,135 +1,174 @@
<p align="center">
<a href="https://www.swiftproxy.net/?code=T2WV1VT50"><img src="https://xxyopen.com/images/ad1.png" alt="AD" ></a>
<a href="https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console"><img src="https://youdoc.github.io/img/tencent.jpg" alt="AD" ></a>
</p>
<p align="center">
<a href='https://github.com/201206030/novel-plus'><img alt="Github stars" src="https://img.shields.io/github/stars/201206030/novel-plus?logo=github"></a>
<a href='https://github.com/201206030/novel-plus'><img alt="Github forks" src="https://img.shields.io/github/forks/201206030/novel-plus?logo=github"></a>
<a href='https://gitee.com/novel_dev_team/novel-plus'><img alt="Gitee stars" src="https://gitee.com/novel_dev_team/novel-plus/badge/star.svg?theme=gitee"></a>
<a href='https://gitee.com/novel_dev_team/novel-plus'><img alt="Gitee forks" src="https://gitee.com/novel_dev_team/novel-plus/badge/fork.svg?theme=gitee"></a>
</p>
[![index](./assets/热门云产品1040.100.jpg)](https://cloud.tencent.com/act/cps/redirect?redirect=1052&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console)
<p align="center">
👉 <a href='https://novel.xxyopen.com'>官网</a> | 👉 <a href='https://www.bilibili.com/video/BV1Zo4y187Mi'>项目演示</a> | 👉 <a href='https://docs.xxyopen.com/course/novelplus/1.html'>安装教程</a>
</p>
# 小说精品屋-plus
## 项目介绍
#### 演示地址
novel-plus 是一个多端PCWAP阅读功能完善的原创文学 CMS
系统由前台门户系统作家后台管理系统平台后台管理系统和爬虫管理系统等多个子系统构成包括小说推荐作品检索小说排行小说阅读小说评论会员中心作家专区等功能支持自定义多模版可拓展的多种小说内容存储方式内置数据库分表存储和
TXT 文本存储阅读主题切换多爬虫源自动采集和更新数据AI写作会员充值订阅模式新闻发布和实时统计报表
[点击前往](http://www.java2nb.com)前台门户
## 项目地址
#### 前言
- 学习版[GitHub](https://github.com/201206030/novel) [码云](https://gitee.com/novel_dev_team/novel)
[保姆级教程](https://docs.xxyopen.com)
- **应用版**[GitHub](https://github.com/201206030/novel-plus) [码云](https://gitee.com/novel_dev_team/novel-plus)
- 微服务版[GitHub](https://github.com/201206030/novel-cloud) [码云](https://gitee.com/novel_dev_team/novel-cloud)
小说精品屋-plus致力于打造一个完整的商用小说门户平台使用前建议先阅读此文档
## 项目结构
#### 项目介绍
[小说精品屋](https://github.com/201206030/fiction_house)是一个多平台web安卓app微信小程序功能完善的小说弹幕网站包含精品小说专区轻小说专区和漫画专区包括小说/漫画分类小说/漫画搜索小说/漫画排行完本小说/漫画小说/漫画评分小说/漫画在线阅读小说/漫画书架小说/漫画阅读记录小说下载小说弹幕小说/漫画自动爬取小说内容自动分享到微博邮件自动推广链接自动推送到百度搜索引擎等功能包含电脑端移动端微信小程序等多个平台现已开源web端安卓端小程序端源码
小说精品屋-plus是在小说精品屋的基础上重新进行了数据库设计代码重构和功能增强提升了程序整体的可读性和性能增加了很多商用特性主要升级如下
- [x] 数据库重新设计结构调整
- [x] 服务端代码重构MyBatis3升级为MyBatis3DynamicSql
- [x] 移动站与PC站站点分离浏览器自动识别跳转
- [x] PC站UI更新
- [x] 新闻模块
- [x] 排行榜
- [x] 小说评论模块
- [x] 阅读主题模块
- [x] 作家专区
- [x] 充值
- [x] 后台管理系统
- [x] 爬虫管理系统
#### 项目结构
```
novel-plus -- 父工程
novel-common -- 通用模块
novel-front -- 前台门户&作家后台
novel-crawl -- 爬虫
novel-admin -- 管理后台
templates -- 前端模版
novel-front -- 前台门户系统
novel-crawl -- 爬虫管理系统
novel-admin -- 后台管理系统
```
## 技术选型
#### 技术选型
Springboot+Mybatis+Mysql+ElasticSearch+Ehcache+Thymeleaf+Layui
| 技术 | 说明
|---------------------|---------------------
| Spring Boot | Spring 应用快速开发脚手架
| Spring AI | Spring 官方 AI 框架
| MyBatis | 持久层 ORM 框架
| MyBatis Dynamic SQL | Mybatis 动态 sql
| PageHelper | MyBatis 分页插件
| MyBatis Generator | 持久层代码生成插件
| Sharding-JDBC | 代码层分库分表中间件
| JJWT | JWT 登录支持
| Spring Security | 安全框架
| Apache Shiro | 安全框架
| Redis | 缓存方案
| Aliyun OSS | 阿里云对象存储服务图片存储备选方案
| Lombok | 简化对象封装工具
| Docker | 应用容器引擎
| MySQL | 数据库服务
| Thymeleaf | 模板引擎
| Layui | 前端 UI 框架
#### PC站截图
## 项目截图
1. 首页
### 绿色主题模版
![img](https://oscimg.oschina.net/oscnet/up-bbb1c7f72e183327bff754a9fa8bb75223e.png)
[![点击查看大图](https://www.xxyopen.com/images/green_novel.png)](https://www.xxyopen.com/images/green_novel.png)
[![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green3.png)
[![点击查看大图](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)](https://www.xxyopen.com/images/resource/os/novel-plus/green2.png)
2. 分类索引页
## 演示视频
![img](https://oscimg.oschina.net/oscnet/up-d0b2e03129bfae47b8bb96a491b73d383c5.png)
https://www.bilibili.com/video/BV18e41197xs
3. 搜索页
## AI 功能
![img](https://gitee.com/xiongxyang/novel-plus/raw/release_v2.1.0/assets/QQ20200520-215756.png)
novel-plus 5.x 已集成 Spring 官方最新发布的 Spring AI 框架并推出多项 AI 功能
![img](https://oscimg.oschina.net/oscnet/up-ed5f689557718924acac76bc3ebca36afcb.png)
1. v5.0.0 版本在小说章节发布页面的文本编辑器中集成了多项智能编辑功能包括 AI 扩写缩写续写及文本润色等这些功能的设计灵感来源于百家号文章编辑器中的 AI 助手
2. v5.1.0 版本在小说发布页面新增 AI 生成封面图功能若作家未上传自定义封面图系统将根据小说信息自动生成封面图
4. 排行榜
目前AI 功能仍处于实验阶段仅实现了基础的核心功能我们非常重视用户的实际使用体验和反馈未来将根据用户需求和使用情况持续优化和调整该功能如果用户反馈积极我们计划进一步开发更高级的
AI 功能例如自动生成有声小说智能情节推荐等以全面提升 novel-plus 的创作能力和用户体验
![img](https://oscimg.oschina.net/oscnet/up-78d5a68586cd92a86c669311f414508f922.png)
我们将持续关注 AI 技术的发展并致力于将其与小说创作场景深度融合为用户带来更智能更便捷的创作工具
5. 详情页
由于 DeepSeek 官方 API 目前不可用novel-plus 项目默认使用的是第三方[硅基流动](https://cloud.siliconflow.cn/i/DOgMRH9S)
提供的 API采用的 AI 模型有对话模型`deepseek-ai/DeepSeek-R1-Distill-Llama-8B`DeepSeek-R1 的蒸馏版本免费使用和生图模型`Kwai-Kolors/Kolors`快手 Kolors 团队开发的文本到图像生成模型免费使用只需注册一个硅基流动账号创建一个
API 密钥并将其添加到 novel-plus 项目 novel-front 模块的 yaml 配置文件中即可体验 novel-plus 项目的 AI 写作功能
![img](https://oscimg.oschina.net/oscnet/up-8be2495a2869f93626b0c9c1df6f329747a.png)
```yaml
spring:
ai:
openai:
image:
enabled: true
base-url: https://api.siliconflow.cn
api-key: sk-rrrupturhdofbiqzjutduuiceecpvfqlnvmgcyiaipbdikoi
options:
model: Kwai-Kolors/Kolors
response_format: URL
api-key: sk-rrrupturhdofbiqzjutduuiceecpvfqlnvmgcyiaipbdikoi
base-url: https://api.siliconflow.cn
chat:
options:
model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B
```
6. 阅读页
> novel-plus 项目默认使用的都是免费 AI 模型生成效果有限如果对生成内容有更高的要求建议选用付费的 AI 模型
![img](https://oscimg.oschina.net/oscnet/up-517c84148d2db8e11717a8bbecc57fa1be7.png)
## 增值服务
7. 用户中心
👉 [了解详情](https://novel.xxyopen.com/service.htm)
![img](https://oscimg.oschina.net/oscnet/up-805a30e7a663a3fd5cb39a7ea26bc132a01.png)
## 微信公众号
8. 充值
发布最新更新动态最新前端模版最新爬虫规则文档教程等
![img](https://oscimg.oschina.net/oscnet/up-5a601b0b3af3224d0bebcfe12fc15075d34.png)
![](https://youdoc.github.io/img/qrcode_for_gh.jpg)
![img](https://oscimg.oschina.net/oscnet/up-face25d02c07b05b2ce954cc4bf4ee6a0cc.png)
## 赞赏支持
9. 作家专区
开源项目不易若此项目能得到你的青睐那么你可以赞赏支持作者持续开发与维护
![img](https://oscimg.oschina.net/oscnet/up-30766372cc7f56480ff1d7d55198204f6ea.png)
- 服务器的费用也是一笔开销
- 编写更完备的文档教程
- 发布更多前端模版和爬虫规则
- 一杯咖啡
![img](https://oscimg.oschina.net/oscnet/up-9737995e465b86f3bee3211221f6c3b8a56.png)
![](https://s1.ax1x.com/2020/10/31/BUQJwq.png)
10. 购买
## 免责声明
![img](https://oscimg.oschina.net/oscnet/up-ce0f585efd82a9670335f118cf5897c85e9.png)
本项目提供的爬虫工具仅用于采集项目初期的测试数据请勿用于商业盈利 用户使用本系统从事任何违法违规的事情一切后果由用户自行承担作者不承担任何责任
![img](https://oscimg.oschina.net/oscnet/up-f849960f4c1303fea77d26e64fc505a7180.png)
#### 手机站截图
1. 首页
![index](https://gitee.com/xiongxyang/novel-plus/raw/release_v2.1.0/assets/QQ%E5%9B%BE%E7%89%8720191018162208.jpg)
2. 小说详情页
![微信图片_20190904181558](https://gitee.com/xiongxyang/novel-plus/raw/release_v2.1.0/assets/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190904181558.png)
3. 目录页
![QQ图片20191018161901](https://gitee.com/xiongxyang/novel-plus/raw/release_v2.1.0/assets/QQ%E5%9B%BE%E7%89%8720191108022250.png)
4. 小说阅读页
![QQ图片20191018161901](https://gitee.com/xiongxyang/novel-plus/raw/release_v2.1.0/assets/QQ%E5%9B%BE%E7%89%8720191018161901.png)
#### 爬虫管理系统截图
![img](https://gitee.com/xiongxyang/novel-plus/raw/release_v2.1.2/assets/crawl_index.png)
#### 后台管理系统截图
![img](https://oscimg.oschina.net/oscnet/up-0552343538674a22a64819834100558f39b.png)
![img](https://oscimg.oschina.net/oscnet/up-faf5dda7320674c29a1772bc0c81d74762e.png)
#### 安装步骤
##### 数据库安装
1. 安装MySQL软件
2. 修改MySQL`max_allowed_packet `配置建议100M
3. 新建数据库设置编码为utf8mb4
4. 执行sql/novel_plus.sql脚本文件
##### 爬虫管理系统安装
1. 修改novel-common模块下application-dev.yml文件中的数据库的配置
2. 修改novel-crawl模块下application.yml文件中的管理员账号密码
3. 启动程序打开浏览器默认8081端口访问
4. 选择已有或新增爬虫源支持自定义爬虫规则点击`开启`按钮开始爬取小说数据
##### 前台小说门户安装
1. 修改novel-common模块下application-dev.yml文件中的数据库的配置
2. 启动程序打开浏览器默认8080端口访问
**喜欢此项目的可以给我的GitHub和Gitee加个Star支持一下 **
#### 其他安装教程
包安装教程[点击前往](https://my.oschina.net/java2nb/blog/4272630)
宝塔安装教程非官方[点击前往](https://www.daniao.org/9166.html)
docker安装教程[点击前往](https://my.oschina.net/java2nb/blog/4271989)
#### 代码仓库
Gitee仓库地址 https://gitee.com/xiongxyang/novel-plus
GitHub仓库地址 https://github.com/201206030/novel-plus
#### QQ交流群
![mini-code](./assets/小说精品屋开源项目交流群群聊二维码.png)
#### 捐赠支持
开源项目不易若此项目能得到你的青睐可以捐赠支持作者持续开发与维护
![mini-code](./assets/jk.png)
#### 备注
精品小说屋所有相关项目均已在开源中国公开感兴趣的可进入[开源中国](https://www.oschina.net/p/fiction_house)按关键字`精品小说屋`搜索
[![index](./assets/120060.jpg)](https://www.aliyun.com/minisite/goods?userCode=uf4nasee )

BIN
assets/120060.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
assets/1573592459699.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 KiB

BIN
assets/1588548668698.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
assets/1588548784395.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
assets/1588548916980.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

BIN
assets/640x100.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
assets/IMG_1736.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
assets/IMG_1737.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
assets/android_index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

BIN
assets/baijiahao.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
assets/chapter_manager.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
assets/chapter_pub.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
assets/charset_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
assets/craw_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
assets/crawl_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/crawl_index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
assets/crawl_pic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
assets/database_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
assets/index_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/jk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
assets/jk_ali.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
assets/jk_wc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
assets/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
assets/manhua_content.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

BIN
assets/mh_content.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
assets/mh_index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

BIN
assets/mini-code.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/mini4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
assets/novel_list.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
assets/novel_pub.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
assets/oschina_tp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
assets/pc_all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

BIN
assets/pc_catalog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
assets/pc_content1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

BIN
assets/pc_content2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

BIN
assets/pc_detail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

BIN
assets/pc_index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 KiB

BIN
assets/pc_rank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

BIN
assets/pic_save_type.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
assets/qq_group.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
assets/score_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
assets/springcloud.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
assets/upload_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
assets/精品小说楼.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -1,53 +0,0 @@
mode:
# 单机模式
type: Standalone
# 元数据持久化
repository:
# 数据库持久化
type: JDBC
# 数据源配置
dataSources:
ds_1:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/novel_plus?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: test123456
ds_2:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/information_schema?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: test123456
# 规则配置
rules:
- !SINGLE
tables:
- "*.*"
- !SHARDING
tables: # 数据分片规则配置
book_content:
# 分库策略缺省表示使用默认分库策略
actualDataNodes: ds_${1}.book_content${0..9}
# 分表策略
tableStrategy:
standard:
# 分片列名称
shardingColumn: index_id
# 分片算法名称
shardingAlgorithmName: bookContentSharding
shardingAlgorithms:
bookContentSharding:
# 行表达式分片算法使用 Groovy 的表达式提供对 SQL 语句中的 = IN 的分片操作支持
type: INLINE
props:
# 分片算法的行表达式
algorithm-expression: book_content${index_id % 10}
props:
# 是否在日志中打印 SQL
sql-show: true

View File

@ -1,2 +0,0 @@
INSERT INTO `crawl_source` (`id`, `source_name`, `crawl_rule`, `source_status`, `create_time`, `update_time`) VALUES
(6, '新笔趣阁', '{\n \"bookListUrl\": \"http://www.xbiquge.la/fenlei/{catId}_{page}.html\",\n \"catIdRule\": {\n \"catId1\": \"1\",\n \"catId2\": \"2\",\n \"catId3\": \"3\",\n \"catId4\": \"4\",\n \"catId5\": \"6\",\n \"catId6\": \"5\"\n },\n \"bookIdPatten\": \"<a\\\\s+href=\\\"http://www.xbiquge.la/(\\\\d+/\\\\d+)/\\\"\\\\s+target=\\\"_blank\\\">\",\n \"pagePatten\": \"<em\\\\s+id=\\\"pagestats\\\">(\\\\d+)/\\\\d+</em>\",\n \"totalPagePatten\": \"<em\\\\s+id=\\\"pagestats\\\">\\\\d+/(\\\\d+)</em>\",\n \"bookDetailUrl\": \"http://www.xbiquge.la/{bookId}/\",\n \"bookNamePatten\": \"<h1>([^/]+)</h1>\",\n \"authorNamePatten\": \"者:([^/]+)</p>\",\n \"picUrlPatten\": \"src=\\\"(http://www.xbiquge.la/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\\"\",\n \"bookStatusRule\": {},\n \"descStart\": \"<div id=\\\"intro\\\">\",\n \"descEnd\": \"</div>\",\n \"upadateTimePatten\": \"<p>最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)</p>\",\n \"upadateTimeFormatPatten\": \"yyyy-MM-dd HH:mm:ss\",\n \"bookIndexUrl\": \"http://www.xbiquge.la/{bookId}/\",\n \"indexIdPatten\": \"<a\\\\s+href=\'/\\\\d+/\\\\d+/(\\\\d+)\\\\.html\'\\\\s+>[^/]+</a>\",\n \"indexNamePatten\": \"<a\\\\s+href=\'/\\\\d+/\\\\d+/\\\\d+\\\\.html\'\\\\s+>([^/]+)</a>\",\n \"bookContentUrl\": \"http://www.xbiquge.la/{bookId}/{indexId}.html\",\n \"contentStart\": \"<div id=\\\"content\\\">\",\n \"contentEnd\": \"<p>\"\n}', 0, '2020-05-23 22:46:58', '2020-05-23 22:46:58');

View File

@ -1,40 +0,0 @@
/*
Navicat MySQL Data Transfer
Source Server : localhost
Source Server Version : 50725
Source Host : localhost:3306
Source Database : novel_plus
Target Server Type : MYSQL
Target Server Version : 50725
File Encoding : 65001
Date: 2020-06-15 15:06:55
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for crawl_single_task
-- ----------------------------
DROP TABLE IF EXISTS `crawl_single_task`;
CREATE TABLE `crawl_single_task` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`source_id` int(11) DEFAULT NULL COMMENT '爬虫源ID',
`source_name` varchar(50) DEFAULT NULL COMMENT '爬虫源名',
`source_book_id` varchar(255) DEFAULT NULL COMMENT '源站小说ID',
`cat_id` int(11) DEFAULT NULL COMMENT '分类ID',
`book_name` varchar(50) DEFAULT NULL COMMENT '爬取的小说名',
`author_name` varchar(50) DEFAULT NULL COMMENT '爬取的小说作者名',
`task_status` tinyint(1) DEFAULT '2' COMMENT '任务状态0失败1成功2未执行',
`exc_count` tinyint(2) DEFAULT '0' COMMENT '已经执行次数最多执行5次',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='抓取单本小说任务表';
-- ----------------------------
-- Records of crawl_single_task
-- ----------------------------
INSERT INTO `crawl_single_task` VALUES ('6', '2', '百书斋', '1', '1', '1', '1', '0', '5', '2020-06-15 14:36:07');
INSERT INTO `crawl_single_task` VALUES ('7', '5', '笔趣阁', '108_108291', '1', '衍天志之不朽仙', '白衣少年丶', '1', '1', '2020-06-15 14:46:08');

View File

@ -1,27 +0,0 @@
CREATE TABLE `author_income_detail` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`author_id` bigint(20) NOT NULL COMMENT '作家ID',
`book_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '作品ID,0表示全部作品',
`income_date` date NOT NULL COMMENT '收入日期',
`income_account` int(11) NOT NULL DEFAULT '0' COMMENT '订阅总额',
`income_count` int(11) NOT NULL DEFAULT '0' COMMENT '订阅次数',
`income_number` int(11) NOT NULL DEFAULT '0' COMMENT '订阅人数',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='稿费收入明细统计表';
CREATE TABLE `author_income` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`author_id` bigint(20) NOT NULL COMMENT '作家ID',
`book_id` bigint(20) NOT NULL COMMENT '作品ID',
`income_month` date NOT NULL COMMENT '收入月份',
`pre_tax_income` bigint(20) NOT NULL DEFAULT '0' COMMENT '税前收入',
`after_tax_income` bigint(20) NOT NULL DEFAULT '0' COMMENT '税后收入',
`pay_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '支付状态0待支付1已支付',
`confirm_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '稿费确认状态0待确认1已确认',
`detail` varchar(255) DEFAULT NULL COMMENT '详情',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='稿费收入统计表';

View File

@ -1 +0,0 @@
alter table book add column `yesterday_buy` int(11) DEFAULT '0' COMMENT '昨日订阅数' after comment_count;

View File

@ -1 +0,0 @@
alter table book_index add column `book_price` int(3) DEFAULT 0 COMMENT '章节费用屋币' after `is_vip`;

View File

@ -1,32 +0,0 @@
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (246, 241, '批量删除', NULL, 'novel:news:batchRemove', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (245, 241, '删除', NULL, 'novel:news:remove', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (244, 241, '修改', NULL, 'novel:news:edit', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (243, 241, '新增', NULL, 'novel:news:add', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (242, 241, '查看', NULL, 'novel:news:detail', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (241, 234, '新闻列表', 'novel/news', 'novel:news:news', 1, 'fa', 8, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (240, 235, '批量删除', NULL, 'novel:category:batchRemove', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (239, 235, '删除', NULL, 'novel:category:remove', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (238, 235, '修改', NULL, 'novel:category:edit', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (237, 235, '新增', NULL, 'novel:category:add', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (236, 235, '查看', NULL, 'novel:category:detail', 2, NULL, 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (235, 234, '类别管理', 'novel/category', 'novel:category:category', 1, 'fa', 6, NULL, NULL);
INSERT INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`, `gmt_create`, `gmt_modified`) VALUES (234, 0, '新闻管理', '', '', 0, 'fa fa-newspaper-o', 8, NULL, NULL);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4889, 1, 246);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4890, 1, 245);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4891, 1, 244);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4892, 1, 243);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4893, 1, 242);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4899, 1, 241);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4894, 1, 240);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4895, 1, 239);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4896, 1, 238);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4897, 1, 237);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4898, 1, 236);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4900, 1, 235);
INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (4888, 1, 234);
delete from sys_menu where menu_id = 202;

View File

@ -1 +0,0 @@
alter table news add column `read_count` BIGINT NOT NULL DEFAULT '0' COMMENT '阅读量' after content;

View File

@ -1,3 +0,0 @@
alter table book_index add column storage_type varchar(10) NOT NULL DEFAULT 'db' COMMENT '存储方式' after book_price ;

View File

@ -1,121 +0,0 @@
CREATE TABLE `website_info`
(
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
name varchar(50) NOT NULL COMMENT '网站名',
domain varchar(50) NOT NULL COMMENT '网站域名',
keyword varchar(50) NOT NULL COMMENT 'SEO关键词',
description varchar(512) NOT NULL COMMENT '网站描述',
qq varchar(20) NOT NULL COMMENT '站长QQ',
logo varchar(200) NOT NULL COMMENT '网站logo图片默认',
logo_dark varchar(200) NOT NULL COMMENT '网站logo图片深色',
create_time datetime null comment '创建时间',
create_user_id bigint null comment '创建人ID',
update_time datetime null comment '更新时间',
update_user_id bigint null comment '更新人ID',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='网站信息表';
INSERT INTO website_info (id, name, domain, keyword, description, qq, logo, logo_dark, create_time, create_user_id,
update_time, update_user_id)
VALUES (1, '小说精品屋', 'www.xxyopen.com', '小说精品屋,小说,小说CMS,原创文学系统,开源小说系统,免费小说建站程序',
'小说精品屋是一个多端PCWAP阅读功能完善的原创文学CMS系统由前台门户系统作家后台管理系统平台后台管理系统爬虫管理系统等多个子系统构成支持会员充值订阅模式新闻发布和实时统计报表等功能新书自动入库老书自动更新',
'1179705413', 'https://youdoc.gitee.io/resource/images/logo/logo.png',
'https://youdoc.gitee.io/resource/images/logo/logo_white.png', null, null, null, null);
INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num, gmt_create, gmt_modified)
VALUES (300, 0, '网站管理', '', '', 0, 'fa fa-television', 6, null, null);
INSERT
INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (301, 300, '网站信息', 'novel/websiteInfo', 'novel:websiteInfo:websiteInfo', '1', 'fa', '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 300);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 301);
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (310, 300, '友情链接', 'novel/friendLink', 'novel:friendLink:friendLink', '1', 'fa', '16');
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (311, 310, '查看', null, 'novel:friendLink:detail', '2', null, '6');
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (312, 310, '新增', null, 'novel:friendLink:add', '2', null, '6');
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (313, 310, '修改', null, 'novel:friendLink:edit', '2', null, '6');
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (314, 310, '删除', null, 'novel:friendLink:remove', '2', null, '6');
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (315, 310, '批量删除', null, 'novel:friendLink:batchRemove', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 310);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 311);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 312);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 313);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 314);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 315);
INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num, gmt_create, gmt_modified)
VALUES (400, 0, '会员管理', '', '', 0, 'fa fa-vcard', 9, null, null);
INSERT
INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (401, 400, '会员列表', 'novel/user', 'novel:user:user', '1', 'fa', '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 400);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 401);
INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num, gmt_create, gmt_modified)
VALUES (500, 0, '订单管理', '', '', 0, 'fa fa-money', 19, null, null);
INSERT
INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (501, 500, '订单列表', 'novel/pay', 'novel:pay:pay', '1', 'fa', '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 500);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 501);
INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num, gmt_create, gmt_modified)
VALUES (600, 0, '小说管理', '', '', 0, 'fa fa-book', 15, null, null);
INSERT
INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (601, 600, '小说列表', 'novel/book', 'novel:book:book', '1', 'fa', '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 600);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 601);
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (602, 601, '删除', null, 'novel:book:remove', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 602);
INSERT
INTO `sys_menu`(`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (603, 600, '评论管理', 'novel/bookComment', 'novel:bookComment:bookComment', '1', 'fa', '10');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 603);
INSERT INTO `sys_menu` (menu_id, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (604, 603, '删除', null, 'novel:bookComment:remove', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 604);

View File

@ -1,51 +0,0 @@
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('轮播图', '0', 'book_rec_type', '小说推荐类型', 0, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('顶部小说栏', '1', 'book_rec_type', '小说推荐类型', 1, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('本周强推', '2', 'book_rec_type', '小说推荐类型', 2, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('热门推荐', '3', 'book_rec_type', '小说推荐类型', 3, null, null, null, null, null, '', null);
INSERT INTO sys_dict (name, value, type, description, sort, parent_id, create_by, create_date, update_by,
update_date, remarks, del_flag)
VALUES ('精品推荐', '4', 'book_rec_type', '小说推荐类型', 4, null, null, null, null, null, '', null);
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (320, '300', '小说推荐', 'novel/bookSetting', 'novel:bookSetting:bookSetting', '1', 'fa', '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (321, '320', '查看', null, 'novel:bookSetting:detail', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (322, '320', '新增', null, 'novel:bookSetting:add', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (323, '320', '修改', null, 'novel:bookSetting:edit', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (324, '320', '删除', null, 'novel:bookSetting:remove', '2', null, '6');
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (325, '320', '批量删除', null, 'novel:bookSetting:batchRemove', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 320);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 321);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 322);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 323);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 324);
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 325);
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (410, '400', '会员反馈', 'novel/userFeedback', 'novel:userFeedback:userFeedback', '1', 'fa', '16');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 410);

View File

@ -1,4 +0,0 @@
INSERT INTO `sys_menu` (`menu_id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES (305, '301', '修改', null, 'novel:websiteInfo:edit', '2', null, '6');
INSERT INTO sys_role_menu (role_id, menu_id)
VALUES (1, 305);

View File

@ -1,3 +0,0 @@
update crawl_source
set crawl_rule = replace(crawl_rule, 'ibiquge.net', 'ibiquzw.org')
where id = 16;

View File

@ -1,44 +0,0 @@
INSERT INTO crawl_source (source_name, crawl_rule, source_status, create_time, update_time)
VALUES ('香书小说网', '{
"bookListUrl": "http://www.xbiqugu.la/fenlei/{catId}_{page}.html",
"catIdRule": {
"catId1": "1",
"catId2": "2",
"catId3": "3",
"catId4": "4",
"catId5": "6",
"catId6": "5"
},
"bookIdPatten": "<a\\\\s+href=\\"http://www.xbiqugu.la/(\\\\d+/\\\\d+)/\\"\\\\s+target=\\"_blank\\">",
"pagePatten": "<em\\\\s+id=\\"pagestats\\">(\\\\d+)/\\\\d+</em>",
"totalPagePatten": "<em\\\\s+id=\\"pagestats\\">\\\\d+/(\\\\d+)</em>",
"bookDetailUrl": "http://www.xbiqugu.la/{bookId}/",
"bookNamePatten": "<h1>([^/]+)</h1>",
"authorNamePatten": "者:([^/]+)</p>",
"picUrlPatten": "src=\\"(http://www.xbiqugu.la/files/article/image/\\\\d+/\\\\d+/\\\\d+s\\\\.jpg)\\"",
"bookStatusRule": {},
"descStart": "<div id=\\"intro\\">",
"descEnd": "</div>",
"upadateTimePatten": "<p>最后更新:(\\\\d+-\\\\d+-\\\\d+\\\\s\\\\d+:\\\\d+:\\\\d+)</p>",
"upadateTimeFormatPatten": "yyyy-MM-dd HH:mm:ss",
"bookIndexUrl": "http://www.xbiqugu.la/{bookId}/",
"indexIdPatten": "<a\\\\s+href=''/\\\\d+/\\\\d+/(\\\\d+)\\\\.html''\\\\s+>[^/]+</a>",
"indexNamePatten": "<a\\\\s+href=''/\\\\d+/\\\\d+/\\\\d+\\\\.html''\\\\s+>([^/]+)</a>",
"bookContentUrl": "http://www.xbiqugu.la/{bookId}/{indexId}.html",
"contentStart": "<div id=\\"content\\">",
"contentEnd": "<p>",
"filterContent":"<div\\\\s+id=\\"content_tip\\">\\\\s*<b>([^/]+)</b>\\\\s*</div>"
}', 0, '2024-06-01 10:11:39', '2024-06-01 10:11:39');
update crawl_source
set crawl_rule = replace(crawl_rule, 'ibiquzw.org', 'biquxs.info')
where id = 16;
delete
from sys_menu
where menu_id = 104;
delete
from sys_menu
where menu_id = 57;

View File

@ -1,2 +0,0 @@
FROM mysql:8.0
COPY novel_plus.sql /docker-entrypoint-initdb.d/init.sql

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
1. novel_plus.sql 为全量 sql 文件yyyyMMdd.sql 为增量 sql 文件
2. 第一次安装只需要执行 novel_plus.sql 文件即可
3. 后续版本升级需要根据上次代码版本的时间执行该日期之后的增量 sql 文件简单来说就是 sql 文件夹中相较于上次多出来的 sql 文件

View File

@ -0,0 +1,8 @@
2020-05-13 21:52:00,972 INFO (StartupInfoLogger.java:50)- Starting TestDemo on USER-20180729KA with PID 3532 (started by Administrator in E:\baseprojectparent\novel-plus\novel-admin)
2020-05-13 21:52:01,113 DEBUG (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.1.RELEASE, Spring v5.0.5.RELEASE
2020-05-13 21:52:01,131 INFO (SpringApplication.java:663)- The following profiles are active: dev
2020-05-13 21:52:54,469 DEBUG (ApplicationContextRegister.java:29)- ApplicationContext registed-->org.springframework.web.context.support.GenericWebApplicationContext@5b529706: startup date [Wed May 13 21:52:01 CST 2020]; root of context hierarchy
2020-05-13 21:53:49,622 INFO (StartupInfoLogger.java:59)- Started TestDemo in 114.268 seconds (JVM running for 124.957)
2020-05-18 09:48:03,219 INFO (StartupInfoLogger.java:50)- Starting TestDemo on DESKTOP-CPCLUI6 with PID 13172 (started by 11797 in D:\gitee\novel-plus\novel-admin)
2020-05-18 09:48:03,223 DEBUG (StartupInfoLogger.java:53)- Running with Spring Boot v2.0.1.RELEASE, Spring v5.0.5.RELEASE
2020-05-18 09:48:03,227 INFO (SpringApplication.java:663)- The following profiles are active: dev

View File

@ -5,7 +5,7 @@
<groupId>com.java2nb</groupId>
<artifactId>novel-admin</artifactId>
<version>5.1.0</version>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>novel-admin</name>
@ -14,14 +14,16 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<version>2.0.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<velocity.version>1.7</velocity.version>
<shardingsphere-jdbc.version>5.5.1</shardingsphere-jdbc.version>
<activiti.version>5.22.0</activiti.version>
</properties>
<dependencies>
@ -56,16 +58,16 @@
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<!-- 请求参数校验相关 -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!--mybatis -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
@ -73,7 +75,18 @@
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!--druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.28</version>
</dependency>
<!--commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
@ -82,18 +95,18 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.9.0</version>
<version>2.5</version>
</dependency>
<!--shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.11.0</version>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.11.0</version>
<version>1.3.2</version>
</dependency>
<!-- shiro ehcache -->
<dependency>
@ -105,7 +118,7 @@
<artifactId>ehcache-core</artifactId>
</exclusion>
</exclusions>
<version>1.11.0</version>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
@ -116,19 +129,17 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
<version>1.2.31</version>
</dependency>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
<exclusions>
<exclusion>
<artifactId>commons-lang</artifactId>
<groupId>commons-lang</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
@ -157,12 +168,6 @@
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
@ -192,29 +197,16 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.4</version>
<exclusions>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- ShardingSphere-JDBC -->
<!-- ehchache -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc</artifactId>
<version>${shardingsphere-jdbc.version}</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!--war包部署需要-->
@ -236,131 +228,41 @@
<!--<scope>provided</scope>-->
<!--</dependency>-->
</dependencies>
<!-- <build>
<plugins>
&lt;!&ndash;<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>&ndash;&gt;
&lt;!&ndash;SpringBoot项目默认使用spring-boot-maven-plugin要打成被其他项目引用的jar包需要更换此插件&ndash;&gt;
&lt;!&ndash; <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>&ndash;&gt;
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>-->
<build>
<plugins>
<!--<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>-->
<!--SpringBoot项目默认使用spring-boot-maven-plugin要打成被其他项目引用的jar包需要更换此插件-->
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<!-- 文件夹 -->
<copy todir="${project.build.directory}/build/config" overwrite="true">
<fileset dir="${basedir}/src/main/build/config">
<include name="*.*"/>
</fileset>
</copy>
<copy file="${project.build.directory}/${project.artifactId}-${project.version}.jar"
tofile="${project.build.directory}/build/${project.artifactId}.jar"/>
<fixcrlf srcdir="${basedir}/src/main/build/scripts" eol="unix"/>
<copy todir="${project.build.directory}/build/bin">
<fileset dir="${basedir}/src/main/build/scripts">
<include name="*.sh"/>
<include name="*.txt"/>
<include name="*.bat"/>
</fileset>
</copy>
<zip destfile='${project.build.directory}/build/${project.artifactId}.zip'>
<zipfileset filemode="755" dir='${project.build.directory}/build/'/>
</zip>
<copy file="${basedir}/src/main/build/docker/Dockerfile"
tofile="${project.build.directory}/build/Dockerfile"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<!--<distributionManagement>
<repository>
<id>ali</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>nexus_release</id>
<name>release</name>
<url>http://47.106.243.172:8081/nexus/content/repositories/releases/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>ali-plugin</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<!-- 定义一个用于切换到中央仓库的profile -->
<id>central-repo</id>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central-plugin</id>
<url>https://repo.maven.apache.org/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<snapshotRepository>
<id>nexus_snapshots</id>
<name>snapshots</name>
<url>http://47.106.243.172:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>-->
</project>

View File

@ -1,9 +0,0 @@
#端口号
server:
port: 8088
spring:
redis:
host: 127.0.0.1
port: 6379
password: test123456

View File

@ -1,47 +0,0 @@
mode:
# 单机模式
type: Standalone
# 元数据持久化
repository:
# 数据库持久化
type: JDBC
# 数据源配置
dataSources:
ds_1:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/novel_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: test123456
# 规则配置
rules:
- !SINGLE
tables:
- "*.*"
- !SHARDING
tables: # 数据分片规则配置
book_content:
# 分库策略缺省表示使用默认分库策略
actualDataNodes: ds_${1}.book_content${0..9}
# 分表策略
tableStrategy:
standard:
# 分片列名称
shardingColumn: index_id
# 分片算法名称
shardingAlgorithmName: bookContentSharding
shardingAlgorithms:
bookContentSharding:
# 行表达式分片算法使用 Groovy 的表达式提供对 SQL 语句中的 = IN 的分片操作支持
type: INLINE
props:
# 分片算法的行表达式
algorithm-expression: book_content${index_id % 10}
props:
# 是否在日志中打印 SQL
sql-show: true

View File

@ -1,9 +0,0 @@
FROM openjdk:8
ADD novel-admin.jar /root
ENV dburl=""
ENV username=""
ENV password=""
ENV redishost = ""
ENV redisport = ""
ENV redispwd = ""
ENTRYPOINT ["sh","-c","java -Dspring.datasource.url=${dburl} -Dspring.datasource.username=${username} -Dspring.datasource.password=${password} -Dspring.redis.host=${redishost} -Dspring.redis.port=${redisport} -Dspring.redis.password=${redispwd} -jar /root/novel-admin.jar"]

View File

@ -1,94 +0,0 @@
#!/bin/sh
APP_NAME=novel-admin
JAR_NAME=$APP_NAME\.jar
#PID 代表是PID文件
PID=$APP_NAME\.pid
#使用说明,用来提示输入参数
usage() {
echo "Usage: ./novel-admin.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
is_exist(){
pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `
#如果不存在返回1存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> 小说精品屋后台正在运行 PID = ${pid} <<<"
else
echo ">>> 小说精品屋后台开始启动 <<<"
nohup java -jar -Dspring.profiles.active=prod $JAR_NAME >/dev/null 2>&1 &
sleep 20
echo $! > $PID
echo ">>> 小说精品屋后台启动完成 PID = $! <<<"
status
fi
}
#停止方法
stop(){
#is_exist
pidf=$(cat $PID)
#echo "$pidf"
echo ">>> 小说精品屋后台 PID = $pidf 开始停止 <<<"
kill $pidf
rm -rf $PID
sleep 2
is_exist
if [ $? -eq "0" ]; then
echo ">>> 小说精品屋后台 PID = $pid 开始强制停止 <<<"
kill -9 $pid
sleep 2
status
else
status
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> 小说精品屋后台正在运行 PID = ${pid} <<<"
else
echo ">>> 小说精品屋后台没有运行 <<<"
fi
}
#重启
restart(){
stop
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac
exit 0

View File

@ -1,47 +1,25 @@
package com.java2nb;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.net.InetAddress;
import java.sql.Connection;
//关闭SpringSecurity的功能
@EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
@EnableTransactionManagement
@ServletComponentScan
@MapperScan("com.java2nb.*.dao")
@SpringBootApplication(exclude = {
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
@SpringBootApplication
@EnableCaching
@Slf4j
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx, DataSource dataSource) {
return args -> {
log.info("创建连接池...");
try (Connection connection = dataSource.getConnection()) {
log.info("连接池已创建.");
log.info("数据库:{}", connection.getMetaData().getDatabaseProductName());
log.info("数据库版本:{}", connection.getMetaData().getDatabaseProductVersion());
}
log.info("项目启动啦,访问路径:{}",
"http://" + InetAddress.getLocalHost().getHostAddress() + ":" + ctx.getEnvironment()
.getProperty("server.port"));
};
}
}

View File

@ -1,16 +1,19 @@
package com.java2nb.common.aspect;
import com.java2nb.common.utils.IPUtils;
import com.java2nb.common.utils.HttpContextUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.net.util.IPAddressUtil;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
@Aspect
@ -34,10 +37,11 @@ public class WebLogAspect {
logger.info("请求地址 : " + request.getRequestURL().toString());
logger.info("HTTP METHOD : " + request.getMethod());
// 获取真实的ip地址
logger.info("IP : " + IPUtils.getIpAddr(request));
//logger.info("IP : " + IPAddressUtil.getClientIpAddress(request));
logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."
+ joinPoint.getSignature().getName());
+ joinPoint.getSignature().getName());
logger.info("参数 : " + Arrays.toString(joinPoint.getArgs()));
// loggger.info("参数 : " + joinPoint.getArgs());
}

View File

@ -1,73 +0,0 @@
package com.java2nb.common.config;
/**
* @author 11797
*/
public interface CacheKey {
/**
* 首页小说设置
*/
String INDEX_BOOK_SETTINGS_KEY = "indexBookSettingsKey";
/**
* 首页新闻
*/
String INDEX_NEWS_KEY = "indexNewsKey";
/**
* 首页点击榜单
*/
String INDEX_CLICK_BANK_BOOK_KEY = "indexClickBankBookKey";
/**
* 首页友情链接
*/
String INDEX_LINK_KEY = "indexLinkKey";
/**
* 首页新书榜单
*/
String INDEX_NEW_BOOK_KEY = "indexNewBookKey";
/**
* 首页更新榜单
*/
String INDEX_UPDATE_BOOK_KEY = "indexUpdateBookKey";
/**
* 模板目录保存key
*/
String TEMPLATE_DIR_KEY = "templateDirKey";
;
/**
* 正在运行的爬虫线程存储KEY前缀
*/
String RUNNING_CRAWL_THREAD_KEY_PREFIX = "runningCrawlTreadDataKeyPrefix";
/**
* 上一次搜索引擎更新的时间
*/
String ES_LAST_UPDATE_TIME = "esLastUpdateTime";
/**
* 搜索引擎转换锁
*/
String ES_TRANS_LOCK = "esTransLock";
/**
* 上一次搜索引擎是否更新过小说点击量
*/
String ES_IS_UPDATE_VISIT = "esIsUpdateVisit";
/**
* 累积的小说点击量
*/
String BOOK_ADD_VISIT_COUNT = "bookAddVisitCount";
/**
* 测试爬虫规则缓存
*/
String BOOK_TEST_PARSE = "testParse";
}

View File

@ -1,7 +1,6 @@
package com.java2nb.common.config;
public class Constant {
//演示系统账户
public static String DEMO_ACCOUNT = "test";
//自动去除表前缀
@ -17,11 +16,9 @@ public class Constant {
//部门根节点id
public static Long DEPT_ROOT_ID = 0l;
//缓存方式
public static String CACHE_TYPE_REDIS = "redis";
public static String CACHE_TYPE_REDIS ="redis";
public static String LOG_ERROR = "error";
public static final String UPLOAD_FILES_PREFIX = "/files/";
}

View File

@ -0,0 +1,132 @@
package com.java2nb.common.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* Created by PrimaryKey on 17/2/4.
*/
@SuppressWarnings("AlibabaRemoveCommentedCode")
@Configuration
public class DruidDBConfig {
private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean(initMethod = "init", destroyMethod = "close") //声明其为Bean实例
@Primary //在同样的DataSource中首先使用被标注的DataSource
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*");
reg.addInitParameter("allow", ""); //白名单
return reg;
}
@Bean public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("profileEnable", "true");
filterRegistrationBean.addInitParameter("principalCookieName","USER_COOKIE");
filterRegistrationBean.addInitParameter("principalSessionName","USER_SESSION");
filterRegistrationBean.addInitParameter("DruidWebStatFilter","/*");
return filterRegistrationBean;
}
}

View File

@ -0,0 +1,82 @@
package com.java2nb.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}

View File

@ -5,8 +5,11 @@ import com.java2nb.common.redis.shiro.RedisCacheManager;
import com.java2nb.common.redis.shiro.RedisManager;
import com.java2nb.common.redis.shiro.RedisSessionDAO;
import com.java2nb.system.shiro.UserRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
@ -26,7 +29,6 @@ import java.util.LinkedHashMap;
*/
@Configuration
public class ShiroConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
@ -36,6 +38,9 @@ public class ShiroConfig {
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.cache.type}")
private String cacheType ;
@Value("${server.session-timeout}")
private int tomcatTimeout;
@ -62,17 +67,17 @@ public class ShiroConfig {
shiroFilterFactoryBean.setSuccessUrl("/index");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/getVerify", "anon");
filterChainDefinitionMap.put("/login","anon");
filterChainDefinitionMap.put("/getVerify","anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/layuimini/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/upload/**", "anon");
filterChainDefinitionMap.put(Constant.UPLOAD_FILES_PREFIX + "**", "anon");
filterChainDefinitionMap.put("/files/**", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/blog", "anon");
filterChainDefinitionMap.put("/blog/open/**", "anon");
@ -88,7 +93,11 @@ public class ShiroConfig {
//设置realm.
securityManager.setRealm(userRealm());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(rediscacheManager());
if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) {
securityManager.setCacheManager(rediscacheManager());
} else {
securityManager.setCacheManager(ehCacheManager());
}
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@ -100,7 +109,8 @@ public class ShiroConfig {
}
/**
* 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
*
* @param securityManager
* @return
@ -129,7 +139,8 @@ public class ShiroConfig {
}
/**
* cacheManager 缓存 redis实现 使用的是shiro-redis开源插件
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*
* @return
*/
@ -141,7 +152,8 @@ public class ShiroConfig {
/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis 使用的是shiro-redis开源插件
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* 使用的是shiro-redis开源插件
*/
@Bean
public RedisSessionDAO redisSessionDAO() {
@ -152,7 +164,11 @@ public class ShiroConfig {
@Bean
public SessionDAO sessionDAO() {
return redisSessionDAO();
if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) {
return redisSessionDAO();
} else {
return new MemorySessionDAO();
}
}
/**
@ -169,4 +185,19 @@ public class ShiroConfig {
return sessionManager;
}
@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManager(cacheManager());
return em;
}
@Bean("cacheManager2")
CacheManager cacheManager(){
return CacheManager.create();
}
}

View File

@ -0,0 +1,48 @@
package com.java2nb.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* ${DESCRIPTION}
*
* @author xiongxy
* @create 2019-11-02 23:53
*/
@EnableSwagger2
@Configuration
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//为当前包路径
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
//构建 api文档的详细信息函数
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//页面标题
.title("功能测试")
//创建人
.contact(new Contact("xiongxy", "1179705413@qq.com", "1179705413@qq.com"))
//版本号
.version("1.0")
//描述
.description("API 描述")
.build();
}
}

View File

@ -7,14 +7,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@Component
class WebConfigurer extends WebMvcConfigurerAdapter {
@Autowired
@Autowired
JnConfig jnConfig;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(Constant.UPLOAD_FILES_PREFIX + "**")
.addResourceLocations("file:///" + jnConfig.getUploadPath());
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**").addResourceLocations("file:///"+ jnConfig.getUploadPath());
}
}

View File

@ -1,10 +1,12 @@
package com.java2nb.common.controller;
import com.java2nb.common.config.Constant;
import com.java2nb.common.config.JnConfig;
import com.java2nb.common.domain.FileDO;
import com.java2nb.common.service.FileService;
import com.java2nb.common.utils.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -12,11 +14,7 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
@ -34,167 +32,165 @@ import java.util.Map;
@RequestMapping("/common/sysFile")
public class FileController extends BaseController {
@Autowired
private FileService sysFileService;
@Autowired
private FileService sysFileService;
@Autowired
private JnConfig jnConfig;
@Autowired
private JnConfig jnConfig;
@GetMapping()
@RequiresPermissions("common:sysFile:sysFile")
String sysFile(Model model) {
Map<String, Object> params = new HashMap<>(16);
return "common/file/file";
}
@GetMapping()
@RequiresPermissions("common:sysFile:sysFile")
String sysFile(Model model) {
Map<String, Object> params = new HashMap<>(16);
return "common/file/file";
}
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("common:sysFile:sysFile")
public PageBean list(@RequestParam Map<String, Object> params) {
// 查询列表数据
Query query = new Query(params);
List<FileDO> sysFileList = sysFileService.list(query);
int total = sysFileService.count(query);
PageBean pageBean = new PageBean(sysFileList, total);
return pageBean;
}
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("common:sysFile:sysFile")
public PageBean list(@RequestParam Map<String, Object> params) {
// 查询列表数据
Query query = new Query(params);
List<FileDO> sysFileList = sysFileService.list(query);
int total = sysFileService.count(query);
PageBean pageBean = new PageBean(sysFileList, total);
return pageBean;
}
@GetMapping("/add")
// @RequiresPermissions("common:bComments")
String add() {
return "common/sysFile/add";
}
@GetMapping("/add")
// @RequiresPermissions("common:bComments")
String add() {
return "common/sysFile/add";
}
@GetMapping("/edit")
// @RequiresPermissions("common:bComments")
String edit(Long id, Model model) {
FileDO sysFile = sysFileService.get(id);
model.addAttribute("sysFile", sysFile);
return "common/sysFile/edit";
}
@GetMapping("/edit")
// @RequiresPermissions("common:bComments")
String edit(Long id, Model model) {
FileDO sysFile = sysFileService.get(id);
model.addAttribute("sysFile", sysFile);
return "common/sysFile/edit";
}
/**
* 信息
*/
@RequestMapping("/info/{id}")
@RequiresPermissions("common:info")
public R info(@PathVariable("id") Long id) {
FileDO sysFile = sysFileService.get(id);
return R.ok().put("sysFile", sysFile);
}
/**
* 信息
*/
@RequestMapping("/info/{id}")
@RequiresPermissions("common:info")
public R info(@PathVariable("id") Long id) {
FileDO sysFile = sysFileService.get(id);
return R.ok().put("sysFile", sysFile);
}
/**
* 保存
*/
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("common:save")
public R save(FileDO sysFile) {
if (sysFileService.save(sysFile) > 0) {
return R.ok();
}
return R.error();
}
/**
* 保存
*/
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("common:save")
public R save(FileDO sysFile) {
if (sysFileService.save(sysFile) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@RequestMapping("/update")
@RequiresPermissions("common:update")
public R update(@RequestBody FileDO sysFile) {
sysFileService.update(sysFile);
/**
* 修改
*/
@RequestMapping("/update")
@RequiresPermissions("common:update")
public R update(@RequestBody FileDO sysFile) {
sysFileService.update(sysFile);
return R.ok();
}
return R.ok();
}
/**
* 删除
*/
@PostMapping("/remove")
@ResponseBody
// @RequiresPermissions("common:remove")
public R remove(Long id, HttpServletRequest request) {
if ("test".equals(getUsername())) {
return R.error(1, "演示系统不允许修改,完整体验请部署程序");
}
String fileName =
jnConfig.getUploadPath() + sysFileService.get(id).getUrl().replace(Constant.UPLOAD_FILES_PREFIX, "");
if (sysFileService.remove(id) > 0) {
boolean b = FileUtil.deleteFile(fileName);
if (!b) {
return R.error("数据库记录删除成功,文件删除失败");
}
return R.ok();
} else {
return R.error();
}
}
/**
* 删除
*/
@PostMapping("/remove")
@ResponseBody
// @RequiresPermissions("common:remove")
public R remove(Long id, HttpServletRequest request) {
if ("test".equals(getUsername())) {
return R.error(1, "演示系统不允许修改,完整体验请部署程序");
}
String fileName = jnConfig.getUploadPath() + sysFileService.get(id).getUrl().replace("/files/", "");
if (sysFileService.remove(id) > 0) {
boolean b = FileUtil.deleteFile(fileName);
if (!b) {
return R.error("数据库记录删除成功,文件删除失败");
}
return R.ok();
} else {
return R.error();
}
}
/**
* 删除
*/
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("common:remove")
public R remove(@RequestParam("ids[]") Long[] ids) {
if ("test".equals(getUsername())) {
return R.error(1, "演示系统不允许修改,完整体验请部署程序");
}
sysFileService.batchRemove(ids);
return R.ok();
}
/**
* 删除
*/
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("common:remove")
public R remove(@RequestParam("ids[]") Long[] ids) {
if ("test".equals(getUsername())) {
return R.error(1, "演示系统不允许修改,完整体验请部署程序");
}
sysFileService.batchRemove(ids);
return R.ok();
}
@ResponseBody
@PostMapping("/upload")
R upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
if ("test".equals(getUsername())) {
return R.error(1, "演示系统不允许修改,完整体验请部署程序");
}
Date date = new Date();
String year = DateUtils.format(date, DateUtils.YEAR_PATTERN);
String month = DateUtils.format(date, DateUtils.MONTH_PATTERN);
String day = DateUtils.format(date, DateUtils.DAY_PATTERN);
@ResponseBody
@PostMapping("/upload")
R upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
if ("test".equals(getUsername())) {
return R.error(1, "演示系统不允许修改,完整体验请部署程序");
}
Date date = new Date();
String year = DateUtils.format(date,DateUtils.YEAR_PATTERN);
String month = DateUtils.format(date,DateUtils.MONTH_PATTERN);
String day = DateUtils.format(date,DateUtils.DAY_PATTERN);
String fileName = file.getOriginalFilename();
String fileDir = year + "/" + month + "/" + day + "/";
fileName = FileUtil.renameToUUID(fileName);
FileDO sysFile = new FileDO(FileType.fileType(fileName), Constant.UPLOAD_FILES_PREFIX + fileDir + fileName,
date);
try {
FileUtil.uploadFile(file.getBytes(), jnConfig.getUploadPath() + fileDir, fileName);
} catch (Exception e) {
return R.error();
}
String fileName = file.getOriginalFilename();
String fileDir = year+"/"+month+"/"+day + "/";
fileName = FileUtil.renameToUUID(fileName);
FileDO sysFile = new FileDO(FileType.fileType(fileName), "/files/" + fileDir + fileName, date);
try {
FileUtil.uploadFile(file.getBytes(), jnConfig.getUploadPath()+fileDir, fileName);
} catch (Exception e) {
return R.error();
}
if (sysFileService.save(sysFile) > 0) {
return R.ok().put("fileName", sysFile.getUrl());
}
return R.error();
}
if (sysFileService.save(sysFile) > 0) {
return R.ok().put("fileName",sysFile.getUrl());
}
return R.error();
}
/**
* 文件下载
*/
@RequestMapping(value = "/download")
public void fileDownload(String filePath, String fileName, HttpServletResponse resp) throws Exception {
String realFilePath = jnConfig.getUploadPath() + filePath;
InputStream in = new FileInputStream(realFilePath);
//设置响应头对文件进行url编码
fileName = URLEncoder.encode(fileName, "UTF-8");
resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
/**
* 文件下载
*/
@RequestMapping(value = "/download")
public void fileDownload(String filePath,String fileName, HttpServletResponse resp) throws Exception {
String realFilePath = jnConfig.getUploadPath() + filePath;
InputStream in = new FileInputStream(realFilePath);
//设置响应头对文件进行url编码
fileName = URLEncoder.encode(fileName, "UTF-8");
resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
resp.setContentLength(in.available());
resp.setContentLength(in.available());
OutputStream out = resp.getOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
out.flush();
out.close();
in.close();
}
OutputStream out = resp.getOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
out.flush();
out.close();
in.close();
}
}

View File

@ -1,33 +1,28 @@
package com.java2nb.common.dao;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
public interface GeneratorMapper {
@Select("select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables"
+ " where table_schema = (select database()) and table_name like concat('%',#{tableName},'%')")
List<Map<String, Object>> list(@Param("tableName") String tableName);
@Select(
"select table_name tableName, engine, table_comment tableComment, create_time createTime from tables"
+ " where table_schema = 'novel_plus' and table_name like concat('%',#{tableName},'%')")
List<Map<String, Object>> list(@Param("tableName") String tableName);
@Select("select count(*) from information_schema.tables where table_schema = (select database())")
int count(Map<String, Object> map);
@Select("select count(*) from tables where table_schema = 'novel_plus'")
int count(Map<String, Object> map);
@Select("select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables \r\n"
+ " where table_schema = (select database()) and table_name = #{tableName}")
Map<String, String> get(String tableName);
@Select(
"select table_name tableName, engine, table_comment tableComment, create_time createTime from tables \r\n"
+ " where table_schema = 'novel_plus' and table_name = #{tableName}")
Map<String, String> get(String tableName);
@Select("select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns\r\n"
+ " where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position")
List<Map<String, String>> listColumns(String tableName);
@Select(
"select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from columns\r\n"
+ " where table_name = #{tableName} and table_schema = 'novel_plus' order by ordinal_position")
List<Map<String, String>> listColumns(String tableName);
@Select(
"select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from columns\r\n"
+ " where table_name = #{tableName} and table_schema = 'novel_plus' and column_key = 'PRI' limit 1")
@Select("select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns\r\n"
+ " where table_name = #{tableName} and table_schema = (select database()) and column_key = 'PRI' limit 1")
Map<String, String> getPriColumn(String tableName);
}

View File

@ -3,7 +3,7 @@ package com.java2nb.common.domain;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
/**
@ -14,259 +14,208 @@ import java.util.Objects;
* @date 2019-09-29 18:28:07
*/
public class DictDO implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
//编号
private Long id;
//标签名
private String name;
//数据值
private String value;
//类型
private String type;
//描述
private String description;
//排序升序
private BigDecimal sort;
//父级编号
private Long parentId;
//创建者
private Integer createBy;
//创建时间
private Date createDate;
//更新者
private Long updateBy;
//更新时间
private Date updateDate;
//备注信息
private String remarks;
//删除标记
private String delFlag;
//编号
private Long id;
//标签名
private String name;
//数据值
private String value;
//类型
private String type;
//描述
private String description;
//排序升序
private BigDecimal sort;
//父级编号
private Long parentId;
//创建者
private Integer createBy;
//创建时间
private Date createDate;
//更新者
private Long updateBy;
//更新时间
private Date updateDate;
//备注信息
private String remarks;
//删除标记
private String delFlag;
/**
* 设置编号
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取编号
*/
public Long getId() {
return id;
}
/**
* 设置标签名
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取标签名
*/
public String getName() {
return name;
}
/**
* 设置数据值
*/
public void setValue(String value) {
this.value = value;
}
/**
* 获取数据值
*/
public String getValue() {
return value;
}
/**
* 设置类型
*/
public void setType(String type) {
this.type = type;
}
/**
* 获取类型
*/
public String getType() {
return type;
}
/**
* 设置描述
*/
public void setDescription(String description) {
this.description = description;
}
/**
* 获取描述
*/
public String getDescription() {
return description;
}
/**
* 设置排序升序
*/
public void setSort(BigDecimal sort) {
this.sort = sort;
}
/**
* 获取排序升序
*/
public BigDecimal getSort() {
return sort;
}
/**
* 设置父级编号
*/
public void setParentId(Long parentId) {
this.parentId = parentId;
}
/**
* 获取父级编号
*/
public Long getParentId() {
return parentId;
}
/**
* 设置创建者
*/
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
/**
* 获取创建者
*/
public Integer getCreateBy() {
return createBy;
}
/**
* 设置创建时间
*/
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
/**
* 获取创建时间
*/
public Date getCreateDate() {
return createDate;
}
/**
* 设置更新者
*/
public void setUpdateBy(Long updateBy) {
this.updateBy = updateBy;
}
/**
* 获取更新者
*/
public Long getUpdateBy() {
return updateBy;
}
/**
* 设置更新时间
*/
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
/**
* 获取更新时间
*/
public Date getUpdateDate() {
return updateDate;
}
/**
* 设置备注信息
*/
public void setRemarks(String remarks) {
this.remarks = remarks;
}
/**
* 获取备注信息
*/
public String getRemarks() {
return remarks;
}
/**
* 设置删除标记
*/
public void setDelFlag(String delFlag) {
this.delFlag = delFlag;
}
/**
* 获取删除标记
*/
public String getDelFlag() {
return delFlag;
}
/**
* 设置编号
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取编号
*/
public Long getId() {
return id;
}
/**
* 设置标签名
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取标签名
*/
public String getName() {
return name;
}
/**
* 设置数据值
*/
public void setValue(String value) {
this.value = value;
}
/**
* 获取数据值
*/
public String getValue() {
return value;
}
/**
* 设置类型
*/
public void setType(String type) {
this.type = type;
}
/**
* 获取类型
*/
public String getType() {
return type;
}
/**
* 设置描述
*/
public void setDescription(String description) {
this.description = description;
}
/**
* 获取描述
*/
public String getDescription() {
return description;
}
/**
* 设置排序升序
*/
public void setSort(BigDecimal sort) {
this.sort = sort;
}
/**
* 获取排序升序
*/
public BigDecimal getSort() {
return sort;
}
/**
* 设置父级编号
*/
public void setParentId(Long parentId) {
this.parentId = parentId;
}
/**
* 获取父级编号
*/
public Long getParentId() {
return parentId;
}
/**
* 设置创建者
*/
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
/**
* 获取创建者
*/
public Integer getCreateBy() {
return createBy;
}
/**
* 设置创建时间
*/
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
/**
* 获取创建时间
*/
public Date getCreateDate() {
return createDate;
}
/**
* 设置更新者
*/
public void setUpdateBy(Long updateBy) {
this.updateBy = updateBy;
}
/**
* 获取更新者
*/
public Long getUpdateBy() {
return updateBy;
}
/**
* 设置更新时间
*/
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
/**
* 获取更新时间
*/
public Date getUpdateDate() {
return updateDate;
}
/**
* 设置备注信息
*/
public void setRemarks(String remarks) {
this.remarks = remarks;
}
/**
* 获取备注信息
*/
public String getRemarks() {
return remarks;
}
/**
* 设置删除标记
*/
public void setDelFlag(String delFlag) {
this.delFlag = delFlag;
}
/**
* 获取删除标记
*/
public String getDelFlag() {
return delFlag;
}
@Override
public String toString() {
return "DictDO{" +
"id=" + id +
", name='" + name + '\'' +
", value='" + value + '\'' +
", type='" + type + '\'' +
", description='" + description + '\'' +
", sort=" + sort +
", parentId=" + parentId +
", createBy=" + createBy +
", createDate=" + createDate +
", updateBy=" + updateBy +
", updateDate=" + updateDate +
", remarks='" + remarks + '\'' +
", delFlag='" + delFlag + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DictDO dictDO = (DictDO) o;
return Objects.equals(id, dictDO.id) && Objects.equals(name, dictDO.name)
&& Objects.equals(value, dictDO.value) && Objects.equals(type, dictDO.type)
&& Objects.equals(description, dictDO.description) && Objects.equals(sort, dictDO.sort)
&& Objects.equals(parentId, dictDO.parentId) && Objects.equals(createBy, dictDO.createBy)
&& Objects.equals(createDate, dictDO.createDate) && Objects.equals(updateBy,
dictDO.updateBy) && Objects.equals(updateDate, dictDO.updateDate) && Objects.equals(remarks,
dictDO.remarks) && Objects.equals(delFlag, dictDO.delFlag);
}
@Override
public int hashCode() {
return Objects.hash(id, name, value, type, description, sort, parentId, createBy, createDate, updateBy,
updateDate,
remarks, delFlag);
}
@Override
public String toString() {
return "DictDO{" +
"id=" + id +
", name='" + name + '\'' +
", value='" + value + '\'' +
", type='" + type + '\'' +
", description='" + description + '\'' +
", sort=" + sort +
", parentId=" + parentId +
", createBy=" + createBy +
", createDate=" + createDate +
", updateBy=" + updateBy +
", updateDate=" + updateDate +
", remarks='" + remarks + '\'' +
", delFlag='" + delFlag + '\'' +
'}';
}
}

View File

@ -2,27 +2,32 @@ package com.java2nb.common.exception;
import com.java2nb.common.utils.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@RestController
public class MainsiteErrorController implements ErrorController {
private Logger logger = LoggerFactory.getLogger(getClass());
private static final String ERROR_PATH = "/error";
@Autowired
ErrorAttributes errorAttributes;
@RequestMapping(
value = {ERROR_PATH},
produces = {"text/html"}
value = {ERROR_PATH},
produces = {"text/html"}
)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
int code = response.getStatus();
@ -53,4 +58,9 @@ public class MainsiteErrorController implements ErrorController {
}
}
@Override
public String getErrorPath() {
// TODO Auto-generated method stub
return ERROR_PATH;
}
}

View File

@ -1,8 +1,5 @@
package com.java2nb.common.service.impl;
import com.java2nb.common.dao.DictDao;
import com.java2nb.common.domain.DictDO;
import com.java2nb.common.service.DictService;
import com.java2nb.common.utils.StringUtils;
import com.java2nb.system.domain.UserDO;
import org.springframework.beans.factory.annotation.Autowired;
@ -12,12 +9,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import com.java2nb.common.dao.DictDao;
import com.java2nb.common.domain.DictDO;
import com.java2nb.common.service.DictService;
@Service
public class DictServiceImpl implements DictService {
@Autowired
private DictDao dictDao;
@ -59,7 +58,7 @@ public class DictServiceImpl implements DictService {
@Override
public List<DictDO> listType() {
return dictDao.listType().stream().distinct().collect(Collectors.toList());
return dictDao.listType();
}
@Override

View File

@ -1,74 +1,72 @@
package com.java2nb.common.service.impl;
import com.java2nb.common.config.Constant;
import com.java2nb.common.config.JnConfig;
import com.java2nb.common.dao.FileDao;
import com.java2nb.common.domain.FileDO;
import com.java2nb.common.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.File;
import java.util.List;
import java.util.Map;
import com.java2nb.common.dao.FileDao;
import com.java2nb.common.domain.FileDO;
import com.java2nb.common.service.FileService;
import org.springframework.util.StringUtils;
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileDao sysFileMapper;
@Autowired
private FileDao sysFileMapper;
@Autowired
private JnConfig jnConfig;
@Override
public FileDO get(Long id){
return sysFileMapper.get(id);
}
@Autowired
private JnConfig jnConfig;
@Override
public List<FileDO> list(Map<String, Object> map){
return sysFileMapper.list(map);
}
@Override
public FileDO get(Long id) {
return sysFileMapper.get(id);
}
@Override
public int count(Map<String, Object> map){
return sysFileMapper.count(map);
}
@Override
public List<FileDO> list(Map<String, Object> map) {
return sysFileMapper.list(map);
}
@Override
public int save(FileDO sysFile){
return sysFileMapper.save(sysFile);
}
@Override
public int count(Map<String, Object> map) {
return sysFileMapper.count(map);
}
@Override
public int update(FileDO sysFile){
return sysFileMapper.update(sysFile);
}
@Override
public int save(FileDO sysFile) {
return sysFileMapper.save(sysFile);
}
@Override
public int remove(Long id){
return sysFileMapper.remove(id);
}
@Override
public int update(FileDO sysFile) {
return sysFileMapper.update(sysFile);
}
@Override
public int remove(Long id) {
return sysFileMapper.remove(id);
}
@Override
public int batchRemove(Long[] ids) {
return sysFileMapper.batchRemove(ids);
}
@Override
public int batchRemove(Long[] ids){
return sysFileMapper.batchRemove(ids);
}
@Override
public Boolean isExist(String url) {
Boolean isExist = false;
if (!StringUtils.isEmpty(url)) {
String filePath = url.replace(Constant.UPLOAD_FILES_PREFIX, "");
filePath = jnConfig.getUploadPath() + filePath;
File file = new File(filePath);
if (file.exists()) {
isExist = true;
}
}
return isExist;
}
}
Boolean isExist = false;
if (!StringUtils.isEmpty(url)) {
String filePath = url.replace("/files/", "");
filePath = jnConfig.getUploadPath() + filePath;
File file = new File(filePath);
if (file.exists()) {
isExist = true;
}
}
return isExist;
}
}

View File

@ -1,14 +1,10 @@
package com.java2nb.common.utils;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* 日期处理
@ -95,37 +91,4 @@ public class DateUtils {
r += "";
return r;
}
/**
* 获取过去第几天的日期
*
* @param past
* @return
*/
@SneakyThrows
public static String getPastDate(int past,Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - past);
Date today = calendar.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(today);
}
/**
* 获取过去几天的日期集合
*
* @param past
* @return
*/
public static List<String> getDateList(int past,Date date) {
List<String> result = new ArrayList<>(past);
for(int i = past - 1 ; i > 0 ; i--){
result.add(getPastDate(i,date));
}
//今天的日期
result.add(new SimpleDateFormat("yyyy-MM-dd").format(date));
return result;
}
}

View File

@ -1,5 +1,6 @@
package com.java2nb.common.utils;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@ -7,80 +8,79 @@ import java.util.HashMap;
import java.util.Map;
public class JSONUtils {
/**
* Bean对象转JSON
*
* @param object
* @param dataFormatString
* @return
*/
public static String beanToJson(Object object, String dataFormatString) {
if (object != null) {
if (StringUtils.isEmpty(dataFormatString)) {
return JSONObject.toJSONString(object);
}
return JSON.toJSONStringWithDateFormat(object, dataFormatString);
} else {
return null;
}
}
/**
* Bean对象转JSON
*
* @param object
* @param dataFormatString
* @return
*/
public static String beanToJson(Object object, String dataFormatString) {
if (object != null) {
if (StringUtils.isEmpty(dataFormatString)) {
return JSONObject.toJSONString(object);
}
return JSON.toJSONStringWithDateFormat(object, dataFormatString);
} else {
return null;
}
}
/**
* Bean对象转JSON
*
* @param object
* @return
*/
public static String beanToJson(Object object) {
if (object != null) {
return JSON.toJSONString(object);
} else {
return null;
}
}
/**
* Bean对象转JSON
*
* @param object
* @return
*/
public static String beanToJson(Object object) {
if (object != null) {
return JSON.toJSONString(object);
} else {
return null;
}
}
/**
* String转JSON字符串
*
* @param key
* @param value
* @return
*/
public static String stringToJsonByFastjson(String key, String value) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return null;
}
Map<String, String> map = new HashMap<String, String>(16);
map.put(key, value);
return beanToJson(map, null);
}
/**
* String转JSON字符串
*
* @param key
* @param value
* @return
*/
public static String stringToJsonByFastjson(String key, String value) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return null;
}
Map<String, String> map = new HashMap<String, String>(16);
map.put(key, value);
return beanToJson(map, null);
}
/**
* 将json字符串转换成对象
*
* @param json
* @param clazz
* @return
*/
public static Object jsonToBean(String json, Object clazz) {
if (StringUtils.isEmpty(json) || clazz == null) {
return null;
}
return JSON.parseObject(json, clazz.getClass());
}
/**
* 将json字符串转换成对象
*
* @param json
* @param clazz
* @return
*/
public static Object jsonToBean(String json, Object clazz) {
if (StringUtils.isEmpty(json) || clazz == null) {
return null;
}
return JSON.parseObject(json, clazz.getClass());
}
/**
* json字符串转map
*
* @param json
* @return
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> jsonToMap(String json) {
if (StringUtils.isEmpty(json)) {
return null;
}
return JSON.parseObject(json, Map.class);
}
/**
* json字符串转map
*
* @param json
* @return
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> jsonToMap(String json) {
if (StringUtils.isEmpty(json)) {
return null;
}
return JSON.parseObject(json, Map.class);
}
}

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