Compare commits

...

No commits in common. "master" and "v2.5.0" have entirely different histories.

1608 changed files with 294849 additions and 15609 deletions

3
.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
*.js linguist-language=java
*.css linguist-language=java
*.html linguist-language=java

41
.gitignore vendored
View File

@ -1,36 +1,5 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
/logs/
/.shardingsphere/
/novel-front/novel-front.iml
/.idea
/novel-front/src/main/java/xyz/zinglizingli/books/core/crawl/BiqugeCrawlSource.java
/novel-front/src/main/java/xyz/zinglizingli/books/core/config/CrawlBiqugeConfig.java
/novel-front/src/main/java/xyz/zinglizingli/books/core/schedule/CrawlBookSchedule.java

Binary file not shown.

View File

@ -1,2 +0,0 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

36
README.en.md Normal file
View File

@ -0,0 +1,36 @@
# 小说精品屋
#### Description
该项目包括了一个小说网站代理和一个独立的小说弹幕网站包括小说在线阅读、TXT下载、小说弹幕、小说自动爬取、小说内容自动分享到微博、链接自动推送到百度搜索引擎等功能。现公布web端代码需要移动端和小程序代码的也可以找我。
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

384
README.md
View File

@ -1,232 +1,250 @@
[![index]( https://youdoc.github.io/img/tencent.jpg )]( https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console )
<p align="center">
<a href='https://github.com/201206030/novel'><img alt="Github stars" src="https://img.shields.io/github/stars/201206030/novel?logo=github"></a>
<a href='https://github.com/201206030/novel'><img alt="Github forks" src="https://img.shields.io/github/forks/201206030/novel?logo=github"></a>
<a href='https://gitee.com/novel_dev_team/novel'><img alt="Gitee stars" src="https://gitee.com/novel_dev_team/novel/badge/star.svg?theme=gitee"></a>
<a href='https://gitee.com/novel_dev_team/novel'><img alt="Gitee forks" src="https://gitee.com/novel_dev_team/novel/badge/fork.svg?theme=gitee"></a>
</p>
## 项目简介
novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离**学习型**
小说项目,配备[保姆级教程](https://docs.xxyopen.com/course/novel)手把手教你**从零开始**开发上线一套生产级别的 Java
系统,由小说门户系统、作家后台管理系统、平台后台管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、会员中心、作家专区、充值订阅、新闻发布等功能。
## 项目地址
- 后端项目(更新中):[GitHub](https://github.com/201206030/novel) [码云](https://gitee.com/novel_dev_team/novel)
- 前端项目(更新中):[GitHub](https://github.com/201206030/novel-front-web)
[码云](https://gitee.com/novel_dev_team/novel-front-web)
- 线上应用版:[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)
## 开发环境
- MySQL 8.0
- Redis 7.0
- Elasticsearch 8.2.0(可选)
- RabbitMQ 3.10.2(可选)
- XXL-JOB 2.3.1(可选)
- JDK 21
- Maven 3.8
- IntelliJ IDEA可选
- Node 16.14
**注Elasticsearch、RabbitMQ 和 XXL-JOB 默认关闭,可通过 application.yml 配置文件中相应的`enable`配置属性开启。**
## 后端技术选型
| 技术 | 版本 | 说明 | 官网 | 学习 |
|---------------------|:------------:|-------------------------| ------------------------------------ |:------------------------------------------------------------------------------------------------------------------------:|
| Spring Boot | 3.3.0 | 容器 + MVC 框架 | [进入](https://spring.io/projects/spring-boot) | [进入](https://docs.spring.io/spring-boot/docs/3.0.0/reference/html) |
| Spring AI | 1.0.0-M6 | Spring 官方 AI 框架 | [进入](https://spring.io/projects/spring-ai) | [进入](https://docs.spring.io/spring-ai/reference/) |
| MyBatis | 3.5.9 | ORM 框架 | [进入](http://www.mybatis.org) | [进入](https://mybatis.org/mybatis-3/zh/index.html) |
| MyBatis-Plus | 3.5.3 | MyBatis 增强工具 | [进入](https://baomidou.com/) | [进入](https://baomidou.com/pages/24112f/) |
| JJWT | 0.11.5 | JWT 登录支持 | [进入](https://github.com/jwtk/jjwt) | - |
| Lombok | 1.18.24 | 简化对象封装工具 | [进入](https://github.com/projectlombok/lombok) | [进入](https://projectlombok.org/features/all) |
| Caffeine | 3.1.0 | 本地缓存支持 | [进入](https://github.com/ben-manes/caffeine) | [进入](https://github.com/ben-manes/caffeine/wiki/Home-zh-CN) |
| Redis | 7.0 | 分布式缓存支持 | [进入](https://redis.io) | [进入](https://redis.io/docs) |
| Redisson | 3.17.4 | 分布式锁实现 | [进入](https://github.com/redisson/redisson) | [进入](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) |
| MySQL | 8.0 | 数据库服务 | [进入](https://www.mysql.com) | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) |
| ShardingSphere-JDBC | 5.5.1 | 数据库分库分表支持 | [进入](https://shardingsphere.apache.org) | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) |
| Elasticsearch | 8.2.0 | 搜索引擎服务 | [进入](https://www.elastic.co) | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) |
| RabbitMQ | 3.10.2 | 开源消息中间件 | [进入](https://www.rabbitmq.com) | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) |
| XXL-JOB | 2.3.1 | 分布式任务调度平台 | [进入](https://www.xuxueli.com/xxl-job) | [进入](https://www.xuxueli.com/xxl-job) |
| Sentinel | 1.8.4 | 流量控制组件 | [进入](https://github.com/alibaba/Sentinel) | [进入](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5) |
| Springdoc-openapi | 2.0.0 | Swagger 3 接口文档自动生成 | [进入](https://github.com/springdoc/springdoc-openapi) | [进入](https://springdoc.org/) |
| Spring Boot Admin | 3.0.0-M1 | 应用管理和监控 | [进入](https://github.com/codecentric/spring-boot-admin) | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) |
| Tomcat | 10.1.24 | Spring Boot 默认内嵌 Web 容器 | [进入](https://tomcat.apache.org) | [进入](https://tomcat.apache.org/tomcat-10.1-doc/index.html) |
| Docker | - | 应用容器引擎 | [进入](https://www.docker.com/) | - |
| Jenkins | - | 自动化部署工具 | [进入](https://github.com/jenkinsci/jenkins) | - |
| Sonarqube | - | 代码质量控制 | [进入](https://www.sonarqube.org/) | - |
**注:更多热门新技术待集成。**
## 前端技术选型
| 技术 | 版本 | 说明 | 官网 | 学习 |
| :----------------- | :-----: | -------------------------- | --------------------------------------- | :-------------------------------------------------: |
| Vue.js | 3.2.13 | 渐进式 JavaScript 框架 | [进入](https://vuejs.org) | [进入](https://staging-cn.vuejs.org/guide/introduction.html) |
| Vue Router | 4.0.15 | Vue.js 的官方路由 | [进入](https://router.vuejs.org) | [进入](https://router.vuejs.org/zh/guide/) |
| axios | 0.27.2 | 基于 promise 的网络请求库 | [进入](https://axios-http.com) | [进入](https://axios-http.com/zh/docs/intro) |
| element-plus | 2.2.0 | 基于 Vue 3面向设计师和开发者的组件库 | [进入](https://element-plus.org) | [进入](https://element-plus.org/zh-CN/guide/design.html) |
## 编码规范
- 规范方式:严格遵守阿里编码规约。
- 命名统一:简介最大程度上达到了见名知意。
- 分包明确:层级分明可快速定位到代码位置。
- 注释完整:描述性高大量减少了开发人员的代码阅读工作量。
- 工具规范使用统一jar包避免出现内容冲突。
- 代码整洁:可读性、维护性高。
- 依赖版本:所有依赖均使用当前最新可用版本以便新技术学习。
## 包结构
[![index]( https://s1.ax1x.com/2020/06/22/NG6N2n.png )](https://cloud.tencent.com/act/cps/redirect?redirect=1052&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console)
```
io
+- github
+- xxyopen
+- novel
+- NovelApplication.java -- 项目启动类
|
+- core -- 项目核心模块,包括各种工具、配置和常量等
| +- common -- 业务无关的通用模块
| | +- exception -- 通用异常处理
| | +- constant -- 通用常量
| | +- req -- 通用请求数据格式封装,例如分页请求数据
| | +- resp -- 接口响应工具及响应数据格式封装
| | +- util -- 通用工具
| |
| +- annotation -- 自定义注解类
| +- aspect -- Spring AOP 切面
| +- auth -- 用户认证授权相关
| +- config -- 业务相关配置
| +- constant -- 业务相关常量
| +- filter -- 过滤器
| +- interceptor -- 拦截器
| +- json -- JSON 相关的包,包括序列化器和反序列化器
| +- task -- 定时任务
| +- util -- 业务相关工具
| +- wrapper -- 装饰器
|
+- dto -- 数据传输对象,包括对各种 Http 请求和响应数据的封装
| +- req -- Http 请求数据封装
| +- resp -- Http 响应数据封装
|
+- dao -- 数据访问层,与底层 MySQL 进行数据交互
+- manager -- 通用业务处理层,对第三方平台封装、对 Service 层通用能力的下沉以及对多个 DAO 的组合复用
+- service -- 相对具体的业务逻辑服务层
+- controller -- 主要是处理各种 Http 请求,各类基本参数校验,或者不复用的业务简单处理,返回 JSON 数据等
| +- front -- 小说门户相关接口
| +- author -- 作家管理后台相关接口
| +- admin -- 平台管理后台相关接口
| +- app -- app 接口
| +- applet -- 小程序接口
| +- open -- 开放接口,供第三方调用
```
# 小说精品屋
## 截图
#### 新项目:小说精品屋-plus推荐
1. 首页
小说精品屋-plus致力于打造一个完整的可商用、可学习的小说门户平台。小说精品屋-plus是在小说精品屋的基础上重新进行了数据库设计、代码重构和功能增强提升了程序整体的可读性和性能增加了很多商用特性。
![img](https://s3.ax1x.com/2020/12/27/r5400A.png)
Gitee仓库地址 https://gitee.com/xiongxyang/novel-plus
2. 分类索引页
GitHub仓库地址 https://github.com/201206030/novel-plus
![img](https://oscimg.oschina.net/oscnet/up-d0b2e03129bfae47b8bb96a491b73d383c5.png)
#### 新项目:小说精品屋-微服务版(推荐)
3. 搜索页
基于小说精品屋-plus构建的Spring Cloud 微服务小说门户平台,可用于学习和商用。
![img](https://s3.ax1x.com/2020/12/27/r5TO8x.png)
Gitee仓库地址 https://gitee.com/xiongxyang/novel-cloud
![img](https://oscimg.oschina.net/oscnet/up-ed5f689557718924acac76bc3ebca36afcb.png)
GitHub仓库地址 https://github.com/201206030/novel-cloud
4. 排行榜
#### 前言
![img](https://oscimg.oschina.net/oscnet/up-78d5a68586cd92a86c669311f414508f922.png)
安装前请先阅读完此文档,了解项目基础配置和模块功能,再根据安装文档安装项目,避免一些不必要的错误。
5. 详情页
#### 安装文档
![img](https://oscimg.oschina.net/oscnet/up-8be2495a2869f93626b0c9c1df6f329747a.png)
源码安装文档(适合有一定技术基础的人):[点击前往](https://my.oschina.net/java2nb/blog/3145593)
6. 阅读页
包安装文档(适合非技术人员):[点击前往](https://my.oschina.net/java2nb/blog/3146627)
![img](https://oscimg.oschina.net/oscnet/up-517c84148d2db8e11717a8bbecc57fa1be7.png)
宝塔安装教程:[点击前往](https://www.daniao.org/7822.html )
7. 用户中心
#### 项目介绍
![img](https://oscimg.oschina.net/oscnet/up-805a30e7a663a3fd5cb39a7ea26bc132a01.png)
小说精品屋是一个多平台web、安卓app、微信小程序、功能完善的小说弹幕网站包含精品小说专区、轻小说专区和漫画专区。包括小说/漫画分类、小说/漫画搜索、小说/漫画排行、完本小说/漫画、小说/漫画评分、小说/漫画在线阅读、小说/漫画书架、小说/漫画阅读记录、小说下载、小说弹幕、小说/漫画自动爬取、小说内容自动分享到微博、邮件自动推广、链接自动推送到百度搜索引擎等功能。包含电脑端、移动端、微信小程序等多个平台现已开源web端、安卓端、小程序端源码。
8. 充值
#### 目录结构
![img](https://oscimg.oschina.net/oscnet/up-5a601b0b3af3224d0bebcfe12fc15075d34.png)
novel-front 前台web网站源码独立项目按需安装
![img](https://oscimg.oschina.net/oscnet/up-face25d02c07b05b2ce954cc4bf4ee6a0cc.png)
novel-admin :平台后台管理系统源码(独立项目,按需安装)
9. 作家专区
#### 软件架构
前台web网站架构Springboot+Mybatis+Mysql+Ehcache+Thymeleaf+Layui
![img](https://oscimg.oschina.net/oscnet/up-30766372cc7f56480ff1d7d55198204f6ea.png)
平台后台管理系统架构 : Springboot+Mybatis+Mysql+Redis+Thymeleaf+Layui+Bootstrap
![img](https://s3.ax1x.com/2020/11/17/DVFiQI.png)
#### 前台web网站截图
![img](https://s1.ax1x.com/2020/11/09/B7X5oF.png)
1. 电脑端(首页)
![img](https://s1.ax1x.com/2020/11/09/B7XLsx.png)
![index](./assets/%E7%B2%BE%E5%93%81%E5%B0%8F%E8%AF%B4%E6%A5%BC.png)
10. 购买
![img](https://oscimg.oschina.net/oscnet/up-ce0f585efd82a9670335f118cf5897c85e9.png)
![img](https://oscimg.oschina.net/oscnet/up-f849960f4c1303fea77d26e64fc505a7180.png)
2. 移动端(首页)
11. 接口文档
![index](./assets/QQ%E5%9B%BE%E7%89%8720191018162208.jpg)
![img](https://youdoc.github.io/img/novel/SwaggerUI.png)
3. 移动端(轻小说专区)
## 安装步骤
![index](./assets/QQ%E5%9B%BE%E7%89%8720191018161330.jpg)
👉 [立即查看](https://docs.xxyopen.com/course/novel/#%E5%AE%89%E8%A3%85%E6%AD%A5%E9%AA%A4)
4. 移动端(动漫专区)
## 联系我们
![index](./assets/mh_index.png)
👉 [立即查看](https://novel.xxyopen.com/service.htm)
5. 移动端(小说详情页)
## 问题
![微信图片_20190904181558](./assets/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20190904181558.png)
### 为什么有 novel/novel-cloud 学习版?
最开始是没有学习版的,只有一个爬虫/原创小说项目(最终发展成为 [novel-plus](https://github.com/201206030/novel-plus)
项目),用户群体大部分是对小说有兴趣,想自建一个干净无广告的小说网站的个人和站长。
后面随着使用人数逐渐增加,想通过这个项目来学习 Java 技术的人数也多了起来,对这部分用户来说,之前的项目用来学习很困难,具体原因如下:
6. 移动端(目录页)
1. novel-plus 功能模块比较多,重复性的增删改查占了大部分,而用户时间是有限的,很难在有限的时间内筛选出对自己有帮助的功能模块来学习。
2. novel-plus 追求的是系统稳定,用户很难在其中学习到最新的技术。
3. novel-plus 代码规范性不够,受限于开发时间限制,代码开发时没有选择一个标准化的规范去参考。
4. novel-plus 文档缺失,由于功能比较多,整个系统的教程编写需要花费大量时间,即使教程最终上线成功,用户也不可能有那么多时间也没有意义去学习所有的功能。
![QQ图片20191018161901](./assets/QQ%E5%9B%BE%E7%89%8720191108022250.png)
最终novel单体架构 和 novel-cloud微服务架构诞生了这两个项目在保证核心流程完整的同时从 novel-plus
中选用了一些有代表性的功能,使用最新技术栈(不间断地更新和集成新技术),在[保姆级教程](https://docs.xxyopen.com/course/novel)的帮助下,尽量保证每一个功能都能让你学到不重复的技术。
7. 移动端(小说阅读页)
所以这两个项目我的重点是去堆技术而不是去堆功能,功能只是其中的辅助,堆太多的重复性增删改查功能没有意义,对学习的帮助也不大。
![QQ图片20191018161901](./assets/QQ%E5%9B%BE%E7%89%8720191018161901.png)
### 谁适合使用 novel/novel-cloud 学习版项目?
8.电脑端(漫画阅读页)
如果对下面任何一个问题你能回答 "是"
![index](./assets/mh_content.png)
1. 你没有项目经验,想学习如何从零开始开发上线一个生产级别的 Java 项目?
2. 你有项目经验,但是公司技术栈太落后,想学习最新的主流开发技术?
那么,本项目正是你需要的。
### 谁暂时还不适合使用 novel/novel-cloud 学习版项目?
#### 后台管理系统截图
如果对下面任何一个问题你能回答 "是"
1. 登录界面
1. 你不懂 Java
2. 你只是想搭建一个小说网站使用?
3. 你想找一个完整的 Java 商用项目,有时间也有耐心去学习项目中的方方面面?
![](./assets/login.png)
那么,太遗憾了,本项目暂时不适合你,请使用 [novel-plus](https://github.com/201206030/novel-plus)。
2. 爬虫管理界面
![](./assets/crawl_pic.png)
3.爬虫配置界面。
![](./assets/crawl_config.png)
3.小说管理页面。
![](./assets/novel_list.png)
4.小说发布页面。
![](./assets/novel_pub.png)
5.小说章节发布页面
![](./assets/chapter_pub.png)
6.小说章节管理页面。
![](./assets/chapter_manager.png)
#### 微信小程序截图
![mini4](./assets/mini4.png)
#### 安卓App截图
![mini4](./assets/android_index.png)
#### 安装说明
数据库安装:
1. 安装MySQL软件。
2. 修改MySQL`max_allowed_packet `配置建议100M
3. 新建数据库books:create database books default character set utf8mb4 collate utf8mb4_general_ci 。
4. 执行sql/books.sql文件。
小说数据爬取的两种方式
1. 运行script/crawlbook/crawlbook.bat脚本文件。适用于本地多机器运行
2. 安装后台管理系统后,打开爬虫管理菜单,点击爬虫运行按钮。(适用于线上环境运行,会占用较多服务器资源)
平台后台管理系统安装独立项目按需安装已停止维护爬虫功能请使用crawlbook.bat
1. 修改application.yml文件中数据库配置。
2. 修改application.yml文件中Redis配置。
3. 修改application.yml文件中文件上传路径配置。
![](./assets/upload_config.png)
4. 启动程序,登录后台系统,运行爬虫程序爬取小说数据。
![](./assets/crawl_pic.png)
前台web网站安装独立项目按需安装
1. 修改项目application.yml配置文件中的数据库配置。
![](./assets/database_config.png)
2. 修改项目application.yml配置文件中的首页本站推荐小说配置修改的小说需要在数据库中存在
![](./assets/index_config.png)
3. 根据需求修改项目application.yml配置文件中的爬取小说最低评分配置建议和爬虫程序中的最低评分配置保持一致
![](./assets/score_config.png)
4. 根据需求修改项目application.yml配置文件中的小说爬虫源配置。
![](./assets/craw_config.png)
5. 根据需求修改项目application.yml配置文件中的图片保存方式。
![](./assets/pic_save_type.png)
6. 本地直接运行或使用maven插件打包成jar文件上传到服务器上。
7. `http://ip:port`访问首页。
8. `http://ip:port/books`访问精品小说模块。
9. `http://ip:port/book/searchSoftBook.html`访问轻小说模块。
10. `http://ip:port/book/searchMhBook.html`访问漫画模块。
**喜欢此项目的可以给我的GitHub和Gitee加个Star支持一下 。**
#### 演示地址
[点击前往](http://47.106.243.172:8888)(前台)
[点击前往 ](http://47.106.243.172:8888) (后台) (**后台爬虫程序运行会占用大量服务器资源,试用人数过多,服务器压力大,现暂停演示** )
演示账号admin/admin123
#### 小程序二维码
![mini-code](./assets/mini-code.png)
#### 代码仓库
Gitee仓库地址 https://gitee.com/xiongxyang/fiction_house
GitHub仓库地址 https://github.com/201206030/fiction_house
#### 文档地址
http://www.java2nb.com/article/5.html
#### QQ交流群
![mini-code](./assets/qq_group.png)
#### 捐赠支持
开源项目不易,若此项目能得到你的青睐,可以捐赠支持作者持续开发与维护。
![mini-code](./assets/jk.png)
##### 捐赠名单
| 捐赠者 | 金额 | 时间 |
| :----- | :------- | :-------------------------- |
| **阳 | ¥10.00 | 2020年03月06日 下午14点10分 |
| *梦 | ¥66.00 | 2019年12月27日 下午21点39分 |
| *金名 | ¥50.00 | 2019年12月27日 下午19点29分 |
| *天气 | ¥300.00 | 2019年12月27日 上午10点13分 |
| *强 | ¥10.00 | 2019年12月25日 下午21点29分 |
| *生 | ¥50.00 | 2019年12月25日 下午18点36分 |
| *江云 | ¥100.00 | 2019年12月20日 下午19点57分 |
| *磊 | ¥3.00 | 2019年12月17日 下午18点09分 |
| *勇 | ¥20.00 | 2019年11月30日 下午16点13分 |
| *伟 | ¥10.00 | 2019年11月14日 上午11点02分 |
| *式 | ¥8.88 | 2019年11月12日 下午23点54分 |
| *星 | ¥20.00 | 2019年11月12日 下午20点11分 |
| *😊 | ¥100.00 | 2019年11月12日 下午15点32分 |
| *东 | ¥10.00 | 2019年11月11日 下午21点23分 |
| *海 | ¥15.00 | 2019年11月11日 上午7点45分 |
| *飞 | ¥5.00 | 2019年11月11日 上午0点14分 |
| *沐 | ¥10.00 | 2019年11月10日 上午12点09分 |
#### 备注
精品小说屋所有相关项目均已在开源中国公开,感兴趣的可进入[开源中国](https://www.oschina.net/p/fiction_house)按关键字`精品小说屋`搜索。
[![index]( https://s1.ax1x.com/2020/06/22/NG6N2n.png)](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/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: 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_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/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,62 +0,0 @@
PUT /book
{
"mappings" : {
"properties" : {
"id" : {
"type" : "long"
},
"authorId" : {
"type" : "long"
},
"authorName" : {
"type" : "text",
"analyzer": "ik_smart"
},
"bookName" : {
"type" : "text",
"analyzer": "ik_smart"
},
"bookDesc" : {
"type" : "text",
"analyzer": "ik_smart"
},
"bookStatus" : {
"type" : "short"
},
"categoryId" : {
"type" : "integer"
},
"categoryName" : {
"type" : "text",
"analyzer": "ik_smart"
},
"lastChapterId" : {
"type" : "long"
},
"lastChapterName" : {
"type" : "text",
"analyzer": "ik_smart"
},
"lastChapterUpdateTime" : {
"type": "long"
},
"picUrl" : {
"type" : "keyword",
"index" : false,
"doc_values" : false
},
"score" : {
"type" : "integer"
},
"wordCount" : {
"type" : "integer"
},
"workDirection" : {
"type" : "short"
},
"visitCount" : {
"type": "long"
}
}
}
}

View File

@ -1,4 +0,0 @@
1. 初始状态下MySQL 只需要执行 `novel.sql` 文件即可正常运行本系统
2. 只有开启 XXL-JOB 的功能,才需要执行 `xxl-job.sql` 文件
3. 只有开启 ShardingSphere-JDBC 的功能,才需要执行 `shardingsphere-jdbc.sql` 文件

View File

@ -1,171 +0,0 @@
DROP PROCEDURE IF EXISTS createBookChapterTable;
-- 创建小说章节表的存储过程
CREATE PROCEDURE createBookChapterTable()
BEGIN
-- 定义变量
DECLARE i int DEFAULT 0;
DECLARE tableName char(13) DEFAULT NULL;
while i < 10 do
set tableName = concat('book_chapter',i);
set @stmt = concat('create table ',tableName,'(
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`book_id` bigint(20) unsigned NOT NULL COMMENT \'小说ID\',
`chapter_num` smallint(5) unsigned NOT NULL COMMENT \'章节号\',
`chapter_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'章节名\',
`word_count` int(10) unsigned NOT NULL COMMENT \'章节字数\',
`is_vip` tinyint(3) unsigned NOT NULL DEFAULT \'0\' COMMENT \'是否收费;1-收费 0-免费\',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_bookId_chapterNum` (`book_id`,`chapter_num`) USING BTREE,
UNIQUE KEY `pk_id` (`id`) USING BTREE,
KEY `idx_bookId` (`book_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=\'小说章节\'');
prepare stmt from @stmt;
execute stmt;
deallocate prepare stmt;
set i = i + 1;
end while;
END;
call createBookChapterTable();
DROP PROCEDURE IF EXISTS createBookContentTable;
-- 创建小说内容表的存储过程
CREATE PROCEDURE createBookContentTable()
BEGIN
-- 定义变量
DECLARE i int DEFAULT 0;
DECLARE tableName char(13) DEFAULT NULL;
while i < 10 do
set tableName = concat('book_content',i);
set @stmt = concat('create table ',tableName,'(
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT \'主键\',
`chapter_id` bigint(20) unsigned NOT NULL COMMENT \'章节ID\',
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'小说章节内容\',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_chapterId` (`chapter_id`) USING BTREE,
UNIQUE KEY `pk_id` (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=\'小说内容\'');
prepare stmt from @stmt;
execute stmt;
deallocate prepare stmt;
set i = i + 1;
end while;
END;
call createBookContentTable();
DROP PROCEDURE IF EXISTS copyBookChapterData;
-- 迁移小说章节数据的存储过程
CREATE PROCEDURE copyBookChapterData()
BEGIN
-- 定义变量
DECLARE s int DEFAULT 0;
DECLARE chapterId bigint;
DECLARE bookId bigint;
DECLARE chapterNum smallint;
DECLARE chapterName varchar(100);
DECLARE wordCount int DEFAULT 0;
DECLARE isVip tinyint(64) DEFAULT 0;
DECLARE createTime datetime DEFAULT NULL;
DECLARE updateTime datetime DEFAULT NULL;
DECLARE tableNumber int DEFAULT 0;
DECLARE tableName char(13) DEFAULT NULL;
-- 定义游标
DECLARE report CURSOR FOR select id,book_id,chapter_num, chapter_name, word_count, is_vip,create_time,update_time from book_chapter;
-- 声明当游标遍历完后将标志变量置成某个值
DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1;
-- 打开游标
open report;
-- 将游标中的值赋值给变量注意变量名不要和返回的列名同名变量顺序要和sql结果列的顺序一致
fetch report into chapterId,bookId,chapterNum, chapterName, wordCount,isVip,createTime,updateTime;
-- 循环遍历
while s<>1 do
-- 执行业务逻辑
set tableNumber = bookId % 10;
set tableName = concat('book_chapter',tableNumber);
set @stmt = concat('insert into ',tableName,'(`id`, `book_id`, `chapter_num`, `chapter_name`, `word_count`, `is_vip`, `create_time`, `update_time`) VALUES (',chapterId,', ',bookId,', ',chapterNum,', \'',chapterName,'\', ',wordCount,', ',isVip,', \'',createTime,'\', \'',updateTime,'\')');
prepare stmt from @stmt;
execute stmt;
deallocate prepare stmt;
fetch report into chapterId,bookId,chapterNum, chapterName, wordCount,isVip,createTime,updateTime;
end while;
-- 关闭游标
close report;
END;
call copyBookChapterData();
DROP PROCEDURE IF EXISTS copyBookContentData;
-- 迁移小说内容数据的存储过程
CREATE PROCEDURE copyBookContentData()
BEGIN
-- 定义变量
DECLARE s int DEFAULT 0;
DECLARE contentId bigint;
DECLARE chapterId bigint;
DECLARE bookContent mediumtext;
DECLARE createTime datetime DEFAULT NULL;
DECLARE updateTime datetime DEFAULT NULL;
DECLARE tableNumber int DEFAULT 0;
DECLARE tableName char(13) DEFAULT NULL;
-- 定义游标
DECLARE report CURSOR FOR select id,chapter_id,content,create_time,update_time from book_content;
-- 声明当游标遍历完后将标志变量置成某个值
DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1;
-- 打开游标
open report;
-- 将游标中的值赋值给变量注意变量名不要和返回的列名同名变量顺序要和sql结果列的顺序一致
fetch report into contentId,chapterId,bookContent,createTime,updateTime;
-- 循环遍历
while s<>1 do
-- 执行业务逻辑
set tableNumber = chapterId % 10;
set tableName = concat('book_content',tableNumber);
set bookContent = REPLACE(bookContent,'\'',"\\'");
set @stmt = concat('insert into ',tableName,'(`id`, `chapter_id`, `content`) VALUES (',contentId,', ',chapterId,',\'',bookContent,'\')');
prepare stmt from @stmt;
execute stmt;
deallocate prepare stmt;
fetch report into contentId,chapterId,bookContent,createTime,updateTime;
end while;
-- 关闭游标
close report;
END;
call copyBookContentData();

View File

@ -1,190 +0,0 @@
#
# XXL-JOB v2.4.0-SNAPSHOT
# Copyright (c) 2015-present, xuxueli.
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `xxl_job`;
SET NAMES utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态0-停止1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限执行器ID列表多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
commit;
-- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务
-- 增加 novel 任务执行器和同步小说数据到 Elasticsearch 的任务
INSERT INTO `xxl_job`.`xxl_job_group` ( `app_name`, `title`, `address_type`, `address_list`, `update_time` )
VALUES
(
'xxl-job-executor-novel',
'novel 任务执行器',
0,
NULL,
now()
);
INSERT INTO `xxl_job`.`xxl_job_info` (
`job_group`,
`job_desc`,
`add_time`,
`update_time`,
`author`,
`alarm_email`,
`schedule_type`,
`schedule_conf`,
`misfire_strategy`,
`executor_route_strategy`,
`executor_handler`,
`executor_param`,
`executor_block_strategy`,
`executor_timeout`,
`executor_fail_retry_count`,
`glue_type`,
`glue_source`,
`glue_remark`,
`glue_updatetime`,
`child_jobid`,
`trigger_status`,
`trigger_last_time`,
`trigger_next_time`
)
VALUES
(
(SELECT
id
FROM
xxl_job_group
WHERE
app_name = 'xxl-job-executor-novel'),
'同步小说数据到 Elasticsearch',
now(),
now(),
'xxyopen',
'',
'CRON',
'0 0 0 1 * ?',
'DO_NOTHING',
'FIRST',
'saveToEsJobHandler',
'',
'SERIAL_EXECUTION',
0,
0,
'BEAN',
'',
'GLUE代码初始化',
now(),
'',
0,
0,
0
);

View File

@ -1,3 +0,0 @@
IntelliJ IDEA 中导入 `intellij-java-google-style.xml` 文件:
`Preferences` => `Editor` => `Code Style` => `Java` => `Schema` => `Import Schema`

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<code_scheme name="GoogleStyle">
<codeStyleSettings language="JAVA">
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="ALIGN_MULTILINE_RESOURCES" value="false"/>
<option name="ALIGN_MULTILINE_FOR" value="false"/>
<option name="CALL_PARAMETERS_WRAP" value="1"/>
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
<option name="EXTENDS_LIST_WRAP" value="1"/>
<option name="THROWS_KEYWORD_WRAP" value="1"/>
<option name="METHOD_CALL_CHAIN_WRAP" value="1"/>
<option name="BINARY_OPERATION_WRAP" value="1"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="TERNARY_OPERATION_WRAP" value="1"/>
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true"/>
<option name="FOR_STATEMENT_WRAP" value="1"/>
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
<option name="WRAP_COMMENTS" value="true"/>
<option name="IF_BRACE_FORCE" value="3"/>
<option name="DOWHILE_BRACE_FORCE" value="3"/>
<option name="WHILE_BRACE_FORCE" value="3"/>
<option name="FOR_BRACE_FORCE" value="3"/>
<option name="PARENT_SETTINGS_INSTALLED" value="true"/>
<indentOptions>
<option name="INDENT_SIZE" value="4"/>
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
<option name="TAB_SIZE" value="4"/>
</indentOptions>
</codeStyleSettings>
</code_scheme>

316
mvnw vendored
View File

@ -1,316 +0,0 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

188
mvnw.cmd vendored
View File

@ -1,188 +0,0 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

4
novel-admin/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/novel-admin.iml
/.idea
/logs
/target

231
novel-admin/pom.xml Normal file
View File

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.java2nb</groupId>
<artifactId>novel-admin</artifactId>
<version>2.0.1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<velocity.version>1.7</velocity.version>
<activiti.version>5.22.0</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- NekoHTML 是一个简单地HTML扫描器和标签补偿器(tag balancer) ,使得程序能解析HTML文档并用标准的XML接口来访问其中的信息。
这个解析器能投扫描HTML文件并“修正”许多作者人或机器在编写HTML文档过程中常犯的错误。
NekoHTML 能增补缺失的父元素、自动用结束标签关闭相应的元素,以及不匹配的内嵌元素标签。
NekoHTML 的开发使用了Xerces Native Interface (XNI)后者是Xerces2的实现基础。-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<!--mybatis -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<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>
<version>1.10</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!--shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!-- utils -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-data-redis</artifactId>-->
<!--</dependency>-->
<!-- quartz -->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-cache</artifactId>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>net.sf.ehcache</groupId>-->
<!--<artifactId>ehcache</artifactId>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-devtools</artifactId>-->
<!--<optional>true</optional>-->
<!--</dependency>-->
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<!-- 添加redis支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.java2nb</groupId>
<artifactId>java2nb</artifactId>
<version>1.0.0-release</version>
<scope>system</scope>
<systemPath>${pom.basedir}/src/main/resources/jar/java2nb-1.0.0-release.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>-->
</plugins>
</build>
</project>

View File

@ -0,0 +1,28 @@
package com.java2nb;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//关闭SpringSecurity的功能
@EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
@EnableTransactionManagement
@ServletComponentScan
@MapperScan("com.java2nb.*.dao")
@SpringBootApplication
@EnableCaching
public class AdminApplication {
public static void main(String[] args){
SpringApplication.run(AdminApplication.class);
}
}

View File

@ -0,0 +1,19 @@
package com.java2nb.books.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
@Data
@Component
@ConfigurationProperties(prefix="crawl")
public class CrawlConfig {
private Integer threadCount;
private Integer priority;
private Float lowestScore;
private String minUptTime;
private Integer maxNumber;
}

View File

@ -0,0 +1,194 @@
package com.java2nb.books.controller;
import java.util.List;
import java.util.Map;
import com.java2nb.books.domain.BookContentDO;
import com.java2nb.books.domain.BookIndexDO;
import com.java2nb.books.vo.BookIndexVO;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import io.swagger.annotations.ApiOperation;
import com.java2nb.books.domain.BookDO;
import com.java2nb.books.service.BookService;
import com.java2nb.common.utils.PageBean;
import com.java2nb.common.utils.Query;
import com.java2nb.common.utils.R;
import javax.jws.WebParam;
/**
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:27:04
*/
@Controller
@RequestMapping("/books/book")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping()
@RequiresPermissions("books:book:book")
String Book() {
return "books/book/book";
}
@ApiOperation(value = "获取列表", notes = "获取列表")
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("books:book:book")
public R list(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<BookDO> bookList = bookService.list(query);
int total = bookService.count(query);
PageBean pageBean = new PageBean(bookList, total);
return R.ok().put("data", pageBean);
}
@ApiOperation(value = "新增页面", notes = "新增页面")
@GetMapping("/add")
String add() {
return "books/book/add";
}
@ApiOperation(value = "修改页面", notes = "修改页面")
@GetMapping("/edit/{id}")
String edit(@PathVariable("id") Long id, Model model) {
BookDO book = bookService.get(id);
model.addAttribute("book", book);
return "books/book/edit";
}
@ApiOperation(value = "查看页面", notes = "查看页面")
@GetMapping("/detail/{id}")
String detail(@PathVariable("id") Long id, Model model) {
BookDO book = bookService.get(id);
model.addAttribute("book", book);
return "books/book/detail";
}
/**
* 保存
*/
@ApiOperation(value = "新增", notes = "新增")
@ResponseBody
@PostMapping("/save")
public R save(BookDO book) {
if (bookService.save(book) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@ApiOperation(value = "修改", notes = "修改")
@ResponseBody
@RequestMapping("/update")
public R update(BookDO book) {
bookService.update(book);
return R.ok();
}
/**
* 删除
*/
@ApiOperation(value = "删除", notes = "删除")
@PostMapping("/remove")
@ResponseBody
public R remove(Long id) {
if (bookService.remove(id) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除
*/
@ApiOperation(value = "批量删除", notes = "批量删除")
@PostMapping("/batchRemove")
@ResponseBody
public R remove(@RequestParam("ids[]") Long[] ids) {
bookService.batchRemove(ids);
return R.ok();
}
@ApiOperation(value = "新增章节页面", notes = "新增章节页面")
@GetMapping("/index/add")
String indexAdd(Long bookId, Model model) {
model.addAttribute("bookId",bookId);
return "books/bookIndex/add";
}
/**
* 保存章节
*/
@ApiOperation(value = "新增章节", notes = "新增章节")
@ResponseBody
@PostMapping("/index/save")
public R indexSave(BookIndexDO bookIndex, BookContentDO bookContent) {
if (bookService.saveIndexAndContent(bookIndex,bookContent) > 0) {
return R.ok();
}
return R.error();
}
@GetMapping("/index")
String BookIndex(Long bookId, Model model) {
model.addAttribute("bookId",bookId);
return "books/bookIndex/bookIndex";
}
@ApiOperation(value = "获取章节列表", notes = "获取章节列表")
@ResponseBody
@GetMapping("/index/list")
public R indexList(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<BookIndexVO> bookIndexList = bookService.indexVOList(query);
int total = bookService.indexVOCount(query);
PageBean pageBean = new PageBean(bookIndexList, total);
return R.ok().put("data", pageBean);
}
/**
* 删除章节
*/
@ApiOperation(value = "删除章节", notes = "删除章节")
@PostMapping("/index/remove")
@ResponseBody
public R indexRemove( Long id,Long bookId) {
if (bookService.indexRemove(id,bookId) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除章节
*/
@ApiOperation(value = "批量删除章节", notes = "批量删除章节")
@PostMapping("/index/batchRemove")
@ResponseBody
public R indexRemove(@RequestParam("ids[]") Long[] ids,@RequestParam("bookIds[]") Long[] bookIds) {
bookService.batchIndexRemove(ids,bookIds);
return R.ok();
}
}

View File

@ -0,0 +1,152 @@
package com.java2nb.books.controller;
import java.util.*;
import com.java2nb.books.config.CrawlConfig;
import com.java2nb.common.utils.GenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import io.swagger.annotations.ApiOperation;
import com.java2nb.books.domain.BookCrawlDO;
import com.java2nb.books.service.BookCrawlService;
import com.java2nb.common.utils.PageBean;
import com.java2nb.common.utils.Query;
import com.java2nb.common.utils.R;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-15 03:42:54
*/
@Slf4j
@Controller
@RequestMapping("/books/bookCrawl")
public class BookCrawlController {
@Autowired
private BookCrawlService bookCrawlService;
@Autowired
private CrawlConfig crawlConfig;
@GetMapping()
@RequiresPermissions("books:bookCrawl:bookCrawl")
String BookCrawl() {
return "books/bookCrawl/bookCrawl";
}
@ApiOperation(value = "获取列表", notes = "获取列表")
@ResponseBody
@GetMapping("/list")
@RequiresPermissions("books:bookCrawl:bookCrawl")
public R list(@RequestParam Map<String, Object> params) {
//查询列表数据
Query query = new Query(params);
List<BookCrawlDO> bookCrawlList = bookCrawlService.list(query);
int total = bookCrawlService.count(query);
PageBean pageBean = new PageBean(bookCrawlList, total);
return R.ok().put("data", pageBean);
}
@ApiOperation(value = "新增页面", notes = "新增页面")
@GetMapping("/add")
@RequiresPermissions("books:bookCrawl:add")
String add() {
return "books/bookCrawl/add";
}
@ApiOperation(value = "修改页面", notes = "修改页面")
@GetMapping("/edit")
String edit( Model model) throws Exception {
model.addAttribute("property", crawlConfig);
return "books/bookCrawl/edit";
}
@ApiOperation(value = "查看页面", notes = "查看页面")
@GetMapping("/detail/{id}")
@RequiresPermissions("books:bookCrawl:detail")
String detail(@PathVariable("id") Long id, Model model) {
BookCrawlDO bookCrawl = bookCrawlService.get(id);
model.addAttribute("bookCrawl", bookCrawl);
return "books/bookCrawl/detail";
}
/**
* 保存
*/
@ApiOperation(value = "新增", notes = "新增")
@ResponseBody
@PostMapping("/save")
@RequiresPermissions("books:bookCrawl:add")
public R save( BookCrawlDO bookCrawl) {
if (bookCrawlService.save(bookCrawl) > 0) {
return R.ok();
}
return R.error();
}
/**
* 修改
*/
@ApiOperation(value = "修改", notes = "修改")
@ResponseBody
@RequestMapping("/update")
public R update(CrawlConfig config) {
BeanUtils.copyProperties(config,crawlConfig);
return R.ok();
}
/**
* 删除
*/
@ApiOperation(value = "删除", notes = "删除")
@PostMapping("/remove")
@ResponseBody
@RequiresPermissions("books:bookCrawl:remove")
public R remove( Long id) {
if (bookCrawlService.remove(id) > 0) {
return R.ok();
}
return R.error();
}
/**
* 删除
*/
@ApiOperation(value = "批量删除", notes = "批量删除")
@PostMapping("/batchRemove")
@ResponseBody
@RequiresPermissions("books:bookCrawl:batchRemove")
public R remove(@RequestParam("ids[]") Long[] ids) {
bookCrawlService.batchRemove(ids);
return R.ok();
}
/**
* 修改爬虫状态
*/
@ApiOperation(value = "修改爬虫状态", notes = "修改爬虫状态")
@ResponseBody
@RequestMapping("/updateStatus")
public R updateStatus( BookCrawlDO bookCrawl) {
bookCrawlService.updateStatus(bookCrawl);
return R.ok();
}
}

View File

@ -0,0 +1,37 @@
package com.java2nb.books.dao;
import com.java2nb.books.domain.BookContentDO;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:28:11
*/
@Mapper
public interface BookContentDao {
BookContentDO get(Long id);
List<BookContentDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(BookContentDO bookContent);
int update(BookContentDO bookContent);
int remove(Long id);
int batchRemove(Long[] ids);
void insertBatch(List<BookContentDO> newContentList);
void removeByBookIds(@Param("bookIds") String bookIds);
}

View File

@ -0,0 +1,34 @@
package com.java2nb.books.dao;
import com.java2nb.books.domain.BookCrawlDO;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-15 03:42:54
*/
@Mapper
public interface BookCrawlDao {
BookCrawlDO get(Long id);
List<BookCrawlDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(BookCrawlDO bookCrawl);
int update(BookCrawlDO bookCrawl);
int remove(Long id);
int batchRemove(Long[] ids);
void initStatus();
}

View File

@ -0,0 +1,36 @@
package com.java2nb.books.dao;
import com.java2nb.books.domain.BookDO;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:27:04
*/
@Mapper
public interface BookDao {
BookDO get(Long id);
List<BookDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(BookDO book);
int update(BookDO book);
int remove(Long id);
int batchRemove(Long[] ids);
void uptUpdateTime( @Param("id") Long bookId, @Param("updateTime") Date date);
}

View File

@ -0,0 +1,45 @@
package com.java2nb.books.dao;
import com.java2nb.books.domain.BookIndexDO;
import java.util.List;
import java.util.Map;
import com.java2nb.books.vo.BookIndexVO;
import com.java2nb.common.utils.Query;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:28:15
*/
@Mapper
public interface BookIndexDao {
BookIndexDO get(Long id);
List<BookIndexDO> list(Map<String,Object> map);
int count(Map<String,Object> map);
int save(BookIndexDO bookIndex);
int update(BookIndexDO bookIndex);
int remove(Long id);
int batchRemove(Long[] ids);
void insertBatch(List<BookIndexDO> newBookIndexList);
Integer queryMaxIndexNum(@Param("bookId") Long bookId);
List<BookIndexVO> listVO(Query query);
int countVO(Query query);
void removeByBookIds(@Param("bookIds") String bookIds);
}

View File

@ -0,0 +1,104 @@
package com.java2nb.books.domain;
import java.io.Serializable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:28:11
*/
public class BookContentDO implements Serializable {
private static final long serialVersionUID = 1L;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long bookId;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long indexId;
//
private Integer indexNum;
//
private String content;
/**
* 设置
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取
*/
public Long getId() {
return id;
}
/**
* 设置
*/
public void setBookId(Long bookId) {
this.bookId = bookId;
}
/**
* 获取
*/
public Long getBookId() {
return bookId;
}
/**
* 设置
*/
public void setIndexId(Long indexId) {
this.indexId = indexId;
}
/**
* 获取
*/
public Long getIndexId() {
return indexId;
}
/**
* 设置
*/
public void setIndexNum(Integer indexNum) {
this.indexNum = indexNum;
}
/**
* 获取
*/
public Integer getIndexNum() {
return indexNum;
}
/**
* 设置
*/
public void setContent(String content) {
this.content = content;
}
/**
* 获取
*/
public String getContent() {
return content;
}
}

View File

@ -0,0 +1,98 @@
package com.java2nb.books.domain;
import java.io.Serializable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-15 03:42:54
*/
public class BookCrawlDO implements Serializable {
private static final long serialVersionUID = 1L;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//
private String crawlWebName;
//
private String crawlWebUrl;
//
private Integer crawlWebCode;
//
private Integer status;
/**
* 设置
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取
*/
public Long getId() {
return id;
}
/**
* 设置
*/
public void setCrawlWebName(String crawlWebName) {
this.crawlWebName = crawlWebName;
}
/**
* 获取
*/
public String getCrawlWebName() {
return crawlWebName;
}
/**
* 设置
*/
public void setCrawlWebUrl(String crawlWebUrl) {
this.crawlWebUrl = crawlWebUrl;
}
/**
* 获取
*/
public String getCrawlWebUrl() {
return crawlWebUrl;
}
/**
* 设置
*/
public void setCrawlWebCode(Integer crawlWebCode) {
this.crawlWebCode = crawlWebCode;
}
/**
* 获取
*/
public Integer getCrawlWebCode() {
return crawlWebCode;
}
/**
* 设置
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* 获取
*/
public Integer getStatus() {
return status;
}
}

View File

@ -0,0 +1,202 @@
package com.java2nb.books.domain;
import java.io.Serializable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:27:04
*/
public class BookDO implements Serializable {
private static final long serialVersionUID = 1L;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//
private Integer catid;
//
private String picUrl;
//
private String bookName;
//
private String author;
//
private String bookDesc;
//
private Float score;
//
private String bookStatus;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long visitCount;
//
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
//
private Integer softCat;
//
private String softTag;
/**
* 设置
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取
*/
public Long getId() {
return id;
}
/**
* 设置
*/
public void setCatid(Integer catid) {
this.catid = catid;
}
/**
* 获取
*/
public Integer getCatid() {
return catid;
}
/**
* 设置
*/
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
/**
* 获取
*/
public String getPicUrl() {
return picUrl;
}
/**
* 设置
*/
public void setBookName(String bookName) {
this.bookName = bookName;
}
/**
* 获取
*/
public String getBookName() {
return bookName;
}
/**
* 设置
*/
public void setAuthor(String author) {
this.author = author;
}
/**
* 获取
*/
public String getAuthor() {
return author;
}
/**
* 设置
*/
public void setBookDesc(String bookDesc) {
this.bookDesc = bookDesc;
}
/**
* 获取
*/
public String getBookDesc() {
return bookDesc;
}
/**
* 设置
*/
public void setScore(Float score) {
this.score = score;
}
/**
* 获取
*/
public Float getScore() {
return score;
}
/**
* 设置
*/
public void setBookStatus(String bookStatus) {
this.bookStatus = bookStatus;
}
/**
* 获取
*/
public String getBookStatus() {
return bookStatus;
}
/**
* 设置
*/
public void setVisitCount(Long visitCount) {
this.visitCount = visitCount;
}
/**
* 获取
*/
public Long getVisitCount() {
return visitCount;
}
/**
* 设置
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 获取
*/
public Date getUpdateTime() {
return updateTime;
}
/**
* 设置
*/
public void setSoftCat(Integer softCat) {
this.softCat = softCat;
}
/**
* 获取
*/
public Integer getSoftCat() {
return softCat;
}
/**
* 设置
*/
public void setSoftTag(String softTag) {
this.softTag = softTag;
}
/**
* 获取
*/
public String getSoftTag() {
return softTag;
}
}

View File

@ -0,0 +1,87 @@
package com.java2nb.books.domain;
import java.io.Serializable;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.java2nb.common.jsonserializer.LongToStringSerializer;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:28:15
*/
public class BookIndexDO implements Serializable {
private static final long serialVersionUID = 1L;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;
//
//java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值)
//所以通过序列化成字符串来解决
@JsonSerialize(using = LongToStringSerializer.class)
private Long bookId;
//
private Integer indexNum;
//
private String indexName;
/**
* 设置
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取
*/
public Long getId() {
return id;
}
/**
* 设置
*/
public void setBookId(Long bookId) {
this.bookId = bookId;
}
/**
* 获取
*/
public Long getBookId() {
return bookId;
}
/**
* 设置
*/
public void setIndexNum(Integer indexNum) {
this.indexNum = indexNum;
}
/**
* 获取
*/
public Integer getIndexNum() {
return indexNum;
}
/**
* 设置
*/
public void setIndexName(String indexName) {
this.indexName = indexName;
}
/**
* 获取
*/
public String getIndexName() {
return indexName;
}
}

View File

@ -0,0 +1,21 @@
package com.java2nb.books.listener;
import com.java2nb.books.dao.BookCrawlDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class AppStartListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private BookCrawlDao bookCrawlDao;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
bookCrawlDao.initStatus();
System.out.println("项目启动成功");
}
}

View File

@ -0,0 +1,32 @@
package com.java2nb.books.service;
import com.java2nb.books.domain.BookCrawlDO;
import java.util.List;
import java.util.Map;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-15 03:42:54
*/
public interface BookCrawlService {
BookCrawlDO get(Long id);
List<BookCrawlDO> list(Map<String, Object> map);
int count(Map<String, Object> map);
int save(BookCrawlDO bookCrawl);
int update(BookCrawlDO bookCrawl);
int remove(Long id);
int batchRemove(Long[] ids);
void updateStatus(BookCrawlDO bookCrawl);
}

View File

@ -0,0 +1,50 @@
package com.java2nb.books.service;
import com.java2nb.books.domain.BookContentDO;
import com.java2nb.books.domain.BookDO;
import com.java2nb.books.domain.BookIndexDO;
import com.java2nb.books.vo.BookIndexVO;
import com.java2nb.common.utils.Query;
import java.util.List;
import java.util.Map;
/**
*
*
* @author xiongxy
* @email 1179705413@qq.com
* @date 2019-11-13 09:27:04
*/
public interface BookService {
BookDO get(Long id);
List<BookDO> list(Map<String, Object> map);
int count(Map<String, Object> map);
int save(BookDO book);
int update(BookDO book);
int remove(Long id);
int batchRemove(Long[] ids);
/**
* 保存章节
*/
int saveIndexAndContent(BookIndexDO bookIndex, BookContentDO bookContent);
List<BookIndexVO> indexVOList(Query query);
int indexVOCount(Query query);
int indexRemove(Long id, Long bookId);
int batchIndexRemove(Long[] ids, Long[] bookIds);
void saveBookAndIndexAndContent(BookDO book, List<BookIndexDO> bookIndex, List<BookContentDO> bookContent);
}

View File

@ -0,0 +1,897 @@
package com.java2nb.books.service.impl;
import com.java2nb.books.config.CrawlConfig;
import com.java2nb.books.dao.BookContentDao;
import com.java2nb.books.dao.BookDao;
import com.java2nb.books.dao.BookIndexDao;
import com.java2nb.books.domain.BookContentDO;
import com.java2nb.books.domain.BookDO;
import com.java2nb.books.domain.BookIndexDO;
import com.java2nb.books.service.BookService;
import com.java2nb.books.util.RestTemplateUtil;
import com.java2nb.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.java2nb.books.dao.BookCrawlDao;
import com.java2nb.books.domain.BookCrawlDO;
import com.java2nb.books.service.BookCrawlService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import static java.util.regex.Pattern.*;
@Service
public class BookCrawlServiceImpl implements BookCrawlService {
@Autowired
private CrawlConfig crawlConfig;
private boolean isInteruptBiquDaoCrawl;//是否中断笔趣岛爬虫程序
private boolean isInteruptBiquTaCrawl;//是否中断笔趣塔爬虫程序
private RestTemplate restTemplate = RestTemplateUtil.getInstance("utf-8");
@Autowired
private BookCrawlDao bookCrawlDao;
@Autowired
private BookDao bookDao;
@Autowired
private BookIndexDao bookIndexDao;
@Autowired
private BookService bookService;
@Override
public BookCrawlDO get(Long id) {
return bookCrawlDao.get(id);
}
@Override
public List<BookCrawlDO> list(Map<String, Object> map) {
return bookCrawlDao.list(map);
}
@Override
public int count(Map<String, Object> map) {
return bookCrawlDao.count(map);
}
@Override
public int save(BookCrawlDO bookCrawl) {
return bookCrawlDao.save(bookCrawl);
}
@Override
public int update(BookCrawlDO bookCrawl) {
return bookCrawlDao.update(bookCrawl);
}
@Override
public int remove(Long id) {
return bookCrawlDao.remove(id);
}
@Override
public int batchRemove(Long[] ids) {
return bookCrawlDao.batchRemove(ids);
}
@Override
public void updateStatus(BookCrawlDO bookCrawl) {
bookCrawlDao.update(bookCrawl);
if (bookCrawl.getStatus() == 0) {
switch (bookCrawl.getCrawlWebCode()) {
case 1: {
isInteruptBiquDaoCrawl = true;
break;
}
case 2: {
isInteruptBiquTaCrawl = true;
break;
}
}
} else {
switch (bookCrawl.getCrawlWebCode()) {
case 1: {
isInteruptBiquDaoCrawl = false;
break;
}
case 2: {
isInteruptBiquTaCrawl = false;
break;
}
}
crawlBook(bookCrawl);
}
}
private void crawlBook(BookCrawlDO bookCrawl) {
int threadCount = crawlConfig.getThreadCount();
int step = 7 / threadCount;
int pos = step;
int i = 1;
while (i <= 7) {
final int fPos = pos;
final int fI = i;
i = pos + 1;
new Thread(
() -> {
int j = fI;
for (; j <= fPos; j++) {
try {
switch (bookCrawl.getCrawlWebCode()) {
case 1: {
while (true) {
if (isInteruptBiquDaoCrawl) {
return;
}
crawBiqudaoBooks(j);
Thread.sleep(1000 * 60 * 60 * 24);
}
}
case 2: {
while (true) {
if (isInteruptBiquTaCrawl) {
return;
}
crawBiquTaBooks(j);
Thread.sleep(1000 * 60 * 60 * 24);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
).start();
pos += step;
if (7 - pos < step) {
pos = 7;
}
}
/*new Thread(() -> {
for (int j = 21; j <= 29; j++) {
for (int k = 1; k <= 499; k++) {
if (isInteruptBiquTaCrawl || isInteruptBiquDaoCrawl) {
return;
}
System.out.println("==============分类============" + j);
System.out.println("==============页码============" + k);
int catId = j;
int page = k;
String bookListUrl = "http://book.sfacg.com/List/default.aspx?&tid=" + catId + "&if=1&PageIndex=" + page;
String forObject = getByTemplate(bookListUrl);
if (forObject != null) {
Pattern bookPatten = Pattern.compile("href=\"/Novel/(\\d+)/\"");
Matcher bookMatcher = bookPatten.matcher(forObject);
boolean isFindBook = bookMatcher.find();
while (isFindBook) {
try {
if (isInteruptBiquTaCrawl || isInteruptBiquDaoCrawl) {
return;
}
long bookNum = Long.parseLong(bookMatcher.group(1));
String bookUrl = "http://book.sfacg.com/Novel/" + bookNum;
String forObject1 = getByTemplate(bookUrl);
if (forObject1 != null) {
Pattern updateTimePatten = Pattern.compile("更新:(\\d+/\\d+/\\d+ \\d+:\\d+:\\d+)");
Matcher updateTimeMatch = updateTimePatten.matcher(forObject1);
boolean isFindUpdateTime = updateTimeMatch.find();
if (isFindUpdateTime) {
String updateTimeStr = updateTimeMatch.group(1);
String dateStr = updateTimeStr;
int firstPos = dateStr.indexOf("/");
String year = dateStr.substring(0, firstPos);
dateStr = dateStr.substring(firstPos + 1);
firstPos = dateStr.indexOf("/");
String month = dateStr.substring(0, firstPos);
dateStr = dateStr.substring(firstPos + 1);
firstPos = dateStr.indexOf(" ");
String day = dateStr.substring(0, firstPos);
dateStr = dateStr.substring(firstPos + 1);
firstPos = dateStr.indexOf(":");
String hour = dateStr.substring(0, firstPos);
dateStr = dateStr.substring(firstPos + 1);
firstPos = dateStr.indexOf(":");
String minus = dateStr.substring(0, firstPos);
String second = dateStr.substring(firstPos + 1);
if (month.length() == 1) {
month = "0" + month;
}
if (day.length() == 1) {
day = "0" + day;
}
if (hour.length() == 1) {
hour = "0" + hour;
}
if (minus.length() == 1) {
minus = "0" + minus;
}
if (second.length() == 1) {
second = "0" + second;
}
Date updateTime = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(updateTimeStr);
//Date updateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(year+"-"+month+"-"+hour+" "+minus+" "+minus);
Pattern bookNamePatten = Pattern.compile("<h1 class=\"title\">\\s*" +
"<span class=\"text\">([^<]+)</span>\\s*" +
"<span");
Matcher bookNameMatcher = bookNamePatten.matcher(forObject1);
boolean isFindBookName = bookNameMatcher.find();
if (isFindBookName) {
String bookName = bookNameMatcher.group(1);
System.out.println(bookName);
Pattern authorPatten = Pattern.compile("<div class=\"author-name\">\\s*" +
"<span>([^<]+)</span>\\s*" +
"</div>");
Matcher authorMatcher = authorPatten.matcher(forObject1);
boolean isFindAuthor = authorMatcher.find();
if (isFindAuthor) {
String author = authorMatcher.group(1);
Pattern picPtten = Pattern.compile("src=\"(http://rs.sfacg.com/web/novel/images/NovelCover/Big/[^\"]+)\"");
Matcher picMatcher = picPtten.matcher(forObject1);
if (picMatcher.find()) {
String pic = picMatcher.group(1);
Pattern visitPatten = Pattern.compile(">点击:(\\d+)<");
Matcher visitMatcher = visitPatten.matcher(forObject1);
boolean isFindVisit = visitMatcher.find();
if (isFindVisit) {
String visit = visitMatcher.group(1);
Pattern statusPatten = Pattern.compile(">字数:\\d+字\\[([^<]+)\\]<");
Matcher statusMatcher = statusPatten.matcher(forObject1);
boolean isFindStatus = statusMatcher.find();
if (isFindStatus) {
String status = statusMatcher.group(1);
if ("已完结".equals(status)) {//先爬已完结的
status = "已完成";
}
Pattern scorePatten = Pattern.compile("<div class=\"num\">\\s*" +
"<span>(\\d+\\.\\d+)</span>\\s*" +
"</div>");
Matcher scoreMather = scorePatten.matcher(forObject1);
boolean isFindScore = scoreMather.find();
if (isFindScore) {
float score = Float.parseFloat(scoreMather.group(1));
//if (score >= 7.0) {
Pattern descPatten = Pattern.compile("<p class=\"introduce\">\\s*" +
"([^<]+)\\s*</p>");
Matcher descMatcher = descPatten.matcher(forObject1);
boolean isFindDesc = descMatcher.find();
if (isFindDesc) {
String desc = descMatcher.group(1);
Pattern tagPatten = Pattern.compile("<li class=\"tag\">\\s*" +
"<a href=\"/stag/\\d+/\" class=\"highlight\"><span class=\"icn\">[^<]+</span><span class=\"text\">([^<]+)</span></a>\\s*" +
"</li>");
Matcher tagMatch = tagPatten.matcher(forObject1);
String tag = "";
boolean isFindTag = tagMatch.find();
while (isFindTag) {
tag += ("," + tagMatch.group(1));
isFindTag = tagMatch.find();
}
if (tag.length() > 0) {
tag = tag.substring(1);
}
BookDO book = new BookDO();
book.setAuthor(author);
book.setCatid(8);
book.setBookDesc(desc);
book.setBookName(bookName);
book.setSoftTag(tag);
book.setSoftCat(catId);
book.setScore(score > 10 ? 8.0f : score);
book.setVisitCount(Long.parseLong(visit));
book.setPicUrl(pic);
book.setBookStatus(status);
book.setUpdateTime(updateTime);
List<BookIndexDO> indexList = new ArrayList<>();
List<BookContentDO> contentList = new ArrayList<>();
//读取目录
String indexUrl = "http://book.sfacg.com/Novel/" + bookNum + "/MainIndex/";
String forObject2 = getByTemplate(indexUrl);
if (forObject2 != null) {
Pattern indexListPatten = Pattern.compile("href=\"(/Novel/\\d+/\\d+/\\d+/)\"\\s+title=\"([^\"]+)\\s*");
Matcher indexListMatch = indexListPatten.matcher(forObject2);
boolean isFindIndex = indexListMatch.find();
int indexNum = 0;
//查询该书籍已存在目录号
List<Integer> hasIndexNum = queryIndexCountByBookNameAndBAuthor(bookName, author);
while (isFindIndex) {
if (isInteruptBiquTaCrawl || isInteruptBiquDaoCrawl) {
return;
}
if (!hasIndexNum.contains(indexNum)) {
String contentUrl = "http://book.sfacg.com" + indexListMatch.group(1);
String indexName = indexListMatch.group(2);
//查询章节内容
String forObject3 = getByTemplate(contentUrl);
if (forObject3 != null && !forObject3.contains("内容整改中,请等待")) {
String content = forObject3.substring(forObject3.indexOf("<div class=\"article-content"));
content = content.substring(0, content.indexOf("</div>") + 6);
//TODO插入章节目录和章节内容
BookIndexDO bookIndex = new BookIndexDO();
bookIndex.setIndexName(indexName);
bookIndex.setIndexNum(indexNum);
indexList.add(bookIndex);
BookContentDO bookContent = new BookContentDO();
bookContent.setContent(content);
bookContent.setIndexNum(indexNum);
contentList.add(bookContent);
} else {
break;
}
}
indexNum++;
isFindIndex = indexListMatch.find();
}
if (indexList.size() == contentList.size() && indexList.size() > 0) {
saveBookAndIndexAndContent(book, indexList, contentList);
}
}
}
}
}
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
isFindBook = bookMatcher.find();
}
}
}
}
}
}).start();*/
}
private void crawBiquTaBooks(int i) {
String baseUrl = "https://m.biquta.la";
String catBookListUrlBase = baseUrl + "/class/";
if (crawlConfig.getPriority() == 1) {
catBookListUrlBase = baseUrl + "/lhb/";
}
//拼接分类URL
int page = 1;
int totalPage = page;
String catBookListUrl = catBookListUrlBase + i + "/" + page + ".html";
String forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数<input type="text" class="page_txt" value="1/3019" size="5" name="txtPage" id="txtPage" />
Pattern pattern = compile("value=\"(\\d+)/(\\d+)\"");
Matcher matcher = pattern.matcher(forObject);
boolean isFind = matcher.find();
System.out.println("匹配分页数" + isFind);
if (isFind) {
int currentPage = Integer.parseInt(matcher.group(1));
totalPage = Integer.parseInt(matcher.group(2));
//解析第一页书籍的数据
Pattern bookPatten = compile("href=\"/(\\d+_\\d+)/\"");
parseBiquTaBook(bookPatten, forObject, i, baseUrl);
while (currentPage < totalPage) {
if (isInteruptBiquTaCrawl) {
return;
}
catBookListUrl = catBookListUrlBase + i + "/" + (currentPage + 1) + ".html";
forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数
matcher = pattern.matcher(forObject);
isFind = matcher.find();
if (isFind) {
currentPage = Integer.parseInt(matcher.group(1));
totalPage = Integer.parseInt(matcher.group(2));
parseBiquTaBook(bookPatten, forObject, i, baseUrl);
}
} else {
currentPage++;
}
}
}
}
}
private void parseBiquTaBook(Pattern bookPatten, String forObject, int catNum, String baseUrl) {
Matcher matcher2 = bookPatten.matcher(forObject);
boolean isFind = matcher2.find();
Pattern scorePatten = compile("<div\\s+class=\"score\">(\\d+\\.\\d+)分</div>");
Matcher scoreMatch = scorePatten.matcher(forObject);
boolean scoreFind = scoreMatch.find();
Pattern bookNamePatten = compile("<p class=\"title\">([^/]+)</p>");
Matcher bookNameMatch = bookNamePatten.matcher(forObject);
boolean isBookNameMatch = bookNameMatch.find();
Pattern authorPatten = compile(">作者:([^/]+)<");
Matcher authoreMatch = authorPatten.matcher(forObject);
boolean isFindAuthor = authoreMatch.find();
System.out.println("匹配书籍url" + isFind);
System.out.println("匹配分数" + scoreFind);
while (isFind && scoreFind && isBookNameMatch && isFindAuthor) {
if (isInteruptBiquTaCrawl) {
return;
}
try {
Float score = Float.parseFloat(scoreMatch.group(1));
if (score < crawlConfig.getLowestScore()) {//数据库空间有限暂时爬取8.0分以上的小说
continue;
}
String bookName = bookNameMatch.group(1);
String author = authoreMatch.group(1);
/*//查询该书籍是否存在
boolean isExsit = bookService.isExsitBook(bookName, author);
if (isExsit) {
continue;
}*/
//System.out.println(new Date()+bookName + "");
String bokNum = matcher2.group(1);
String bookUrl = baseUrl + "/" + bokNum + "/";
String body = getByTemplate(bookUrl);
if (body != null) {
Pattern statusPatten = compile("状态:([^/]+)</li>");
Matcher statusMatch = statusPatten.matcher(body);
if (statusMatch.find()) {
String status = statusMatch.group(1);
Pattern updateTimePatten = compile("更新:(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+)</a>");
Matcher updateTimeMatch = updateTimePatten.matcher(body);
if (updateTimeMatch.find()) {
String updateTimeStr = updateTimeMatch.group(1);
SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
Date updateTime = format.parse(updateTimeStr);
if (updateTime.getTime() < new SimpleDateFormat("yyyy-MM-dd").parse(crawlConfig.getMinUptTime()).getTime()) {
continue;
}
Pattern picPatten = compile("<img src=\"([^>]+)\"\\s+onerror=\"this.src=");
Matcher picMather = picPatten.matcher(body);
if (picMather.find()) {
String picSrc = picMather.group(1);
String desc = body.substring(body.indexOf("<p class=\"review\">") + "<p class=\"review\">".length());
desc = desc.substring(0, desc.indexOf("</p>"));
BookDO book = new BookDO();
book.setAuthor(author);
book.setCatid(catNum);
book.setBookDesc(desc);
book.setBookName(bookName);
book.setScore(score > 10 ? 8.0f : score);
book.setPicUrl(picSrc);
book.setBookStatus(status);
book.setUpdateTime(updateTime);
List<BookIndexDO> indexList = new ArrayList<>();
List<BookContentDO> contentList = new ArrayList<>();
//读取目录
Pattern indexPatten = compile("<a\\s+href=\"(/du/\\d+_\\d+/)\">查看完整目录</a>");
Matcher indexMatch = indexPatten.matcher(body);
if (indexMatch.find()) {
String indexUrl = baseUrl + indexMatch.group(1);
String body2 = getByTemplate(indexUrl);
if (body2 != null) {
Pattern indexListPatten = compile("<a\\s+style=\"\"\\s+href=\"(/\\d+_\\d+/\\d+\\.html)\">([^/]+)</a>");
Matcher indexListMatch = indexListPatten.matcher(body2);
boolean isFindIndex = indexListMatch.find();
int indexNum = 0;
//查询该书籍已存在目录号
List<Integer> hasIndexNum = queryIndexCountByBookNameAndBAuthor(bookName, author);
while (isFindIndex) {
if (isInteruptBiquTaCrawl) {
return;
}
if (!hasIndexNum.contains(indexNum)) {
String contentUrl = baseUrl + indexListMatch.group(1);
String indexName = indexListMatch.group(2);
//查询章节内容
String body3 = getByTemplate(contentUrl.replace("//m.", "//www."));
if (body3 != null) {
String start = "id=\"content\">";
String end = "<script>";
String content = body3.substring(body3.indexOf(start) + start.length());
content = "<div class=\"article-content font16\" id=\"ChapterBody\" data-class=\"font16\">" + content.substring(0, content.indexOf(end)) + "</div>";
//TODO插入章节目录和章节内容
BookIndexDO bookIndex = new BookIndexDO();
bookIndex.setIndexName(indexName);
bookIndex.setIndexNum(indexNum);
indexList.add(bookIndex);
BookContentDO bookContent = new BookContentDO();
bookContent.setContent(content);
bookContent.setIndexNum(indexNum);
contentList.add(bookContent);
}
}
indexNum++;
isFindIndex = indexListMatch.find();
}
if (indexList.size() == contentList.size() && indexList.size() > 0) {
bookService.saveBookAndIndexAndContent(book, indexList, contentList);
}
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
matcher2.find();
isFind = matcher2.find();
scoreFind = scoreMatch.find();
isBookNameMatch = bookNameMatch.find();
isFindAuthor = authoreMatch.find();
}
}
}
private void crawBiqudaoBooks(final int i) {
String baseUrl = "https://m.biqudao.com";
String catBookListUrlBase = baseUrl + "/bqgeclass/";
if (crawlConfig.getPriority() == 1) {
catBookListUrlBase = baseUrl + "/bqgelhb/";
}
//拼接分类URL
int page = 1;//起始页码
int totalPage = page;
String catBookListUrl = catBookListUrlBase + i + "/" + page + ".html";
String forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数<input type="text" class="page_txt" value="1/3019" size="5" name="txtPage" id="txtPage" />
Pattern pattern = compile("value=\"(\\d+)/(\\d+)\"");
Matcher matcher = pattern.matcher(forObject);
boolean isFind = matcher.find();
System.out.println("匹配分页数" + isFind);
if (isFind) {
int currentPage = Integer.parseInt(matcher.group(1));
totalPage = Integer.parseInt(matcher.group(2));
//解析第一页书籍的数据
Pattern bookPatten = compile("href=\"/(bqge\\d+)/\"");
parseBiqudaoBook(bookPatten, forObject, i, baseUrl);
while (currentPage < totalPage) {
if (isInteruptBiquDaoCrawl) {
return;
}
catBookListUrl = catBookListUrlBase + i + "/" + (currentPage + 1) + ".html";
forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数
matcher = pattern.matcher(forObject);
isFind = matcher.find();
if (isFind) {
currentPage = Integer.parseInt(matcher.group(1));
totalPage = Integer.parseInt(matcher.group(2));
parseBiqudaoBook(bookPatten, forObject, i, baseUrl);
}
} else {
currentPage++;
}
}
}
}
}
private void parseBiqudaoBook(Pattern bookPatten, String forObject, int catNum, String baseUrl) {
Matcher matcher2 = bookPatten.matcher(forObject);
boolean isFind = matcher2.find();
Pattern scorePatten = compile("<div\\s+class=\"score\">(\\d+\\.\\d+)分</div>");
Matcher scoreMatch = scorePatten.matcher(forObject);
boolean scoreFind = scoreMatch.find();
Pattern bookNamePatten = compile("<p class=\"title\">([^/]+)</p>");
Matcher bookNameMatch = bookNamePatten.matcher(forObject);
boolean isBookNameMatch = bookNameMatch.find();
Pattern authorPatten = compile(">作者:([^<]+)<");
Matcher authoreMatch = authorPatten.matcher(forObject);
boolean isFindAuthor = authoreMatch.find();
System.out.println("匹配书籍url" + isFind);
System.out.println("匹配分数" + scoreFind);
while (isFind && scoreFind && isBookNameMatch && isFindAuthor) {
try {
if (isInteruptBiquDaoCrawl) {
return;
}
Float score = Float.parseFloat(scoreMatch.group(1));
if (score < crawlConfig.getLowestScore()) {
continue;
}
String bookName = bookNameMatch.group(1);
String author = authoreMatch.group(1);
/*//查询该书籍是否存在
boolean isExsit = bookService.isExsitBook(bookName, author);
if (isExsit) {
continue;
}*/
//System.out.println(new Date()+bookName + "");
String bokNum = matcher2.group(1);
String bookUrl = baseUrl + "/" + bokNum + "/";
String body = getByTemplate(bookUrl);
if (body != null) {
Pattern statusPatten = compile("状态:([^/]+)</li>");
Matcher statusMatch = statusPatten.matcher(body);
if (statusMatch.find()) {
String status = statusMatch.group(1);
Pattern updateTimePatten = compile("更新:(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+)</a>");
Matcher updateTimeMatch = updateTimePatten.matcher(body);
if (updateTimeMatch.find()) {
String updateTimeStr = updateTimeMatch.group(1);
SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
Date updateTime = format.parse(updateTimeStr);
if (updateTime.getTime() < new SimpleDateFormat("yyyy-MM-dd").parse(crawlConfig.getMinUptTime()).getTime()) {
continue;
}
Pattern picPatten = compile("<img src=\"([^>]+)\"\\s+onerror=\"this.src=");
Matcher picMather = picPatten.matcher(body);
if (picMather.find()) {
String picSrc = picMather.group(1);
Pattern descPatten = compile("class=\"review\">([^<]+)</p>");
Matcher descMatch = descPatten.matcher(body);
if (descMatch.find()) {
String desc = descMatch.group(1);
BookDO book = new BookDO();
book.setAuthor(author);
book.setCatid(catNum);
book.setBookDesc(desc);
book.setBookName(bookName);
book.setScore(score > 10 ? 8.0f : score);
book.setPicUrl(picSrc);
book.setBookStatus(status);
book.setUpdateTime(updateTime);
List<BookIndexDO> indexList = new ArrayList<>();
List<BookContentDO> contentList = new ArrayList<>();
//读取目录
Pattern indexPatten = compile("<a\\s+href=\"(/bqge\\d+/all\\.html)\">查看完整目录</a>");
Matcher indexMatch = indexPatten.matcher(body);
if (indexMatch.find()) {
String indexUrl = baseUrl + indexMatch.group(1);
String body2 = getByTemplate(indexUrl);
if (body2 != null) {
Pattern indexListPatten = compile("<a[^/]+style[^/]+href=\"(/bqge\\d+/\\d+\\.html)\">([^/]+)</a>");
Matcher indexListMatch = indexListPatten.matcher(body2);
boolean isFindIndex = indexListMatch.find();
int indexNum = 0;
//查询该书籍已存在目录号
List<Integer> hasIndexNum = queryIndexCountByBookNameAndBAuthor(bookName, author);
while (isFindIndex) {
if (isInteruptBiquDaoCrawl) {
return;
}
if (!hasIndexNum.contains(indexNum)) {
String contentUrl = baseUrl + indexListMatch.group(1);
String indexName = indexListMatch.group(2);
//查询章节内容
String body3 = getByTemplate(contentUrl);
if (body3 != null) {
Pattern contentPattten = compile("章节错误,点此举报(.*)加入书签,方便阅读");
String start = "『章节错误,点此举报』";
String end = "『加入书签,方便阅读』";
String content = body3.substring(body3.indexOf(start) + start.length(), body3.indexOf(end));
//TODO插入章节目录和章节内容
BookIndexDO bookIndex = new BookIndexDO();
bookIndex.setIndexName(indexName);
bookIndex.setIndexNum(indexNum);
indexList.add(bookIndex);
BookContentDO bookContent = new BookContentDO();
bookContent.setContent(content);
bookContent.setIndexNum(indexNum);
contentList.add(bookContent);
//System.out.println(indexName);
} else {
break;
}
}
indexNum++;
isFindIndex = indexListMatch.find();
}
if (indexList.size() == contentList.size() && indexList.size() > 0) {
bookService.saveBookAndIndexAndContent(book, indexList, contentList);
}
}
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
matcher2.find();
isFind = matcher2.find();
scoreFind = scoreMatch.find();
isBookNameMatch = bookNameMatch.find();
isFindAuthor = authoreMatch.find();
}
}
}
private String getByTemplate(String catBookListUrl) {
try {
ResponseEntity<String> forEntity = restTemplate.getForEntity(catBookListUrl, String.class);
if (forEntity.getStatusCode() == HttpStatus.OK) {
return forEntity.getBody();
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 查询该书籍目录数量
*/
private List<Integer> queryIndexCountByBookNameAndBAuthor(String bookName, String author) {
List<Integer> result = new ArrayList<>();
Map<String, Object> bookExample = new HashMap<>();
bookExample.put("bookName", bookName);
bookExample.put("author", author);
List<BookDO> books = bookDao.list(bookExample);
if (books.size() > 0) {
Long bookId = books.get(0).getId();
Map<String, Object> bookIndexExample = new HashMap<>();
bookIndexExample.put("bookId", bookId);
List<BookIndexDO> bookIndices = bookIndexDao.list(bookIndexExample);
if (bookIndices != null && bookIndices.size() > 0) {
for (BookIndexDO bookIndex : bookIndices) {
result.add(bookIndex.getIndexNum());
}
}
}
return result;
}
}

View File

@ -0,0 +1,199 @@
package com.java2nb.books.service.impl;
import com.java2nb.books.dao.BookContentDao;
import com.java2nb.books.dao.BookIndexDao;
import com.java2nb.books.domain.BookContentDO;
import com.java2nb.books.domain.BookIndexDO;
import com.java2nb.books.util.StringUtil;
import com.java2nb.books.vo.BookIndexVO;
import com.java2nb.common.utils.Query;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import com.java2nb.books.dao.BookDao;
import com.java2nb.books.domain.BookDO;
import com.java2nb.books.service.BookService;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Autowired
private BookIndexDao bookIndexDao;
@Autowired
private BookContentDao bookContentDao;
@Override
public BookDO get(Long id){
return bookDao.get(id);
}
@Override
public List<BookDO> list(Map<String, Object> map){
String sort = (String) map.get("sort");
if(StringUtils.isNotBlank(sort)){
map.put("sort",StringUtil.humpToLine(sort));
}
return bookDao.list(map);
}
@Override
public int count(Map<String, Object> map){
return bookDao.count(map);
}
@Override
public int save(BookDO book){
book.setVisitCount(0l);
if(book.getUpdateTime() == null){
book.setUpdateTime(new Date());
}
return bookDao.save(book);
}
@Override
public int update(BookDO book){
return bookDao.update(book);
}
@Transactional
@Override
public int remove(Long id){
int rows = bookDao.remove(id);
bookIndexDao.removeByBookIds(id+"");
bookContentDao.removeByBookIds(id+"");
return rows;
}
@Transactional
@Override
public int batchRemove(Long[] ids){
int rows = bookDao.batchRemove(ids);
String bookIds = StringUtils.join(ids,",");
bookIndexDao.removeByBookIds(bookIds);
bookContentDao.removeByBookIds(bookIds);
return rows;
}
@Override
@Transactional
public int saveIndexAndContent(BookIndexDO bookIndex, BookContentDO bookContent) {
Integer maxBookNum = bookIndexDao.queryMaxIndexNum(bookIndex.getBookId());
int nextIndexNum = 0;
if(maxBookNum != null){
nextIndexNum = maxBookNum + 1;
}
bookIndex.setIndexNum(nextIndexNum);
bookContent.setBookId(bookIndex.getBookId());
bookContent.setIndexNum(nextIndexNum);
bookDao.uptUpdateTime(bookIndex.getBookId(),new Date());
bookIndexDao.save(bookIndex);
bookContentDao.save(bookContent);
return 1;
}
@Override
public List<BookIndexVO> indexVOList(Query query) {
return bookIndexDao.listVO(query);
}
@Override
public int indexVOCount(Query query) {
return bookIndexDao.countVO(query);
}
@Override
@Transactional
public int indexRemove(Long id, Long bookId) {
bookContentDao.removeByBookIds(id+"");
return bookIndexDao.remove(id);
}
@Transactional
@Override
public int batchIndexRemove(Long[] ids, Long[] bookIds) {
bookContentDao.removeByBookIds(StringUtils.join(ids,","));
return bookIndexDao.batchRemove(ids);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveBookAndIndexAndContent(BookDO book, List<BookIndexDO> bookIndex, List<BookContentDO> bookContent) {
Long bookId = -1L;
book.setBookName(book.getBookName().trim());
book.setAuthor(book.getAuthor().trim());
Map<String, Object> bookExample = new HashMap<>();
bookExample.put("bookName", book.getBookName());
bookExample.put("author", book.getAuthor());
List<BookDO> books = bookDao.list(bookExample);
if (books.size() > 0) {
//更新
bookId = books.get(0).getId();
book.setId(bookId);
bookDao.update(book);
} else {
if (book.getVisitCount() == null) {
Long visitCount = generateVisiteCount(book.getScore());
book.setVisitCount(visitCount);
}
//插入
int rows = bookDao.save(book);
if (rows > 0) {
bookId = book.getId();
}
}
if (bookId >= 0) {
List<BookIndexDO> newBookIndexList = new ArrayList<>();
List<BookContentDO> newContentList = new ArrayList<>();
for (int i = 0; i < bookIndex.size(); i++) {
BookContentDO bookContentItem = bookContent.get(i);
if (!bookContentItem.getContent().contains("正在手打中,请稍等片刻,内容更新后,需要重新刷新页面,才能获取最新更新")) {
BookIndexDO bookIndexItem = bookIndex.get(i);
bookIndexItem.setBookId(bookId);
bookContentItem.setBookId(bookId);
bookContentItem.setIndexNum(bookIndexItem.getIndexNum());
newBookIndexList.add(bookIndexItem);
newContentList.add(bookContentItem);
}
}
if (newBookIndexList.size() > 0) {
bookIndexDao.insertBatch(newBookIndexList);
bookContentDao.insertBatch(newContentList);
}
}
}
private Long generateVisiteCount(Float score) {
return Long.parseLong((int)(score*10000) + new Random().nextInt(1000) + "");
}
}

View File

@ -0,0 +1,71 @@
package com.java2nb.books.util;
import lombok.SneakyThrows;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.List;
public class RestTemplateUtil {
@SneakyThrows
public static RestTemplate getInstance(String charset) {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
//忽略证书
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", csf)
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
//连接池的最大连接数0代表不限如果取0需要考虑连接泄露导致系统崩溃的后果
connectionManager.setMaxTotal(1000);
//每个路由的最大连接数,如果只调用一个地址,可以将其设置为最大连接数
connectionManager.setDefaultMaxPerRoute(300);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
requestFactory.setConnectionRequestTimeout(3000);
requestFactory.setConnectTimeout(3000);
requestFactory.setReadTimeout(10000);
RestTemplate restTemplate = new RestTemplate(requestFactory);
List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> httpMessageConverter : list) {
if(httpMessageConverter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) httpMessageConverter).setDefaultCharset(Charset.forName(charset));
break;
}
}
return restTemplate;
}
}

View File

@ -0,0 +1,38 @@
package com.java2nb.books.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringUtil {
private static Pattern linePattern = Pattern.compile("_(\\w)");
/**
* 下划线转驼峰
*/
public static String lineToHump(String str) {
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
private static Pattern humpPattern = Pattern.compile("[A-Z]");
/**
* 驼峰转下划线
*/
public static String humpToLine(String str) {
Matcher matcher = humpPattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}

View File

@ -0,0 +1,12 @@
package com.java2nb.books.vo;
import com.java2nb.books.domain.BookIndexDO;
import lombok.Data;
@Data
public class BookIndexVO extends BookIndexDO {
private String bookName;
}

View File

@ -0,0 +1,11 @@
crawl:
#爬虫线程数
threadCount: 1
#爬取优先级 1评分优先 2更新时间优先
priority: 1
#小说最低评分
lowestScore: 7.8
#小说最小更新时间
minUptTime: 2000-01-01
#爬取最大条数
maxNumber: 100000

View File

@ -0,0 +1,94 @@
java2nb:
uploadPath: /var/java2nb/uploaded_files/
username: admin
password: 111111
server:
session-timeout: 18000
# tomcat:
# max-threads: 1000
# min-spare-threads: 30
port: 80
# uri-encoding: utf-8
#security:
# basic:
# enabled: false
spring:
thymeleaf:
mode: LEGACYHTML5
cache: false
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
servlet:
multipart:
max-file-size: 30Mb
max-request-size: 30Mb
devtools:
restart:
enabled: true
cache:
type: redis
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/books?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: test123456
#password:
initialSize: 1
minIdle: 3
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
#useGlobalDataSourceStat: true
redis:
host: 127.0.0.1
port: 6379
password: test
# 连接超时时间(毫秒)
timeout: 10000
jedis:
pool:
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 10
# 连接池最大连接数(使用负值表示没有限制)
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
profiles:
include: crawl
mybatis:
configuration:
#自动将数据库带下划线的表字段值映射到Java类的驼峰字段上
map-underscore-to-camel-case: true
mapper-locations: mybatis/**/*Mapper.xml
typeAliasesPackage: com.java2nb.**.domain
logging:
level:
root: info
com.java2nb: debug

View File

@ -0,0 +1,6 @@
__ ________ ___.
|__|____ ___ _______ \_____ \ ____\_ |__
| \__ \\ \/ /\__ \ / ____/ / \| __ \
| |/ __ \\ / / __ \_/ \| | \ \_\ \
/\__| (____ /\_/ (____ /\_______ \___| /___ /
\______| \/ \/ \/ \/ \/

View File

@ -0,0 +1,10 @@
#爬虫线程数
threadCount=1
#爬取优先级 1评分优先 2更新时间优先
priority=1
#小说最低评分
lowestScore=0
#小说最小更新时间
minUptTime=2000-01-01
#爬取最大条数
maxNumber=100000

View File

@ -0,0 +1,35 @@
#\u4EE3\u7801\u751F\u6210\u5668\uFF0C\u914D\u7F6E\u4FE1\u606F
#\u5305\u540D
srcPath=D:\\gitee\\admin-base\\java2nb\\src
package=com.java2nb.system
#\u4F5C\u8005
author=xiongxy
#Email
email=1179705413@qq.com
#\u81EA\u52A8\u53BB\u9664\u8868\u524D\u7F00\uFF0C\u9ED8\u8BA4\u662F true
autoRemovePre=true
#\u8868\u524D\u7F00(\u7C7B\u540D\u4E0D\u4F1A\u5305\u542B\u8868\u524D\u7F00)
tablePrefix=sys_
#\u7C7B\u578B\u8F6C\u6362\uFF0C\u914D\u7F6E\u4FE1\u606F
tinyint=Integer
smallint=Integer
mediumint=Integer
int=Integer
integer=Integer
bigint=Long
float=Float
double=Double
decimal=BigDecimal
bit=Boolean
char=String
varchar=String
tinytext=String
text=String
mediumtext=String
longtext=String
date=Date
datetime=Date
timestamp=Date

View File

@ -1,20 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->
<!-- appender是configuration的子节点是负责写日志的组件。 -->
<!-- ConsoleAppender把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--
<pattern>%d %p (%file:%line\)- %m%n</pattern>
-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 -->
<charset>UTF-8</charset>
@ -26,7 +26,7 @@
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过1KB时对当前日志进行分割 重命名 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/novel.log</File>
<File>logs/debug.log</File>
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- TimeBasedRollingPolicy 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
@ -49,35 +49,16 @@
<charset>UTF-8</charset>
</encoder>
</appender>
<springProfile name="dev">
<!-- ROOT 日志级别 -->
<!-- 控制台输出日志级别 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.maijinjie.springboot 为根包也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="io.github.xxyopen" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
<logger name="com.java2nb" level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
<logger name="org.zalando.logbook" level="TRACE" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
</springProfile>
<springProfile name="prod">
<!-- ROOT 日志级别 -->
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.maijinjie.springboot 为根包也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="io.github.xxyopen" level="ERROR" additivity="false">
<appender-ref ref="FILE"/>
</logger>
</springProfile>
</configuration>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.books.dao.BookContentDao">
<select id="get" resultType="com.java2nb.books.domain.BookContentDO">
select `id`,`book_id`,`index_id`,`index_num`,`content` from book_content where id = #{value}
</select>
<select id="list" resultType="com.java2nb.books.domain.BookContentDO">
select `id`,`book_id`,`index_id`,`index_num`,`content` from book_content
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="bookId != null and bookId != ''"> and book_id = #{bookId} </if>
<if test="indexId != null and indexId != ''"> and index_id = #{indexId} </if>
<if test="indexNum != null and indexNum != ''"> and index_num = #{indexNum} </if>
<if test="content != null and content != ''"> and content = #{content} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from book_content
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="bookId != null and bookId != ''"> and book_id = #{bookId} </if>
<if test="indexId != null and indexId != ''"> and index_id = #{indexId} </if>
<if test="indexNum != null and indexNum != ''"> and index_num = #{indexNum} </if>
<if test="content != null and content != ''"> and content = #{content} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.books.domain.BookContentDO" useGeneratedKeys="true" keyProperty="id">
insert into book_content
(
`id`,
`book_id`,
`index_id`,
`index_num`,
`content`
)
values
(
#{id},
#{bookId},
#{indexId},
#{indexNum},
#{content}
)
</insert>
<update id="update" parameterType="com.java2nb.books.domain.BookContentDO">
update book_content
<set>
<if test="bookId != null">`book_id` = #{bookId}, </if>
<if test="indexId != null">`index_id` = #{indexId}, </if>
<if test="indexNum != null">`index_num` = #{indexNum}, </if>
<if test="content != null">`content` = #{content}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from book_content where id = #{value}
</delete>
<delete id="batchRemove">
delete from book_content where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<insert id="insertBatch" parameterType="java.util.List">
insert into book_content (book_id, index_num, content)
values
<foreach collection="list" item="item" index="index"
separator=",">
<trim prefix="(" suffix=")" suffixOverrides=",">
#{item.bookId,jdbcType=VARCHAR},
#{item.indexNum,jdbcType=VARCHAR},
#{item.content,jdbcType=VARCHAR},
</trim>
</foreach>
</insert>
<delete id="removeByBookIds" parameterType="string">
delete from book_content where book_id in (${bookIds});
</delete>
</mapper>

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.books.dao.BookCrawlDao">
<select id="get" resultType="com.java2nb.books.domain.BookCrawlDO">
select `id`,`crawl_web_name`,`crawl_web_url`,`crawl_web_code`,`status` from book_crawl where id = #{value}
</select>
<select id="list" resultType="com.java2nb.books.domain.BookCrawlDO">
select `id`,`crawl_web_name`,`crawl_web_url`,`crawl_web_code`,`status` from book_crawl
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="crawlWebName != null and crawlWebName != ''"> and crawl_web_name = #{crawlWebName} </if>
<if test="crawlWebUrl != null and crawlWebUrl != ''"> and crawl_web_url = #{crawlWebUrl} </if>
<if test="crawlWebCode != null and crawlWebCode != ''"> and crawl_web_code = #{crawlWebCode} </if>
<if test="status != null and status != ''"> and status = #{status} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from book_crawl
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="crawlWebName != null and crawlWebName != ''"> and crawl_web_name = #{crawlWebName} </if>
<if test="crawlWebUrl != null and crawlWebUrl != ''"> and crawl_web_url = #{crawlWebUrl} </if>
<if test="crawlWebCode != null and crawlWebCode != ''"> and crawl_web_code = #{crawlWebCode} </if>
<if test="status != null and status != ''"> and status = #{status} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.books.domain.BookCrawlDO">
insert into book_crawl
(
`id`,
`crawl_web_name`,
`crawl_web_url`,
`crawl_web_code`,
`status`
)
values
(
#{id},
#{crawlWebName},
#{crawlWebUrl},
#{crawlWebCode},
#{status}
)
</insert>
<update id="update" parameterType="com.java2nb.books.domain.BookCrawlDO">
update book_crawl
<set>
<if test="crawlWebName != null">`crawl_web_name` = #{crawlWebName}, </if>
<if test="crawlWebUrl != null">`crawl_web_url` = #{crawlWebUrl}, </if>
<if test="crawlWebCode != null">`crawl_web_code` = #{crawlWebCode}, </if>
<if test="status != null">`status` = #{status}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from book_crawl where id = #{value}
</delete>
<delete id="batchRemove">
delete from book_crawl where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<update id="initStatus">
update book_crawl set status = 0
</update>
</mapper>

View File

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.books.dao.BookIndexDao">
<select id="get" resultType="com.java2nb.books.domain.BookIndexDO">
select `id`,`book_id`,`index_num`,`index_name` from book_index where id = #{value}
</select>
<select id="list" resultType="com.java2nb.books.domain.BookIndexDO">
select `id`,`book_id`,`index_num`,`index_name` from book_index
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="bookId != null and bookId != ''"> and book_id = #{bookId} </if>
<if test="indexNum != null and indexNum != ''"> and index_num = #{indexNum} </if>
<if test="indexName != null and indexName != ''"> and index_name = #{indexName} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from book_index
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="bookId != null and bookId != ''"> and book_id = #{bookId} </if>
<if test="indexNum != null and indexNum != ''"> and index_num = #{indexNum} </if>
<if test="indexName != null and indexName != ''"> and index_name = #{indexName} </if>
</where>
</select>
<select id="listVO" resultType="com.java2nb.books.vo.BookIndexVO">
select t1.`id`,t1.`book_id`,t1.`index_num`,t1.`index_name`,t2.book_name bookName from book_index t1 inner join book t2
on t1.book_id = t2.id
<where>
<if test="id != null and id != ''">and t1.id = #{id}</if>
<if test="bookId != null and bookId != ''">and t1.book_id = #{bookId}</if>
<if test="indexNum != null and indexNum != ''">and t1.index_num = #{indexNum}</if>
<if test="indexName != null and indexName != ''">and t1.index_name = #{indexName}</if>
<if test="bookName != null and bookName != ''">and t2.book_name = #{bookName}</if>
<if test="author != null and author != ''">and t2.author = #{author}</if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by t1.${sort} ${order}
</when>
<otherwise>
order by t1.book_id asc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="countVO" resultType="int">
select count(*) from book_index t1 inner join book t2
on t1.book_id = t2.id
<where>
<if test="id != null and id != ''">and t1.id = #{id}</if>
<if test="bookId != null and bookId != ''">and t1.book_id = #{bookId}</if>
<if test="indexNum != null and indexNum != ''">and t1.index_num = #{indexNum}</if>
<if test="indexName != null and indexName != ''">and t1.index_name = #{indexName}</if>
<if test="bookName != null and bookName != ''">and t2.book_name = #{bookName}</if>
<if test="author != null and author != ''">and t2.author = #{author}</if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.books.domain.BookIndexDO" useGeneratedKeys="true" keyProperty="id">
insert into book_index
(
`id`,
`book_id`,
`index_num`,
`index_name`
)
values
(
#{id},
#{bookId},
#{indexNum},
#{indexName}
)
</insert>
<update id="update" parameterType="com.java2nb.books.domain.BookIndexDO">
update book_index
<set>
<if test="bookId != null">`book_id` = #{bookId}, </if>
<if test="indexNum != null">`index_num` = #{indexNum}, </if>
<if test="indexName != null">`index_name` = #{indexName}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from book_index where id = #{value}
</delete>
<delete id="batchRemove">
delete from book_index where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<insert id="insertBatch" parameterType="java.util.List">
insert into book_index (book_id, index_num, index_name)
values
<foreach collection="list" item="item" index="index"
separator=",">
<trim prefix="(" suffix=")" suffixOverrides=",">
#{item.bookId,jdbcType=VARCHAR},
#{item.indexNum,jdbcType=VARCHAR},
#{item.indexName,jdbcType=VARCHAR},
</trim>
</foreach>
</insert>
<select id="queryMaxIndexNum" parameterType="java.lang.Long" resultType="java.lang.Integer">
select max(index_num) from book_index where book_id = #{bookId,jdbcType=VARCHAR} ;
</select>
<delete id="removeByBookIds" parameterType="string">
delete from book_index where book_id in (${bookIds});
</delete>
</mapper>

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.books.dao.BookDao">
<select id="get" resultType="com.java2nb.books.domain.BookDO">
select `id`,`catId`,`pic_url`,`book_name`,`author`,`book_desc`,`score`,`book_status`,`visit_count`,`update_time`,`soft_cat`,`soft_tag` from book where id = #{value}
</select>
<select id="list" resultType="com.java2nb.books.domain.BookDO">
select
`id`,`catId`,`pic_url`,`book_name`,`author`,`book_desc`,`score`,`book_status`,`visit_count`,`update_time`,`soft_cat`,`soft_tag`
from book
<where>
<if test="id != null and id != ''">and id = #{id}</if>
<choose>
<when test="catid != null and catid != ''">
and catId = #{catid}
</when>
<otherwise>
and catId <![CDATA[ < ]]> 8
</otherwise>
</choose>
<if test="catid != null and catid != ''"></if>
<if test="picUrl != null and picUrl != ''">and pic_url = #{picUrl}</if>
<if test="bookName != null and bookName != ''">and book_name = #{bookName}</if>
<if test="author != null and author != ''">and author = #{author}</if>
<if test="bookDesc != null and bookDesc != ''">and book_desc = #{bookDesc}</if>
<if test="score != null and score != ''">and score = #{score}</if>
<if test="bookStatus != null and bookStatus != ''">and book_status = #{bookStatus}</if>
<if test="visitCount != null and visitCount != ''">and visit_count = #{visitCount}</if>
<if test="updateTime != null and updateTime != ''">and update_time = #{updateTime}</if>
<if test="softCat != null and softCat != ''">and soft_cat = #{softCat}</if>
<if test="softTag != null and softTag != ''">and soft_tag = #{softTag}</if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from book
<where>
<if test="id != null and id != ''">and id = #{id}</if>
<if test="catid != null and catid != ''">and catId = #{catid}</if>
<if test="picUrl != null and picUrl != ''">and pic_url = #{picUrl}</if>
<if test="bookName != null and bookName != ''">and book_name = #{bookName}</if>
<if test="author != null and author != ''">and author = #{author}</if>
<if test="bookDesc != null and bookDesc != ''">and book_desc = #{bookDesc}</if>
<if test="score != null and score != ''">and score = #{score}</if>
<if test="bookStatus != null and bookStatus != ''">and book_status = #{bookStatus}</if>
<if test="visitCount != null and visitCount != ''">and visit_count = #{visitCount}</if>
<if test="updateTime != null and updateTime != ''">and update_time = #{updateTime}</if>
<if test="softCat != null and softCat != ''">and soft_cat = #{softCat}</if>
<if test="softTag != null and softTag != ''">and soft_tag = #{softTag}</if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.books.domain.BookDO" useGeneratedKeys="true" keyProperty="id">
insert into book
(
`catId`,
`pic_url`,
`book_name`,
`author`,
`book_desc`,
`score`,
`book_status`,
`visit_count`,
`update_time`,
`soft_cat`,
`soft_tag`
)
values
(
#{catid},
#{picUrl},
#{bookName},
#{author},
#{bookDesc},
#{score},
#{bookStatus},
#{visitCount},
#{updateTime},
#{softCat},
#{softTag}
)
</insert>
<update id="update" parameterType="com.java2nb.books.domain.BookDO">
update book
<set>
<if test="catid != null">`catId` = #{catid},</if>
<if test="picUrl != null">`pic_url` = #{picUrl},</if>
<if test="bookName != null">`book_name` = #{bookName},</if>
<if test="author != null">`author` = #{author},</if>
<if test="bookDesc != null">`book_desc` = #{bookDesc},</if>
<if test="score != null">`score` = #{score},</if>
<if test="bookStatus != null">`book_status` = #{bookStatus},</if>
<if test="visitCount != null">`visit_count` = #{visitCount},</if>
<if test="updateTime != null">`update_time` = #{updateTime},</if>
<if test="softCat != null">`soft_cat` = #{softCat},</if>
<if test="softTag != null">`soft_tag` = #{softTag}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from book where id = #{value}
</delete>
<delete id="batchRemove">
delete from book where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<update id="uptUpdateTime">
update book set update_time = #{updateTime} where id = #{id}
</update>
</mapper>

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.common.dao.DictDao">
<select id="get" resultType="com.java2nb.common.domain.DictDO">
select
`id`,`name`,`value`,`type`,`description`,`sort`,`parent_id`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`
from sys_dict where id = #{value}
</select>
<select id="list" resultType="com.java2nb.common.domain.DictDO">
select
`id`,`name`,`value`,`type`,`description`,`sort`,`parent_id`,`create_by`,`create_date`,`update_by`,`update_date`,`remarks`,`del_flag`
from sys_dict
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="name != null and name != ''"> and name = #{name} </if>
<if test="value != null and value != ''"> and value = #{value} </if>
<if test="type != null and type != ''"> and type = #{type} </if>
<if test="description != null and description != ''"> and description = #{description} </if>
<if test="sort != null and sort != ''"> and sort = #{sort} </if>
<if test="parentId != null and parentId != ''"> and parent_id = #{parentId} </if>
<if test="createBy != null and createBy != ''"> and create_by = #{createBy} </if>
<if test="createDate != null and createDate != ''"> and create_date = #{createDate} </if>
<if test="updateBy != null and updateBy != ''"> and update_by = #{updateBy} </if>
<if test="updateDate != null and updateDate != ''"> and update_date = #{updateDate} </if>
<if test="remarks != null and remarks != ''"> and remarks = #{remarks} </if>
<if test="delFlag != null and delFlag != ''"> and del_flag = #{delFlag} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_dict
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="name != null and name != ''"> and name = #{name} </if>
<if test="value != null and value != ''"> and value = #{value} </if>
<if test="type != null and type != ''"> and type = #{type} </if>
<if test="description != null and description != ''"> and description = #{description} </if>
<if test="sort != null and sort != ''"> and sort = #{sort} </if>
<if test="parentId != null and parentId != ''"> and parent_id = #{parentId} </if>
<if test="createBy != null and createBy != ''"> and create_by = #{createBy} </if>
<if test="createDate != null and createDate != ''"> and create_date = #{createDate} </if>
<if test="updateBy != null and updateBy != ''"> and update_by = #{updateBy} </if>
<if test="updateDate != null and updateDate != ''"> and update_date = #{updateDate} </if>
<if test="remarks != null and remarks != ''"> and remarks = #{remarks} </if>
<if test="delFlag != null and delFlag != ''"> and del_flag = #{delFlag} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.common.domain.DictDO"
useGeneratedKeys="true" keyProperty="id">
insert into sys_dict
(
`name`,
`value`,
`type`,
`description`,
`sort`,
`parent_id`,
`create_by`,
`create_date`,
`update_by`,
`update_date`,
`remarks`,
`del_flag`
)
values
(
#{name},
#{value},
#{type},
#{description},
#{sort},
#{parentId},
#{createBy},
#{createDate},
#{updateBy},
#{updateDate},
#{remarks},
#{delFlag}
)
</insert>
<update id="update" parameterType="com.java2nb.common.domain.DictDO">
update sys_dict
<set>
<if test="name != null">`name` = #{name}, </if>
<if test="value != null">`value` = #{value}, </if>
<if test="type != null">`type` = #{type}, </if>
<if test="description != null">`description` = #{description}, </if>
<if test="sort != null">`sort` = #{sort}, </if>
<if test="parentId != null">`parent_id` = #{parentId}, </if>
<if test="createBy != null">`create_by` = #{createBy}, </if>
<if test="createDate != null">`create_date` = #{createDate}, </if>
<if test="updateBy != null">`update_by` = #{updateBy}, </if>
<if test="updateDate != null">`update_date` = #{updateDate}, </if>
<if test="remarks != null">`remarks` = #{remarks}, </if>
<if test="delFlag != null">`del_flag` = #{delFlag}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from sys_dict where id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_dict where id in
<foreach item="id" collection="array" open="(" separator=","
close=")">
#{id}
</foreach>
</delete>
<select id="listType" resultType="com.java2nb.common.domain.DictDO">
select distinct `type` , description from sys_dict
</select>
</mapper>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.common.dao.FileDao">
<select id="get" resultType="com.java2nb.common.domain.FileDO">
select `id`,`type`,`url`,`create_date` from sys_file where id = #{value}
</select>
<select id="list" resultType="com.java2nb.common.domain.FileDO">
select `id`,`type`,`url`,`create_date` from sys_file
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="type != null and type != ''"> and type = #{type} </if>
<if test="url != null and url != ''"> and url = #{url} </if>
<if test="createDate != null and createDate != ''"> and create_date = #{createDate} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_file
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="type != null and type != ''"> and type = #{type} </if>
<if test="url != null and url != ''"> and url = #{url} </if>
<if test="createDate != null and createDate != ''"> and create_date = #{createDate} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.common.domain.FileDO" useGeneratedKeys="true" keyProperty="id">
insert into sys_file
(
`type`,
`url`,
`create_date`
)
values
(
#{type},
#{url},
#{createDate}
)
</insert>
<update id="update" parameterType="com.java2nb.common.domain.FileDO">
update sys_file
<set>
<if test="type != null">`type` = #{type}, </if>
<if test="url != null">`url` = #{url}, </if>
<if test="createDate != null">`create_date` = #{createDate}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from sys_file where id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_file where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.common.dao.LogDao">
<select id="get" resultType="com.java2nb.common.domain.LogDO">
select `id`,`user_id`,`username`,`operation`,`time`,`method`,`params`,`ip`,`gmt_create` from sys_log where id = #{value}
</select>
<select id="list" resultType="com.java2nb.common.domain.LogDO">
select `id`,`user_id`,`username`,`operation`,`time`,`method`,`params`,`ip`,`gmt_create` from sys_log
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="username != null and username != ''"> and username = #{username} </if>
<if test="operation != null and operation != ''"> and operation = #{operation} </if>
<if test="time != null and time != ''"> and time = #{time} </if>
<if test="method != null and method != ''"> and method = #{method} </if>
<if test="params != null and params != ''"> and params = #{params} </if>
<if test="ip != null and ip != ''"> and ip = #{ip} </if>
<if test="gmtCreate != null and gmtCreate != ''"> and gmt_create = #{gmtCreate} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_log
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="username != null and username != ''"> and username = #{username} </if>
<if test="operation != null and operation != ''"> and operation = #{operation} </if>
<if test="time != null and time != ''"> and time = #{time} </if>
<if test="method != null and method != ''"> and method = #{method} </if>
<if test="params != null and params != ''"> and params = #{params} </if>
<if test="ip != null and ip != ''"> and ip = #{ip} </if>
<if test="gmtCreate != null and gmtCreate != ''"> and gmt_create = #{gmtCreate} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.common.domain.LogDO" useGeneratedKeys="true" keyProperty="id">
insert into sys_log
(
`user_id`,
`username`,
`operation`,
`time`,
`method`,
`params`,
`ip`,
`gmt_create`
)
values
(
#{userId},
#{username},
#{operation},
#{time},
#{method},
#{params},
#{ip},
#{gmtCreate}
)
</insert>
<update id="update" parameterType="com.java2nb.common.domain.LogDO">
update sys_log
<set>
<if test="userId != null">`user_id` = #{userId}, </if>
<if test="username != null">`username` = #{username}, </if>
<if test="operation != null">`operation` = #{operation}, </if>
<if test="time != null">`time` = #{time}, </if>
<if test="method != null">`method` = #{method}, </if>
<if test="params != null">`params` = #{params}, </if>
<if test="ip != null">`ip` = #{ip}, </if>
<if test="gmtCreate != null">`gmt_create` = #{gmtCreate}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from sys_log where id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_log where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.system.dao.DeptDao">
<select id="get" resultType="com.java2nb.system.domain.DeptDO">
select
`dept_id`,`parent_id`,`name`,`order_num`,`del_flag` from sys_dept
where dept_id = #{value}
</select>
<select id="list" resultType="com.java2nb.system.domain.DeptDO">
select `dept_id`,`parent_id`,`name`,`order_num`,`del_flag` from
sys_dept
<where>
<if test="deptId != null and deptId != ''"> and dept_id = #{deptId} </if>
<if test="parentId != null and parentId != ''"> and parent_id = #{parentId} </if>
<if test="name != null and name != ''"> and name = #{name} </if>
<if test="orderNum != null and orderNum != ''"> and order_num = #{orderNum} </if>
<if test="delFlag != null and delFlag != ''"> and del_flag = #{delFlag} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by dept_id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_dept
<where>
<if test="deptId != null and deptId != ''"> and dept_id = #{deptId} </if>
<if test="parentId != null and parentId != ''"> and parent_id = #{parentId} </if>
<if test="name != null and name != ''"> and name = #{name} </if>
<if test="orderNum != null and orderNum != ''"> and order_num = #{orderNum} </if>
<if test="delFlag != null and delFlag != ''"> and del_flag = #{delFlag} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.system.domain.DeptDO"
useGeneratedKeys="true" keyProperty="deptId">
insert into sys_dept
(
`parent_id`,
`name`,
`order_num`,
`del_flag`
)
values
(
#{parentId},
#{name},
#{orderNum},
#{delFlag}
)
</insert>
<update id="update" parameterType="com.java2nb.system.domain.DeptDO">
update sys_dept
<set>
<if test="parentId != null">`parent_id` = #{parentId}, </if>
<if test="name != null">`name` = #{name}, </if>
<if test="orderNum != null">`order_num` = #{orderNum}, </if>
<if test="delFlag != null">`del_flag` = #{delFlag}</if>
</set>
where dept_id = #{deptId}
</update>
<delete id="remove">
delete from sys_dept where dept_id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_dept where dept_id in
<foreach item="deptId" collection="array" open="(" separator=","
close=")">
#{deptId}
</foreach>
</delete>
<select id="listParentDept" resultType="long">
select DISTINCT parent_id from sys_dept
</select>
<select id="getDeptUserNumber" resultType="int">
select count(*) from sys_user where dept_id = #{value}
</select>
</mapper>

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.system.dao.MenuDao">
<select id="get" resultType="com.java2nb.system.domain.MenuDO">
select
`menu_id`,`parent_id`,`name`,`url`,`perms`,`type`,`icon`,`order_num`,`gmt_create`,`gmt_modified`
from sys_menu where menu_id = #{value}
</select>
<select id="list" resultType="com.java2nb.system.domain.MenuDO">
select
`menu_id`,`parent_id`,`name`,`url`,`perms`,`type`,`icon`,`order_num`,`gmt_create`,`gmt_modified`
from sys_menu
<where>
<if test="menuId != null and menuId != ''"> and menu_id = #{menuId} </if>
<if test="parentId != null and parentId != ''"> and parent_id = #{parentId} </if>
<if test="name != null and name != ''"> and name = #{name} </if>
<if test="url != null and url != ''"> and url = #{url} </if>
<if test="perms != null and perms != ''"> and perms = #{perms} </if>
<if test="type != null and type != ''"> and type = #{type} </if>
<if test="icon != null and icon != ''"> and icon = #{icon} </if>
<if test="orderNum != null and orderNum != ''"> and order_num = #{orderNum} </if>
<if test="gmtCreate != null and gmtCreate != ''"> and gmt_create = #{gmtCreate} </if>
<if test="gmtModified != null and gmtModified != ''"> and gmt_modified = #{gmtModified} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by menu_id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_menu
<where>
<if test="menuId != null and menuId != ''"> and menu_id = #{menuId} </if>
<if test="parentId != null and parentId != ''"> and parent_id = #{parentId} </if>
<if test="name != null and name != ''"> and name = #{name} </if>
<if test="url != null and url != ''"> and url = #{url} </if>
<if test="perms != null and perms != ''"> and perms = #{perms} </if>
<if test="type != null and type != ''"> and type = #{type} </if>
<if test="icon != null and icon != ''"> and icon = #{icon} </if>
<if test="orderNum != null and orderNum != ''"> and order_num = #{orderNum} </if>
<if test="gmtCreate != null and gmtCreate != ''"> and gmt_create = #{gmtCreate} </if>
<if test="gmtModified != null and gmtModified != ''"> and gmt_modified = #{gmtModified} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.system.domain.MenuDO"
useGeneratedKeys="true" keyProperty="menuId">
insert into sys_menu
(
`parent_id`,
`name`,
`url`,
`perms`,
`type`,
`icon`,
`order_num`,
`gmt_create`,
`gmt_modified`
)
values
(
#{parentId},
#{name},
#{url},
#{perms},
#{type},
#{icon},
#{orderNum},
#{gmtCreate},
#{gmtModified}
)
</insert>
<update id="update" parameterType="com.java2nb.system.domain.MenuDO">
update sys_menu
<set>
<if test="parentId != null">`parent_id` = #{parentId}, </if>
<if test="name != null">`name` = #{name}, </if>
<if test="url != null">`url` = #{url}, </if>
<if test="perms != null">`perms` = #{perms}, </if>
<if test="type != null">`type` = #{type}, </if>
<if test="icon != null">`icon` = #{icon}, </if>
<if test="orderNum != null">`order_num` = #{orderNum}, </if>
<if test="gmtCreate != null">`gmt_create` = #{gmtCreate}, </if>
<if test="gmtModified != null">`gmt_modified` = #{gmtModified}</if>
</set>
where menu_id = #{menuId}
</update>
<delete id="remove">
delete from sys_menu where menu_id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_menu where menu_id in
<foreach item="menuId" collection="array" open="(" separator=","
close=")">
#{menuId}
</foreach>
</delete>
<select id="listMenuByUserId" resultType="com.java2nb.system.domain.MenuDO">
select distinct
m.menu_id , parent_id, name, url,
perms,`type`,icon,order_num,gmt_create, gmt_modified
from sys_menu m
left
join sys_role_menu rm on m.menu_id = rm.menu_id left join
sys_user_role ur
on rm.role_id =ur.role_id where ur.user_id = #{id}
and
m.type in(0,1)
order by
m.order_num
</select>
<select id="listUserPerms" resultType="string">
select distinct m.perms
from sys_menu m left join
sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur
on rm.role_id = ur.role_id where ur.user_id
= #{id}
</select>
</mapper>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.system.dao.RoleDao">
<select id="get" resultType="com.java2nb.system.domain.RoleDO">
select
`role_id`,`role_name`,`role_sign`,`remark`,`user_id_create`,`gmt_create`,`gmt_modified`
from sys_role where role_id = #{value}
</select>
<select id="list" resultType="com.java2nb.system.domain.RoleDO">
select
`role_id`,`role_name`,`role_sign`,`remark`,`user_id_create`,`gmt_create`,`gmt_modified`
from sys_role
<where>
<if test="roleId != null and roleId != ''"> and role_id = #{roleId} </if>
<if test="roleName != null and roleName != ''"> and role_name = #{roleName} </if>
<if test="roleSign != null and roleSign != ''"> and role_sign = #{roleSign} </if>
<if test="remark != null and remark != ''"> and remark = #{remark} </if>
<if test="userIdCreate != null and userIdCreate != ''"> and user_id_create = #{userIdCreate} </if>
<if test="gmtCreate != null and gmtCreate != ''"> and gmt_create = #{gmtCreate} </if>
<if test="gmtModified != null and gmtModified != ''"> and gmt_modified = #{gmtModified} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by role_id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_role
<where>
<if test="roleId != null and roleId != ''"> and role_id = #{roleId} </if>
<if test="roleName != null and roleName != ''"> and role_name = #{roleName} </if>
<if test="roleSign != null and roleSign != ''"> and role_sign = #{roleSign} </if>
<if test="remark != null and remark != ''"> and remark = #{remark} </if>
<if test="userIdCreate != null and userIdCreate != ''"> and user_id_create = #{userIdCreate} </if>
<if test="gmtCreate != null and gmtCreate != ''"> and gmt_create = #{gmtCreate} </if>
<if test="gmtModified != null and gmtModified != ''"> and gmt_modified = #{gmtModified} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.system.domain.RoleDO"
useGeneratedKeys="true" keyProperty="roleId">
insert into sys_role
(
`role_name`,
`role_sign`,
`remark`,
`user_id_create`,
`gmt_create`,
`gmt_modified`
)
values
(
#{roleName},
#{roleSign},
#{remark},
#{userIdCreate},
#{gmtCreate},
#{gmtModified}
)
</insert>
<update id="update" parameterType="com.java2nb.system.domain.RoleDO">
update sys_role
<set>
<if test="roleName != null">`role_name` = #{roleName}, </if>
<if test="roleSign != null">`role_sign` = #{roleSign}, </if>
<if test="remark != null">`remark` = #{remark}, </if>
<if test="userIdCreate != null">`user_id_create` = #{userIdCreate}, </if>
<if test="gmtCreate != null">`gmt_create` = #{gmtCreate}, </if>
<if test="gmtModified != null">`gmt_modified` = #{gmtModified}</if>
</set>
where role_id = #{roleId}
</update>
<delete id="remove">
delete from sys_role where role_id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_role where role_id in
<foreach item="roleId" collection="array" open="(" separator=","
close=")">
#{roleId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.system.dao.RoleMenuDao">
<select id="get" resultType="com.java2nb.system.domain.RoleMenuDO">
select `id`,`role_id`,`menu_id` from
sys_role_menu where id = #{value}
</select>
<select id="list" resultType="com.java2nb.system.domain.RoleMenuDO">
select `id`,`role_id`,`menu_id` from sys_role_menu
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="roleId != null and roleId != ''"> and role_id = #{roleId} </if>
<if test="menuId != null and menuId != ''"> and menu_id = #{menuId} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_role_menu
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="roleId != null and roleId != ''"> and role_id = #{roleId} </if>
<if test="menuId != null and menuId != ''"> and menu_id = #{menuId} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.system.domain.RoleMenuDO"
useGeneratedKeys="true" keyProperty="id">
insert into sys_role_menu
(
`role_id`,
`menu_id`
)
values
(
#{roleId},
#{menuId}
)
</insert>
<update id="update" parameterType="com.java2nb.system.domain.RoleMenuDO">
update sys_role_menu
<set>
<if test="roleId != null">`role_id` = #{roleId}, </if>
<if test="menuId != null">`menu_id` = #{menuId}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from sys_role_menu where id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_role_menu where id in
<foreach item="id" collection="array" open="(" separator=","
close=")">
#{id}
</foreach>
</delete>
<select id="listMenuIdByRoleId" resultType="long">
select menu_id from sys_role_menu
<where>role_id = #{roleId}</where>
</select>
<delete id="removeByRoleId">
DELETE FROM sys_role_menu WHERE role_id=#{roleId}
</delete>
<delete id="removeByMenuId">
DELETE FROM sys_role_menu WHERE menu_id=#{menuId}
</delete>
<insert id="batchSave">
INSERT INTO sys_role_menu(role_id, menu_id) values
<foreach item="item" index="index" collection="list"
separator=",">
(#{item.roleId},#{item.menuId})
</foreach>
</insert>
</mapper>

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.system.dao.UserDao">
<select id="get" resultType="com.java2nb.system.domain.UserDO">
select `user_id`,`username`,`name`,`password`,`dept_id`,`email`,`mobile`,`status`,`user_id_create`,`gmt_create`,`gmt_modified`,`sex`,`birth`,`pic_id`,`live_address`,`hobby`,`province`,`city`,`district` from sys_user where user_id = #{value}
</select>
<select id="list" resultType="com.java2nb.system.domain.UserDO">
select
`user_id`,`username`,`name`,`password`,`dept_id`,`email`,`mobile`,`status`,`user_id_create`,`gmt_create`,`gmt_modified`,`sex`,`birth`,`pic_id`,`live_address`,`hobby`,`province`,`city`,`district`
from sys_user
<where>
<if test="userId != null and userId != ''">and user_id = #{userId}</if>
<if test="username != null and username != ''">and username = #{username}</if>
<if test="name != null and name != ''">and name = #{name}</if>
<if test="password != null and password != ''">and password = #{password}</if>
<if test="deptId != null and deptId != ''">and dept_id = #{deptId}</if>
<if test="deptIds != null and deptIds.size() > 0">and dept_id in
<foreach collection="deptIds" item="item" index="index" separator="," open="(" close=")">
#{item}
</foreach>
</if>
<if test="email != null and email != ''">and email = #{email}</if>
<if test="mobile != null and mobile != ''">and mobile = #{mobile}</if>
<if test="status != null and status != ''">and status = #{status}</if>
<if test="userIdCreate != null and userIdCreate != ''">and user_id_create = #{userIdCreate}</if>
<if test="gmtCreate != null and gmtCreate != ''">and gmt_create = #{gmtCreate}</if>
<if test="gmtModified != null and gmtModified != ''">and gmt_modified = #{gmtModified}</if>
<if test="sex != null and sex != ''">and sex = #{sex}</if>
<if test="birth != null and birth != ''">and birth = #{birth}</if>
<if test="picId != null and picId != ''">and pic_id = #{picId}</if>
<if test="liveAddress != null and liveAddress != ''">and live_address = #{liveAddress}</if>
<if test="hobby != null and hobby != ''">and hobby = #{hobby}</if>
<if test="province != null and province != ''">and province = #{province}</if>
<if test="city != null and city != ''">and city = #{city}</if>
<if test="district != null and district != ''">and district = #{district}</if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by user_id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_user
<where>
<if test="userId != null and userId != ''">and user_id = #{userId}</if>
<if test="username != null and username != ''">and username = #{username}</if>
<if test="name != null and name != ''">and name = #{name}</if>
<if test="password != null and password != ''">and password = #{password}</if>
<if test="deptId != null and deptId != ''">and dept_id = #{deptId}</if>
<if test="email != null and email != ''">and email = #{email}</if>
<if test="mobile != null and mobile != ''">and mobile = #{mobile}</if>
<if test="status != null and status != ''">and status = #{status}</if>
<if test="userIdCreate != null and userIdCreate != ''">and user_id_create = #{userIdCreate}</if>
<if test="gmtCreate != null and gmtCreate != ''">and gmt_create = #{gmtCreate}</if>
<if test="gmtModified != null and gmtModified != ''">and gmt_modified = #{gmtModified}</if>
<if test="sex != null and sex != ''">and sex = #{sex}</if>
<if test="birth != null and birth != ''">and birth = #{birth}</if>
<if test="picId != null and picId != ''">and pic_id = #{picId}</if>
<if test="liveAddress != null and liveAddress != ''">and live_address = #{liveAddress}</if>
<if test="hobby != null and hobby != ''">and hobby = #{hobby}</if>
<if test="province != null and province != ''">and province = #{province}</if>
<if test="city != null and city != ''">and city = #{city}</if>
<if test="district != null and district != ''">and district = #{district}</if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.system.domain.UserDO" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user
(
`username`,
`name`,
`password`,
`dept_id`,
`email`,
`mobile`,
`status`,
`user_id_create`,
`gmt_create`,
`gmt_modified`,
`sex`,
`birth`,
`pic_id`,
`live_address`,
`hobby`,
`province`,
`city`,
`district`
)
values
(
#{username},
#{name},
#{password},
#{deptId},
#{email},
#{mobile},
#{status},
#{userIdCreate},
#{gmtCreate},
#{gmtModified},
#{sex},
#{birth},
#{picId},
#{liveAddress},
#{hobby},
#{province},
#{city},
#{district}
)
</insert>
<update id="update" parameterType="com.java2nb.system.domain.UserDO">
update sys_user
<set>
<if test="username != null">`username` = #{username},</if>
<if test="name != null">`name` = #{name},</if>
<if test="password != null">`password` = #{password},</if>
<if test="deptId != null">`dept_id` = #{deptId},</if>
<if test="email != null">`email` = #{email},</if>
<if test="mobile != null">`mobile` = #{mobile},</if>
<if test="status != null">`status` = #{status},</if>
<if test="userIdCreate != null">`user_id_create` = #{userIdCreate},</if>
<if test="gmtCreate != null">`gmt_create` = #{gmtCreate},</if>
<if test="gmtModified != null">`gmt_modified` = #{gmtModified},</if>
<if test="sex != null">`sex` = #{sex},</if>
<if test="birth != null">`birth` = #{birth},</if>
<if test="picId != null">`pic_id` = #{picId},</if>
<if test="liveAddress != null">`live_address` = #{liveAddress},</if>
<if test="hobby != null">`hobby` = #{hobby},</if>
<if test="province != null">`province` = #{province},</if>
<if test="city != null">`city` = #{city},</if>
<if test="district != null">`district` = #{district}</if>
</set>
where user_id = #{userId}
</update>
<delete id="remove">
delete from sys_user where user_id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_user where user_id in
<foreach item="userId" collection="array" open="(" separator="," close=")">
#{userId}
</foreach>
</delete>
<select id="listAllDept" resultType="long">
select DISTINCT dept_id from sys_user
</select>
</mapper>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.java2nb.system.dao.UserRoleDao">
<select id="get" resultType="com.java2nb.system.domain.UserRoleDO">
select `id`,`user_id`,`role_id` from
sys_user_role where id = #{value}
</select>
<select id="list" resultType="com.java2nb.system.domain.UserRoleDO">
select `id`,`user_id`,`role_id` from sys_user_role
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="roleId != null and roleId != ''"> and role_id = #{roleId} </if>
</where>
<choose>
<when test="sort != null and sort.trim() != ''">
order by ${sort} ${order}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</select>
<select id="count" resultType="int">
select count(*) from sys_user_role
<where>
<if test="id != null and id != ''"> and id = #{id} </if>
<if test="userId != null and userId != ''"> and user_id = #{userId} </if>
<if test="roleId != null and roleId != ''"> and role_id = #{roleId} </if>
</where>
</select>
<insert id="save" parameterType="com.java2nb.system.domain.UserRoleDO"
useGeneratedKeys="true" keyProperty="id">
insert into sys_user_role
(
`user_id`,
`role_id`
)
values
(
#{userId},
#{roleId}
)
</insert>
<update id="update" parameterType="com.java2nb.system.domain.UserRoleDO">
update sys_user_role
<set>
<if test="userId != null">`user_id` = #{userId}, </if>
<if test="roleId != null">`role_id` = #{roleId}</if>
</set>
where id = #{id}
</update>
<delete id="remove">
delete from sys_user_role where id = #{value}
</delete>
<delete id="batchRemove">
delete from sys_user_role where id in
<foreach item="id" collection="array" open="(" separator=","
close=")">
#{id}
</foreach>
</delete>
<select id="listRoleId" resultType="long">
select role_id from
sys_user_role where
user_id=#{userId}
</select>
<delete id="removeByUserId">
delete from sys_user_role where user_id=#{userId}
</delete>
<delete id="removeByRoleId">
delete from sys_user_role where role_id=#{roleId}
</delete>
<delete id="batchRemoveByUserId">
delete from sys_user_role where user_id in
<foreach item="id" collection="array" open="(" separator=","
close=")">
#{id}
</foreach>
</delete>
<insert id="batchSave">
INSERT INTO sys_user_role(user_id, role_id) values
<foreach item="item" index="index" collection="list"
separator=",">
(#{item.userId},#{item.roleId})
</foreach>
</insert>
</mapper>

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