refactor: 基于 novel 项目 & Spring Cloud 2022 & Spring Cloud Alibaba 2022 重构

This commit is contained in:
xiongxiaoyang 2023-03-30 16:15:56 +08:00
parent d68ce51c82
commit 3d098eea5e
505 changed files with 14127 additions and 24067 deletions

201
LICENSE
View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,36 +0,0 @@
# novel-cloud
#### Description
小说门户网站提供文学阅读与写作平台。基于Spring Cloud Alibaba 微服务构建,可用于学习和商用。
#### 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/)

162
README.md
View File

@ -1,97 +1,107 @@
[![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-cloud'><img alt="Github stars" src="https://img.shields.io/github/stars/201206030/novel-cloud?logo=github"></a>
<a href='https://github.com/201206030/novel-cloud'><img alt="Github forks" src="https://img.shields.io/github/forks/201206030/novel-cloud?logo=github"></a>
<a href='https://gitee.com/novel_dev_team/novel-cloud'><img alt="Gitee stars" src="https://gitee.com/novel_dev_team/novel-cloud/badge/star.svg?theme=gitee"></a>
<a href='https://gitee.com/novel_dev_team/novel-cloud'><img alt="Gitee forks" src="https://gitee.com/novel_dev_team/novel-cloud/badge/fork.svg?theme=gitee"></a>
<a href="https://github.com/201206030/novel-cloud"><img src="https://visitor-badge.glitch.me/badge?page_id=201206030.novel-cloud" alt="visitors"></a>
<a href='https://docs.oracle.com/en/java/javase/17'><img alt="Java 17" src="https://img.shields.io/badge/Java%2017-%234479A1.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAABNVBMVEUAAABkmP9ml/9mmf9mmf9lmv9nmf9mmf9mmf9nmP9mmf9mmf9mmv9mmf9mmf9mmf9mmf9mmP9llv9mmf9mmf9mmv9mmf9mmf9mmf9mmf//AABlmf9mmf9km/9mmf9mmf9lmf9mmf9mmf//AABmmf9mmf9mmf9lmv9mmf//AABmmf9mmP9mmf9mmf//AABgl/9mmf//AABmmP//AABmmf//AAD/AABmmf9mmv9mmf//AABnmf//AAD/AAD/AABmmf//AAD/AABlmf9mmf//AABmmf9mmv9mmf//AAD/AAD/AABmmf//AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AABmmf//AAD/AAD/AABsof9mmf//AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AABmmf//AAB37HanAAAAZXRSTlMAP4CLnb8dtpUP2plK78zEpyoKrGbVbxj334BjRzL7sVA168C8hXlEIwvJYJBXQQahWC8k5M6nW1Q6Myb2ya5yY0gT0rp9dWpSEerm35JtH5l7Xhjnzo2EdATz2dOfiDst8AW1KD5Fo/kAAAl3SURBVHja3Ny7ruIwEAbg/zloU9FEiqJQoCQiEsUh4k4ESNw56H//R1gHlsQk8TnbrcdfS8OIsT2escB/MoEjlnDEfAQ3ZMUDTlgwhRvIIZyQcAcneDzc4QKPDOACj3TjLPHICC7wSMIFR5JOFFxUXDjcQyoXyJeRbpzteyoLyOdR6UO8kMoN8u2pjCGfR+UM8b5IOlE0jlkKId2aigt33YQl+X2UPUu3DYTzqThwrZokLMVXCLfk0xbC9fiUSy8Ye3zpQbYRXyLhha9P0oXqpIpjANGqOGLZd1yfdGKlB3QjsVZ8SyDZiW+55GnCxmMlxE/sPl/8gpULzL52X7DZiDUfBv0g5dnu3+P8exyT9SDmt92t4E36axzDWU4Wc1jtEv0WR5BSOVneUlnffo5jsTpSiexe5MCOmhBN/jKmYvsix2TAWjFBw/D1se2LHBgmrI3v+LQ582UPy2UFa0s0zKd8Omaw3IiabTPIMV8G1nfpVtT08GEx418r2G5Lzbw7q3iwPq1woiaAblJ9ltrf2vpmLQ+huySC7rsD1o74MLrxJbb9LFfmrHndfUbmPqy3/oc4pgKuu196HHfoepLaD48pK8nG8HvAfvcxK8W1ddTLGfHMWFtDd81JihmCBub6KpXUZ+xHrIwNtVcuIbF6rA2hu7Ik5gFKwsqp684r5dXcwtho6E+piHnaFLCStm9ZgqbSO9PWizHfBNSKevUe9xs5JysQz5RZGUkpPZPPQALjtnyCAN+mPbZHWXO3Hd8WxkBiCQ/7A7712/WJpDcPG77dW8eIrNl0tdo3rV1L1gZcrYWHuXZhJGCVLG6G0W1EUlSVMjMce1sKS65hdxsIGaUl18AwZjvwRcxL2cwwL5jxwxrWW/Jp2siex426qeXDaGUSdS/3FUlZx6LPp0O/3WDRWf7OobTv/qYZPxwtH63XO1dkmCrKGR8iPHQnT0rdAfbLYipF2AxwSp39k1Bg1H2rDaRtXMCuu6Y6U3OEBMvul/xj1nKIkHY2rK8FKzFk8Kj4HatH0gCuukwl7eSS1RiqSvcZGkYSX/oXHd2fkCVp/5Nw6yjYj+IyqxS3z72ZoEbdn3bu/HVpMI4D+Gf37S63uXRebSoeKCKoGQl+UyMpouiEIIhP//+fULoOc1/LdFsuev0ssrfu+Tx7ru15HHnmevUpmyeO7x6OTN6HvWH2Xony5OA9Wh+zMmiPuHP/RaSxP4Eserp/2fcys7R7i+d7Jfh1Zv+PrUd7cxCZ6tIj7n1vMNnO8SPQ/cdZrFdRD+9mYSvK7716kIHZrBM8ewOn8myKNn0p78EV+vACTmKQFQW/q6yHkBZ9QvKabxXaVFWAizVzBWYQ8JU6fiMJkDi9Q1u4xdkexGJCEm9hpyrhV7kmJEm3NRd3mJUOMRFgj0fjVxNICkGqGFIbQ0hMNdkkNUrEkELWIFEr/IqAuBkdDr+hdUgaiSEO4uVRLn7DlSBOswnpQES/jaE5xIks4HddiIs+DiruhnR+2UwsiI/Txj02XKqvV+c8J+IWz8IRGwzNYr1f962GcB5Bl/PBgBnhd0wJjhpgqAix4fHAhiNLApzCcGa1ZrVjL/nKjYIH6vNTfj4S4pPDWyiiakrkukfsaVZ7RbtBUvzA5JiXYr2ARyk+NYO0g0A+h3Gy6GLtLYTSCxKazjmMgctRnZoBpzCTqL8hLy/l8CwFV9UoexJGOJGVWN8ecjy5+KXptt0y/pZi+XSQlz0H/pyOobIASVsMm/JkXFyvlgHF01qFYziN7gYNu9iTiZrOCn24QIAhFbLNEDE0hmyzMVSBbGttIk09YQIkQsJQAOmQIRkTDHUhDbWgA8mYpFixFnMGSUiGjl9B8joWIgMJwZALiZtp+AUPiWhhyIfk+bj1Es5jEHMDjpIxJEHyKAyRLfhDrR7lK4jos7/pCN01pIDBr95JHQ9O05+upXYZv3nZhNs4NO50WUgDg3sKucqgS86LVcJrCZHaphPVfIMacBYe4lmIqIYfqxCQjhIeVX6n1EeuaL1sq6pYx1+pSwdR3lK4pRYhNaSCMVB8aj+KrOIXZhXS1OpeGqKyai5gz1DbtbkppE0nLTyTqNnDw4rMIyITVsH0TXi1gH9mZDaaAkTYCmrFFvxFfS/Pq8pJEXzJlh24FUk338I1YEur7oBru4eJynUx55t0l+x5BhznwPUxFuxsWCOmwxnrCH3477//dmT4F3gVFv4BXeThHzB+iSJk39RERAYyz8Md0oDTOQRcHUPFkEtNT8jSkle0qiDSLbgyxE/DXXpVrBK604dDwrBUJLWbMn5TJq+syhF4m3duzucq2kDiqSAYMGIBo5TuEK6Jieejp3A9HLyEWYKrwb7EsyldHa4IKZ6XYnB1T2f9jo9/SKTHBlyjaXCDJ+PsGlyDxWzKQlSJ4jb4OyOOkv/+4LdPLBlrU/5FvWFlcqCO8BYFkeHzUwEi0p6OEJpLroBflP1GpzRc/DLwrCn3Ouv5kgwV5S+fP0OHgLiVpDpuuVKqbVQbQJxmqzbuMHkBUtXDBsSmqZVxh25C2tZ4AzFheQypMqROt2IL0nH/4jYjwsK4bi0av2lC6sj41r67+B0J6SJ2JwlsiEUH91hrFlIyLPJt/ELyYI8Q25jp3aAKSRPkgNsgRmPAFM5H4aFRZUlAMgxdtmkLv8o19IMeWYbzzRi8RZmhGz1PgLiwRIfU1M1PK9YlOFDNvYVLkBYeU29rQYdw4DyOTkzyy67mi2X8mX/LfvsFhV24zNsxV8ejwnW1NqfxwXbPw5AV4FBfWLAzvTYNt9TOG4Fkqtaxr8xRX0JE5UVUDbjY21p+cFPAhI3MFdE/viHfifFOLlJmInmUnEn1WLidt8wlssk0zJMblTEG7rZq1BZw1GzOhHWfgMQIOtGzA5r7kumcAGSHYOHXpiSDoRwBqTAcvdacdOwlRZuc2s7dWKK7qSuF8v4eIcakqUa+V6q1BDhBlXbxq1wesunnQx3tLMYQagcHUxSpBEnqCxAztmTzzAZ/Vlk7kLQW/1JbVmcxHD2Ri6T2soAR5tiBVDjFShnR9TWeXPeaHmvAyQxWn05sSgtXTaJErSG/hRS1xpT/41IKoxumsqtMTWJPSa72xsW8PV8tKUnj2mK9jEe9U/l8zYDUhY8vtIUXU244mqz+9WXFfosYN/hKro5/aNQ2u6sx0bq6afldoqArbc+Dtm/EUeREaGET3n/rbc+4gP+iPgNo04Ue6Gbq9gAAAABJRU5ErkJggg=="></a>
<a href='https://docs.spring.io/spring-boot/docs/3.0.0-SNAPSHOT/reference/html'><img alt="Spring Boot 3" src="https://img.shields.io/badge/Spring%20Boot%203-%23000000.svg?logo=springboot"></a>
<a href='https://staging-cn.vuejs.org'><img alt="Vue 3" src="https://img.shields.io/badge/Vue%203%20-%232b3847.svg?logo=vue.js"></a><br/>
<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>
<a href="https://github.com/201206030/novel"><img src="https://visitor-badge.glitch.me/badge?page_id=201206030.novel" alt="visitors"></a>
</p>
<p align="center">
👉<a href='https://docs.xxyopen.com/course/novelcloud/'>项目文档</a> | <a href='https://novel.xxyopen.com'>👉官网</a> | <a href='http://47.106.243.172:8888'>👉演示站点</a>
</p>
## 项目背景
### 学习版
小说网站业务难度适中,没有商城系统那种复杂的业务。但是作为互联网项目,一样需要面对大规模用户和海量数据的处理,所以高并发、高可用、高性能、高容错、可扩展性、可维护性也是小说网站设计需要考虑的问题,商城系统中所用到的技术同样适用于小说网站。综上所述,使用微服务架构来构建一个小说门户平台是非常有必要的,利用微服务构建的小说门户平台来学习现下流行技术相较于业务比较复杂的商场系统来说也是比较容易的,非常适合于没有实际微服务项目经验的同学用来学习和入门微服务技术栈。
[基于 Sprint Boot 3 + Vue 3 开发的前后端分离学习型小说项目](https://github.com/201206030/novel)
## 项目简介
### 项目背景
novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离**学习型**
小说项目,配备 [保姆级教程](https://docs.xxyopen.com/course/novel) 手把手教你**从零开始**开发上线一套生产级别的 Java
系统,由小说门户系统、作家后台管理系统、平台后台管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、会员中心、作家专区、充值订阅、新闻发布等功能。
novel-cloud 是 novel 项目的微服务版本,基于 `Spring Cloud 2022` & `Spring Cloud Alibaba 2022` 构建,数据结构、后端接口和 novel 项目保持完全一致Vue 3 开发的前端能无缝对接这两个项目。
小说网站业务难度适中,没有商城系统那种复杂的业务。但是作为互联网项目,一样需要面对大规模用户和海量数据的处理,所以高并发、高可用、高性能、高容错、可扩展性、可维护性也是小说网站设计需要考虑的问题,商城系统中所用到的技术同样适用于小说网站。
## 项目地址
综上所述,使用微服务架构来构建一个小说门户平台是非常有必要的,利用微服务技术栈构建的小说门户平台学习时下流行技术相较于业务比较复杂的商城系统来说也是比较容易的,非常适合没有实际微服务项目经验的同学用来学习和入门微服务技术栈。
- 单体架构后端项目:[GitHub](https://github.com/201206030/novel) [码云](https://gitee.com/novel_dev_team/novel) | [文档](https://docs.xxyopen.com/course/novel)
- 微服务架构后端项目:[GitHub](https://github.com/201206030/novel-cloud) [码云](https://gitee.com/novel_dev_team/novel-cloud) [文档](https://docs.xxyopen.com/course/novelcloud)
- 前端项目:[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)
### 项目简介
## 开发环境
novel-cloud 是基于 [novel-plus](https://github.com/201206030/novel-plus) 构建的 Spring Cloud 微服务架构小说门户平台,致力于原创文学阅读与写作,提供了爬虫工具用于开发过程中测试数据的采集(爬虫项目和 novel-plus 通用)。采用了 Spring Boot 2.2.5.RELEASE 、Spring Cloud Hoxton.SR4、 MyBatis3 Dynamic SQL、Sharding-JDBC、Redis、RabbitMQ、Elasticsearch、Docker 等流行技术,集成了 Nacos 注册中心/配置中心、Spring Cloud Gateway 网关、Spring Boot Admin 监控中心、ELK 分布式日志分析等基础服务。
- MySQL 8.0
- Redis 7.0
- Elasticsearch 8.6.2
- RabbitMQ 3.x
- XXL-JOB 2.3.1
- Nacos 2.2.1
- JDK 17
- Maven 3.8
- IntelliJ IDEA 2021.3(可选)
- Node 16.14
### 项目结构
## 后端技术选型
| 技术 | 版本 | 说明 | 官网 | 学习 |
|----------------------|:--------------:|-----------------------------------| -------------------------------------- |:-----------------------------------------------------------------------------------------------------------------------------:|
| Spring Cloud | 2022.0.1 | 微服务开发的一站式解决方案 | https://spring.io/projects/spring-cloud | [进入](https://docs.spring.io/spring-cloud/docs/current/reference/html/) |
| Spring Cloud Alibaba | 2022.0.0.0-RC1 | 阿里巴巴贡献的 Spring Cloud 微服务开发一站式解决方案 | https://github.com/alibaba/spring-cloud-alibaba | [进入](https://spring-cloud-alibaba-group.github.io/github-pages/2021/zh-cn/2021.0.5.0/index.html) |
| Nacos | 2.2.1 | 服务发现和配置管理 | https://nacos.io | [进入](https://nacos.io/zh-cn/docs/what-is-nacos.html) |
| Spring Boot Admin | 3.0.2 | 微服务管理和监控 | https://github.com/codecentric/spring-boot-admin | [进入](https://codecentric.github.io/spring-boot-admin/3.0.0-M1) |
| Spring Boot | 3.0.5 | 容器 + MVC 框架 | https://spring.io/projects/spring-boot | [进入](https://docs.spring.io/spring-boot/docs/3.0.0/reference/html) |
| 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) |
| RabbitMQ | 3.x | 开源消息中间件 | https://www.rabbitmq.com | [进入](https://www.rabbitmq.com/tutorials/tutorial-one-java.html) |
| MySQL | 8.0 | 数据库服务 | https://www.mysql.com | [进入](https://docs.oracle.com/en-us/iaas/mysql-database/doc/getting-started.html) |
| ShardingSphere-JDBC | 5.1.1 | 数据库分库分表支持 | https://shardingsphere.apache.org | [进入](https://shardingsphere.apache.org/document/5.1.1/cn/overview) |
| Elasticsearch | 8.6.2 | 搜索引擎服务 | https://www.elastic.co | [进入](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) |
| XXL-JOB | 2.3.1 | 分布式任务调度平台 | https://www.xuxueli.com/xxl-job | [进入](https://www.xuxueli.com/xxl-job) |
| Springdoc-openapi | 2.0.0 | Swagger 3 接口文档自动生成 | https://github.com/springdoc/springdoc-openapi | [进入](https://springdoc.org/) |
| Undertow | 2.2.17.Final | Java 开发的高性能 Web 服务器 | https://undertow.io | [进入](https://undertow.io/documentation.html) |
**注:更多热门新技术待集成。**
## 前端技术选型
| 技术 | 版本 | 说明 | 官网 | 学习 |
| :----------------- | :-----: | -------------------------- | --------------------------------------- | :-------------------------------------------------: |
| 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) |
## 软件架构
![QQ20200520-215756](https://s3.ax1x.com/2020/12/09/r92rrT.png)
👉 [克隆架构图](https://www.processon.com/view/5fd028fbe0b34d425254e710)
## 项目结构
```
novel-cloud
├── novel-common -- 通用模块,供其他业务微服务模块依赖
├── novel-gen -- 持久层代码生成器,集成 Swagger
├── novel-gateway -- 基于 Spring Cloud Gateway 构建的网关服务
├── novel-monitor -- 基于 Spring Boot Admin 构建的监控中心
├── novel-search -- 基于 Elasticsearch 构建的搜索微服务
├── novel-file -- 基于 Aliyun OSS 构建的文件微服务
├── novel-home -- 门户首页微服务
├── novel-news -- 新闻中心微服务
├── novel-user -- 用户中心微服务
├── novel-author -- 作家中心微服务
├── novel-core -- 项目核心模块,供其它各个业务微服务依赖
├── novel-gateway -- 基于 Spring Cloud Gateway 构建的微服务网关
├── novel-monitor -- 基于 Spring Boot Admin 构建的微服务监控中心
├── novel-search -- 基于 Elasticsearch 构建的搜索服务
├── novel-home -- 首页微服务
├── novel-news -- 新闻微服务
├── novel-book -- 小说微服务
└── novel-pay -- 支付微服务
├── novel-user -- 会员微服务
├── novel-author -- 作家微服务
└── novel-resource -- 资源微服务
```
### 技术选型
| 技术 | 说明
|----------------------| ---------------------------
| Spring Boot | Spring 应用快速开发脚手架
| Spring Cloud | 微服务架构解决方案
| Nacos | 注册中心和配置中心
| Sentinel | 限流/熔断/降级
| Spring Cloud Gateway | 微服务网关
| Spring Boot Admin | 微服务监控
| MyBatis | 持久层 ORM 框架
| MyBatis Dynamic SQL | MyBatis 动态 SQL
| PageHelper | MyBatis 分页插件
| MyBatis Generator | 持久层代码生成插件
| Seata | 分布式事务中间件(待应用)
| Sharding-JDBC | 代码层分库分表中间件
| JJWT | JWT 登录支持
| Redis | 分布式缓存
| Elasticsearch | 搜索引擎
| RabbitMQ | 消息队列
| Aliyun OSS | 阿里云对象存储服务
| MySQL | 数据库服务
| Redisson | 实现分布式锁
| Lombok | 简化对象封装工具
| Swagger | API 文档生成工具
| Docker | 应用容器引擎
| Logstash | 分布式日志采集
| Vue.js | 前端开发框架
### 项目架构
![](https://s3.ax1x.com/2020/12/09/r92rrT.png)
### 代码仓库
Gitee 仓库地址: https://gitee.com/novel_dev_team/novel-cloud
GitHub 仓库地址: https://github.com/201206030/novel-cloud
### QQ 交流群
👉[立即查看](https://novel.xxyopen.com/service.htm)
### 微信公众号(发布最新更新资讯)
![](https://docs.xxyopen.com/img/qrcode_for_gh.jpg)
### 捐赠支持
## 捐赠支持
开源项目不易,若此项目能得到你的青睐,可以捐赠支持作者持续开发与维护。
![](https://s1.ax1x.com/2020/10/31/BUQJwq.png)
![mini-code](https://s1.ax1x.com/2020/10/31/BUQJwq.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

BIN
assert/nacos_config.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

BIN
assert/navoel-discovery.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
assert/novel-monitor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

11
bin/run.sh Normal file
View File

@ -0,0 +1,11 @@
# novel-cloud 目录下运行 `bash bin/run.sh` 命令来启动所有的微服务
mvn clean install -Dmaven.test.skip
cd novel-book/novel-book-service
mvn spring-boot:run &
cd ../../novel-search
mvn spring-boot:run &
cd ../../novel-monitor
sleep 30
mvn spring-boot:run &
cd ..

View File

@ -1,7 +1,6 @@
PUT /novel
PUT /book
{
"mappings" : {
"properties" : {
"id" : {
"type" : "long"
@ -11,72 +10,53 @@ PUT /novel
},
"authorName" : {
"type" : "text",
"analyzer": "ik_smart",
"boost": 1.5
"analyzer": "ik_smart"
},
"bookName" : {
"type" : "text",
"analyzer": "ik_smart",
"boost": 2
"analyzer": "ik_smart"
},
"bookDesc" : {
"type" : "text",
"analyzer": "ik_smart",
"boost": 0.1
"analyzer": "ik_smart"
},
"bookStatus" : {
"type" : "short"
},
"catId" : {
"categoryId" : {
"type" : "integer"
},
"catName" : {
"categoryName" : {
"type" : "text",
"analyzer": "ik_smart",
"boost": 1.0
"analyzer": "ik_smart"
},
"lastIndexId" : {
"lastChapterId" : {
"type" : "long"
},
"lastIndexName" : {
"lastChapterName" : {
"type" : "text",
"analyzer": "ik_smart",
"boost": 0.1
"analyzer": "ik_smart"
},
"lastIndexUpdateTime" : {
"type": "keyword"
"lastChapterUpdateTime" : {
"type": "long"
},
"picUrl" : {
"type" : "keyword",
"index" : false,
"doc_values" : false
},
"score" : {
"type" : "float"
"type" : "integer"
},
"wordCount" : {
"type" : "integer"
},
"workDirection" : {
"type" : "short"
},
"visitCount" : {
"type": "long"
}
}
}
}

Binary file not shown.

View File

@ -1,116 +0,0 @@
DROP TABLE IF EXISTS `book_content0`;
CREATE TABLE `book_content0` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1155 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content1
-- ----------------------------
DROP TABLE IF EXISTS `book_content1`;
CREATE TABLE `book_content1` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=406 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content2
-- ----------------------------
DROP TABLE IF EXISTS `book_content2`;
CREATE TABLE `book_content2` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1222 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content3
-- ----------------------------
DROP TABLE IF EXISTS `book_content3`;
CREATE TABLE `book_content3` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=410 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content4
-- ----------------------------
DROP TABLE IF EXISTS `book_content4`;
CREATE TABLE `book_content4` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1188 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content5
-- ----------------------------
DROP TABLE IF EXISTS `book_content5`;
CREATE TABLE `book_content5` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=416 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content6
-- ----------------------------
DROP TABLE IF EXISTS `book_content6`;
CREATE TABLE `book_content6` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1180 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content7
-- ----------------------------
DROP TABLE IF EXISTS `book_content7`;
CREATE TABLE `book_content7` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=404 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content8
-- ----------------------------
DROP TABLE IF EXISTS `book_content8`;
CREATE TABLE `book_content8` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1134 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';
-- ----------------------------
-- Table structure for book_content9
-- ----------------------------
DROP TABLE IF EXISTS `book_content9`;
CREATE TABLE `book_content9` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`index_id` bigint(20) DEFAULT NULL COMMENT '目录ID',
`content` mediumtext COMMENT '小说章节内容',
PRIMARY KEY (`id`),
UNIQUE KEY `key_uq_indexId` (`index_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=415 DEFAULT CHARSET=utf8mb4 COMMENT='小说内容表';

1038
doc/sql/init.sql Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,68 +0,0 @@
management: #开启SpringBoot Admin的监控
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
server:
port: 527
spring:
cloud:
nacos:
discovery:
server-addr: 47.106.243.172:8848
namespace: 3960c71a-62ac-4b8f-8c30-bba8e8143a0c
gateway:
routes:
- id: home-route
uri: lb://novel-home
predicates:
- Path=/api/home/**
filters:
#注意过滤器按顺序执行,下面的顺序不能打乱
- SwaggerFilter
- RewritePath=/api/(?<segment>.*), /$\{segment}
- id: news-route
uri: lb://news-service
predicates:
- Path=/api/news/**
filters:
#注意过滤器按顺序执行,下面的顺序不能打乱
- SwaggerFilter
- RewritePath=/api/(?<segment>.*), /$\{segment}
- id: user-route
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
#注意过滤器按顺序执行,下面的顺序不能打乱
- SwaggerFilter
- RewritePath=/api/(?<segment>.*), /$\{segment}
- id: book-route
uri: lb://book-service
predicates:
- Path=/api/book/**
filters:
#注意过滤器按顺序执行,下面的顺序不能打乱
- SwaggerFilter
- RewritePath=/api/(?<segment>.*), /$\{segment}
- id: search-route
uri: lb://novel-search
predicates:
- Path=/api/search/**
filters:
#注意过滤器按顺序执行,下面的顺序不能打乱
- SwaggerFilter
- RewritePath=/api/(?<segment>.*), /$\{segment}
- id: monitor-route
uri: lb://novel-monitor
predicates:
- Path=/monitor/**
filters:
- RewritePath=/monitor/(?<segment>.*), /$\{segment}

View File

@ -1,34 +0,0 @@
<?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">
<parent>
<artifactId>novel-author</artifactId>
<groupId>com.java2nb.novel</groupId>
<version>1.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>author-api</artifactId>
<dependencies>
<dependency>
<groupId>com.java2nb.novel</groupId>
<artifactId>novel-common</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -1,148 +0,0 @@
package com.java2nb.novel.author.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.util.Date;
public class Author {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "用户ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long userId;
@ApiModelProperty(value = "邀请码")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String inviteCode;
@ApiModelProperty(value = "笔名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String penName;
@ApiModelProperty(value = "手机号码")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String telPhone;
@ApiModelProperty(value = "QQ或微信账号")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String chatAccount;
@ApiModelProperty(value = "电子邮箱")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String email;
@ApiModelProperty(value = "作品方向0男频1女频")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte workDirection;
@ApiModelProperty(value = "0正常1封禁")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte status;
@ApiModelProperty(value = "创建时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getUserId() {
return userId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUserId(Long userId) {
this.userId = userId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getInviteCode() {
return inviteCode;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode == null ? null : inviteCode.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getPenName() {
return penName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setPenName(String penName) {
this.penName = penName == null ? null : penName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getTelPhone() {
return telPhone;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setTelPhone(String telPhone) {
this.telPhone = telPhone == null ? null : telPhone.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getChatAccount() {
return chatAccount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setChatAccount(String chatAccount) {
this.chatAccount = chatAccount == null ? null : chatAccount.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getEmail() {
return email;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getWorkDirection() {
return workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setWorkDirection(Byte workDirection) {
this.workDirection = workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getStatus() {
return status;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setStatus(Byte status) {
this.status = status;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

View File

@ -1,92 +0,0 @@
package com.java2nb.novel.author.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.util.Date;
public class AuthorCode {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "邀请码")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String inviteCode;
@ApiModelProperty(value = "有效时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date validityTime;
@ApiModelProperty(value = "是否使用过0未使用1:使用过")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte isUse;
@ApiModelProperty(value = "创建时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@ApiModelProperty(value = "创建人ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getInviteCode() {
return inviteCode;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode == null ? null : inviteCode.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getValidityTime() {
return validityTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setValidityTime(Date validityTime) {
this.validityTime = validityTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getIsUse() {
return isUse;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIsUse(Byte isUse) {
this.isUse = isUse;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getCreateUserId() {
return createUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
}

View File

@ -1,71 +0,0 @@
<?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">
<parent>
<artifactId>novel-author</artifactId>
<groupId>com.java2nb.novel</groupId>
<version>1.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>author-service</artifactId>
<dependencies>
<dependency>
<groupId>com.java2nb.novel</groupId>
<artifactId>author-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.maven.plugin.version}</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>201206030/${project.artifactId}:${project.version}</imageName>
<dockerHost>${docker.host}</dockerHost>
<baseImage>java:8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>-->
</plugins>
</build>
</project>

View File

@ -1,24 +0,0 @@
package com.java2nb.novel;
import com.java2nb.novel.common.cache.CacheService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
/**
* 作家微服务启动器
* @author xiongxiaoyang
* @version 1.0
* @since 2020/5/27
*/
@SpringBootApplication
//@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {CacheService.class})})
@EnableFeignClients
public class AuthorApplication {
public static void main(String[] args) {
SpringApplication.run(AuthorApplication.class);
}
}

View File

@ -1,50 +0,0 @@
package com.java2nb.novel.author.mapper;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.SqlTable;
import javax.annotation.Generated;
import java.sql.JDBCType;
import java.util.Date;
public final class AuthorCodeDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final AuthorCode authorCode = new AuthorCode();
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> id = authorCode.id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> inviteCode = authorCode.inviteCode;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> validityTime = authorCode.validityTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> isUse = authorCode.isUse;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = authorCode.createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> createUserId = authorCode.createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final class AuthorCode extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<String> inviteCode = column("invite_code", JDBCType.VARCHAR);
public final SqlColumn<Date> validityTime = column("validity_time", JDBCType.TIMESTAMP);
public final SqlColumn<Byte> isUse = column("is_use", JDBCType.TINYINT);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public final SqlColumn<Long> createUserId = column("create_user_id", JDBCType.BIGINT);
public AuthorCode() {
super("author_code");
}
}
}

View File

@ -1,177 +0,0 @@
package com.java2nb.novel.author.mapper;
import com.java2nb.novel.author.entity.AuthorCode;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.delete.DeleteDSL;
import org.mybatis.dynamic.sql.delete.MyBatis3DeleteModelAdapter;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.render.RenderingStrategy;
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
import org.mybatis.dynamic.sql.select.SelectDSL;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.MyBatis3UpdateModelAdapter;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import javax.annotation.Generated;
import java.util.List;
import static com.java2nb.novel.author.mapper.AuthorCodeDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
@Mapper
public interface AuthorCodeMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
int insert(InsertStatementProvider<AuthorCode> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("AuthorCodeResult")
AuthorCode selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="AuthorCodeResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="invite_code", property="inviteCode", jdbcType=JdbcType.VARCHAR),
@Result(column="validity_time", property="validityTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="is_use", property="isUse", jdbcType=JdbcType.TINYINT),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="create_user_id", property="createUserId", jdbcType=JdbcType.BIGINT)
})
List<AuthorCode> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default QueryExpressionDSL<MyBatis3SelectModelAdapter<Long>> countByExample() {
return SelectDSL.selectWithMapper(this::count, SqlBuilder.count())
.from(authorCode);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default DeleteDSL<MyBatis3DeleteModelAdapter<Integer>> deleteByExample() {
return DeleteDSL.deleteFromWithMapper(this::delete, authorCode);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) {
return DeleteDSL.deleteFromWithMapper(this::delete, authorCode)
.where(id, isEqualTo(id_))
.build()
.execute();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(AuthorCode record) {
return insert(SqlBuilder.insert(record)
.into(authorCode)
.map(id).toProperty("id")
.map(inviteCode).toProperty("inviteCode")
.map(validityTime).toProperty("validityTime")
.map(isUse).toProperty("isUse")
.map(createTime).toProperty("createTime")
.map(createUserId).toProperty("createUserId")
.build()
.render(RenderingStrategy.MYBATIS3));
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(AuthorCode record) {
return insert(SqlBuilder.insert(record)
.into(authorCode)
.map(id).toPropertyWhenPresent("id", record::getId)
.map(inviteCode).toPropertyWhenPresent("inviteCode", record::getInviteCode)
.map(validityTime).toPropertyWhenPresent("validityTime", record::getValidityTime)
.map(isUse).toPropertyWhenPresent("isUse", record::getIsUse)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
.map(createUserId).toPropertyWhenPresent("createUserId", record::getCreateUserId)
.build()
.render(RenderingStrategy.MYBATIS3));
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default QueryExpressionDSL<MyBatis3SelectModelAdapter<List<AuthorCode>>> selectByExample() {
return SelectDSL.selectWithMapper(this::selectMany, id, inviteCode, validityTime, isUse, createTime, createUserId)
.from(authorCode);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default QueryExpressionDSL<MyBatis3SelectModelAdapter<List<AuthorCode>>> selectDistinctByExample() {
return SelectDSL.selectDistinctWithMapper(this::selectMany, id, inviteCode, validityTime, isUse, createTime, createUserId)
.from(authorCode);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default AuthorCode selectByPrimaryKey(Long id_) {
return SelectDSL.selectWithMapper(this::selectOne, id, inviteCode, validityTime, isUse, createTime, createUserId)
.from(authorCode)
.where(id, isEqualTo(id_))
.build()
.execute();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default UpdateDSL<MyBatis3UpdateModelAdapter<Integer>> updateByExample(AuthorCode record) {
return UpdateDSL.updateWithMapper(this::update, authorCode)
.set(id).equalTo(record::getId)
.set(inviteCode).equalTo(record::getInviteCode)
.set(validityTime).equalTo(record::getValidityTime)
.set(isUse).equalTo(record::getIsUse)
.set(createTime).equalTo(record::getCreateTime)
.set(createUserId).equalTo(record::getCreateUserId);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default UpdateDSL<MyBatis3UpdateModelAdapter<Integer>> updateByExampleSelective(AuthorCode record) {
return UpdateDSL.updateWithMapper(this::update, authorCode)
.set(id).equalToWhenPresent(record::getId)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(validityTime).equalToWhenPresent(record::getValidityTime)
.set(isUse).equalToWhenPresent(record::getIsUse)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.set(createUserId).equalToWhenPresent(record::getCreateUserId);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(AuthorCode record) {
return UpdateDSL.updateWithMapper(this::update, authorCode)
.set(inviteCode).equalTo(record::getInviteCode)
.set(validityTime).equalTo(record::getValidityTime)
.set(isUse).equalTo(record::getIsUse)
.set(createTime).equalTo(record::getCreateTime)
.set(createUserId).equalTo(record::getCreateUserId)
.where(id, isEqualTo(record::getId))
.build()
.execute();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(AuthorCode record) {
return UpdateDSL.updateWithMapper(this::update, authorCode)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(validityTime).equalToWhenPresent(record::getValidityTime)
.set(isUse).equalToWhenPresent(record::getIsUse)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.set(createUserId).equalToWhenPresent(record::getCreateUserId)
.where(id, isEqualTo(record::getId))
.build()
.execute();
}
}

View File

@ -1,70 +0,0 @@
package com.java2nb.novel.author.mapper;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.SqlTable;
import javax.annotation.Generated;
import java.sql.JDBCType;
import java.util.Date;
public final class AuthorDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final Author author = new Author();
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> id = author.id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> userId = author.userId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> inviteCode = author.inviteCode;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> penName = author.penName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> telPhone = author.telPhone;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> chatAccount = author.chatAccount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> email = author.email;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> workDirection = author.workDirection;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> status = author.status;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = author.createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final class Author extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<Long> userId = column("user_id", JDBCType.BIGINT);
public final SqlColumn<String> inviteCode = column("invite_code", JDBCType.VARCHAR);
public final SqlColumn<String> penName = column("pen_name", JDBCType.VARCHAR);
public final SqlColumn<String> telPhone = column("tel_phone", JDBCType.VARCHAR);
public final SqlColumn<String> chatAccount = column("chat_account", JDBCType.VARCHAR);
public final SqlColumn<String> email = column("email", JDBCType.VARCHAR);
public final SqlColumn<Byte> workDirection = column("work_direction", JDBCType.TINYINT);
public final SqlColumn<Byte> status = column("status", JDBCType.TINYINT);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public Author() {
super("author");
}
}
}

View File

@ -1,205 +0,0 @@
package com.java2nb.novel.author.mapper;
import com.java2nb.novel.author.entity.Author;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.delete.DeleteDSL;
import org.mybatis.dynamic.sql.delete.MyBatis3DeleteModelAdapter;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.render.RenderingStrategy;
import org.mybatis.dynamic.sql.select.MyBatis3SelectModelAdapter;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
import org.mybatis.dynamic.sql.select.SelectDSL;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.MyBatis3UpdateModelAdapter;
import org.mybatis.dynamic.sql.update.UpdateDSL;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
import javax.annotation.Generated;
import java.util.List;
import static com.java2nb.novel.author.mapper.AuthorDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
@Mapper
public interface AuthorMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
int insert(InsertStatementProvider<Author> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("AuthorResult")
Author selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="AuthorResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="user_id", property="userId", jdbcType=JdbcType.BIGINT),
@Result(column="invite_code", property="inviteCode", jdbcType=JdbcType.VARCHAR),
@Result(column="pen_name", property="penName", jdbcType=JdbcType.VARCHAR),
@Result(column="tel_phone", property="telPhone", jdbcType=JdbcType.VARCHAR),
@Result(column="chat_account", property="chatAccount", jdbcType=JdbcType.VARCHAR),
@Result(column="email", property="email", jdbcType=JdbcType.VARCHAR),
@Result(column="work_direction", property="workDirection", jdbcType=JdbcType.TINYINT),
@Result(column="status", property="status", jdbcType=JdbcType.TINYINT),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP)
})
List<Author> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default QueryExpressionDSL<MyBatis3SelectModelAdapter<Long>> countByExample() {
return SelectDSL.selectWithMapper(this::count, SqlBuilder.count())
.from(author);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default DeleteDSL<MyBatis3DeleteModelAdapter<Integer>> deleteByExample() {
return DeleteDSL.deleteFromWithMapper(this::delete, author);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) {
return DeleteDSL.deleteFromWithMapper(this::delete, author)
.where(id, isEqualTo(id_))
.build()
.execute();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(Author record) {
return insert(SqlBuilder.insert(record)
.into(author)
.map(id).toProperty("id")
.map(userId).toProperty("userId")
.map(inviteCode).toProperty("inviteCode")
.map(penName).toProperty("penName")
.map(telPhone).toProperty("telPhone")
.map(chatAccount).toProperty("chatAccount")
.map(email).toProperty("email")
.map(workDirection).toProperty("workDirection")
.map(status).toProperty("status")
.map(createTime).toProperty("createTime")
.build()
.render(RenderingStrategy.MYBATIS3));
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(Author record) {
return insert(SqlBuilder.insert(record)
.into(author)
.map(id).toPropertyWhenPresent("id", record::getId)
.map(userId).toPropertyWhenPresent("userId", record::getUserId)
.map(inviteCode).toPropertyWhenPresent("inviteCode", record::getInviteCode)
.map(penName).toPropertyWhenPresent("penName", record::getPenName)
.map(telPhone).toPropertyWhenPresent("telPhone", record::getTelPhone)
.map(chatAccount).toPropertyWhenPresent("chatAccount", record::getChatAccount)
.map(email).toPropertyWhenPresent("email", record::getEmail)
.map(workDirection).toPropertyWhenPresent("workDirection", record::getWorkDirection)
.map(status).toPropertyWhenPresent("status", record::getStatus)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
.build()
.render(RenderingStrategy.MYBATIS3));
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default QueryExpressionDSL<MyBatis3SelectModelAdapter<List<Author>>> selectByExample() {
return SelectDSL.selectWithMapper(this::selectMany, id, userId, inviteCode, penName, telPhone, chatAccount, email, workDirection, status, createTime)
.from(author);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default QueryExpressionDSL<MyBatis3SelectModelAdapter<List<Author>>> selectDistinctByExample() {
return SelectDSL.selectDistinctWithMapper(this::selectMany, id, userId, inviteCode, penName, telPhone, chatAccount, email, workDirection, status, createTime)
.from(author);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Author selectByPrimaryKey(Long id_) {
return SelectDSL.selectWithMapper(this::selectOne, id, userId, inviteCode, penName, telPhone, chatAccount, email, workDirection, status, createTime)
.from(author)
.where(id, isEqualTo(id_))
.build()
.execute();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default UpdateDSL<MyBatis3UpdateModelAdapter<Integer>> updateByExample(Author record) {
return UpdateDSL.updateWithMapper(this::update, author)
.set(id).equalTo(record::getId)
.set(userId).equalTo(record::getUserId)
.set(inviteCode).equalTo(record::getInviteCode)
.set(penName).equalTo(record::getPenName)
.set(telPhone).equalTo(record::getTelPhone)
.set(chatAccount).equalTo(record::getChatAccount)
.set(email).equalTo(record::getEmail)
.set(workDirection).equalTo(record::getWorkDirection)
.set(status).equalTo(record::getStatus)
.set(createTime).equalTo(record::getCreateTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default UpdateDSL<MyBatis3UpdateModelAdapter<Integer>> updateByExampleSelective(Author record) {
return UpdateDSL.updateWithMapper(this::update, author)
.set(id).equalToWhenPresent(record::getId)
.set(userId).equalToWhenPresent(record::getUserId)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(penName).equalToWhenPresent(record::getPenName)
.set(telPhone).equalToWhenPresent(record::getTelPhone)
.set(chatAccount).equalToWhenPresent(record::getChatAccount)
.set(email).equalToWhenPresent(record::getEmail)
.set(workDirection).equalToWhenPresent(record::getWorkDirection)
.set(status).equalToWhenPresent(record::getStatus)
.set(createTime).equalToWhenPresent(record::getCreateTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(Author record) {
return UpdateDSL.updateWithMapper(this::update, author)
.set(userId).equalTo(record::getUserId)
.set(inviteCode).equalTo(record::getInviteCode)
.set(penName).equalTo(record::getPenName)
.set(telPhone).equalTo(record::getTelPhone)
.set(chatAccount).equalTo(record::getChatAccount)
.set(email).equalTo(record::getEmail)
.set(workDirection).equalTo(record::getWorkDirection)
.set(status).equalTo(record::getStatus)
.set(createTime).equalTo(record::getCreateTime)
.where(id, isEqualTo(record::getId))
.build()
.execute();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(Author record) {
return UpdateDSL.updateWithMapper(this::update, author)
.set(userId).equalToWhenPresent(record::getUserId)
.set(inviteCode).equalToWhenPresent(record::getInviteCode)
.set(penName).equalToWhenPresent(record::getPenName)
.set(telPhone).equalToWhenPresent(record::getTelPhone)
.set(chatAccount).equalToWhenPresent(record::getChatAccount)
.set(email).equalToWhenPresent(record::getEmail)
.set(workDirection).equalToWhenPresent(record::getWorkDirection)
.set(status).equalToWhenPresent(record::getStatus)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.where(id, isEqualTo(record::getId))
.build()
.execute();
}
}

View File

@ -1,4 +0,0 @@
spring:
profiles:
include: [common]

View File

@ -1,13 +0,0 @@
spring:
application:
name: author-service
cloud:
nacos:
config:
extconfig[0]:
dataid: novel-jwt.yml
group: novel-common
refresh: true
profiles:
active: dev

View File

@ -3,27 +3,28 @@
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">
<parent>
<artifactId>novel-cloud</artifactId>
<groupId>com.java2nb.novel</groupId>
<version>1.3.0</version>
<artifactId>novel-author</artifactId>
<groupId>io.github.xxyopen</groupId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>novel-gen</artifactId>
<artifactId>novel-author-api</artifactId>
<dependencies>
<dependency>
<groupId>com.java2nb.novel</groupId>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-common</artifactId>
</dependency>
<!-- MyBatis 生成器 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis-generator.version}</version>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,28 @@
package io.github.xxyopen.novel.author.dto;
import lombok.Builder;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 作家信息 DTO
*
* @author xiongxiaoyang
* @date 2022/5/18
*/
@Data
@Builder
public class AuthorInfoDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
private String penName;
private Integer status;
}

View File

@ -0,0 +1,58 @@
package io.github.xxyopen.novel.author.dto.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;
/**
* 作家注册 请求DTO
*
* @author xiongxiaoyang
* @date 2022/5/23
*/
@Data
public class AuthorRegisterReqDto {
@Schema(hidden = true)
private Long userId;
/**
* 笔名
*/
@Schema(description = "笔名", required = true)
@NotBlank(message = "笔名不能为空!")
private String penName;
/**
* 手机号码
*/
@Schema(description = "手机号码", required = true)
@NotBlank(message = "手机号不能为空!")
@Pattern(regexp = "^1[3|4|5|6|7|8|9][0-9]{9}$", message = "手机号格式不正确!")
private String telPhone;
/**
* QQ或微信账号
*/
@Schema(description = "QQ或微信账号", required = true)
@NotBlank(message = "QQ或微信账号不能为空")
private String chatAccount;
/**
* 电子邮箱
*/
@Schema(description = "电子邮箱", required = true)
@NotBlank(message = "电子邮箱不能为空!")
@Email(message = "邮箱格式不正确!")
private String email;
/**
* 作品方向;0-男频 1-女频
*/
@Schema(description = "作品方向;0-男频 1-女频", required = true)
@NotNull(message = "作品方向不能为空!")
@Min(0)
@Max(1)
private Integer workDirection;
}

View File

@ -0,0 +1,36 @@
<?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">
<parent>
<artifactId>novel-author</artifactId>
<groupId>io.github.xxyopen</groupId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>novel-author-service</artifactId>
<dependencies>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-author-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-book-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-config</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,21 @@
package io.github.xxyopen.novel.author;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication(scanBasePackages = {"io.github.xxyopen.novel"})
@MapperScan("io.github.xxyopen.novel.author.dao.mapper")
@EnableCaching
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"io.github.xxyopen.novel.book.feign"})
public class NovelAuthorApplication {
public static void main(String[] args) {
SpringApplication.run(NovelAuthorApplication.class, args);
}
}

View File

@ -0,0 +1,88 @@
package io.github.xxyopen.novel.author.config;
import io.github.xxyopen.novel.author.dto.AuthorInfoDto;
import io.github.xxyopen.novel.author.manager.cache.AuthorInfoCacheManager;
import io.github.xxyopen.novel.common.auth.JwtUtils;
import io.github.xxyopen.novel.common.auth.UserHolder;
import io.github.xxyopen.novel.common.constant.ErrorCodeEnum;
import io.github.xxyopen.novel.common.constant.SystemConfigConsts;
import io.github.xxyopen.novel.config.exception.BusinessException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import java.util.Objects;
/**
* 认证授权 拦截器为了注入其它的 Spring beans需要通过 @Component 注解将该拦截器注册到 Spring 上下文
*
* @author xiongxiaoyang
* @date 2022/5/18
*/
@Component
@RequiredArgsConstructor
public class AuthInterceptor implements HandlerInterceptor {
private final AuthorInfoCacheManager authorInfoCacheManager;
/**
* handle 执行前调用
*/
@SuppressWarnings("NullableProblems")
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 获取登录 JWT
String token = request.getHeader(SystemConfigConsts.HTTP_AUTH_HEADER_NAME);
// 开始认证
if (!StringUtils.hasText(token)) {
// token 为空
throw new BusinessException(ErrorCodeEnum.USER_LOGIN_EXPIRED);
}
Long userId = JwtUtils.parseToken(token, SystemConfigConsts.NOVEL_FRONT_KEY);
if (Objects.isNull(userId)) {
// token 解析失败
throw new BusinessException(ErrorCodeEnum.USER_LOGIN_EXPIRED);
}
// 作家权限认证
AuthorInfoDto authorInfo = authorInfoCacheManager.getAuthor(userId);
if (Objects.isNull(authorInfo)) {
// 作家账号不存在无权访问作家专区
throw new BusinessException(ErrorCodeEnum.USER_UN_AUTH);
}
// 设置作家ID到当前线程
UserHolder.setAuthorId(authorInfo.getId());
// 设置 userId 到当前线程
UserHolder.setUserId(userId);
return HandlerInterceptor.super.preHandle(request, response, handler);
}
/**
* handler 执行后调用出现异常不调用
*/
@SuppressWarnings("NullableProblems")
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* DispatcherServlet 完全处理完请求后调用出现异常照常调用
*/
@SuppressWarnings("NullableProblems")
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 清理当前线程保存的用户数据
UserHolder.clear();
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

View File

@ -0,0 +1,45 @@
package io.github.xxyopen.novel.author.config;
import io.github.xxyopen.novel.common.constant.ApiRouterConsts;
import io.github.xxyopen.novel.config.interceptor.TokenParseInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Spring Web Mvc 相关配置不要加 @EnableWebMvc 注解否则会导致 jackson 的全局配置失效因为 @EnableWebMvc 注解会导致 WebMvcAutoConfiguration 自动配置失效
*
* @author xiongxiaoyang
* @date 2022/5/18
*/
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final AuthInterceptor authInterceptor;
private final TokenParseInterceptor tokenParseInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 权限认证拦截
registry.addInterceptor(authInterceptor)
// 拦截作家后台相关请求接口
.addPathPatterns(
ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/**")
// 放行注册相关请求接口
.excludePathPatterns(ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register",
ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/status")
.order(2);
// Token 解析
registry.addInterceptor(tokenParseInterceptor)
.addPathPatterns(
ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register", ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/status")
.order(3);
}
}

View File

@ -0,0 +1,110 @@
package io.github.xxyopen.novel.author.controller.author;
import io.github.xxyopen.novel.author.dto.req.AuthorRegisterReqDto;
import io.github.xxyopen.novel.author.manager.feign.BookFeignManager;
import io.github.xxyopen.novel.author.service.AuthorService;
import io.github.xxyopen.novel.book.dto.req.BookAddReqDto;
import io.github.xxyopen.novel.book.dto.req.BookPageReqDto;
import io.github.xxyopen.novel.book.dto.req.ChapterAddReqDto;
import io.github.xxyopen.novel.book.dto.req.ChapterPageReqDto;
import io.github.xxyopen.novel.book.dto.resp.BookChapterRespDto;
import io.github.xxyopen.novel.book.dto.resp.BookInfoRespDto;
import io.github.xxyopen.novel.common.auth.UserHolder;
import io.github.xxyopen.novel.common.constant.ApiRouterConsts;
import io.github.xxyopen.novel.common.constant.SystemConfigConsts;
import io.github.xxyopen.novel.common.req.PageReqDto;
import io.github.xxyopen.novel.common.resp.PageRespDto;
import io.github.xxyopen.novel.common.resp.RestResp;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.*;
/**
* 作家后台-作家模块 API 控制器
*
* @author xiongxiaoyang
* @date 2022/5/23
*/
@Tag(name = "AuthorController", description = "作家后台-作者模块")
@SecurityRequirement(name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME)
@RestController
@RequestMapping(ApiRouterConsts.API_AUTHOR_URL_PREFIX)
@RequiredArgsConstructor
public class AuthorController {
private final AuthorService authorService;
private final BookFeignManager bookFeignManager;
/**
* 作家注册接口
*/
@Operation(summary = "作家注册接口")
@PostMapping("register")
public RestResp<Void> register(@Valid @RequestBody AuthorRegisterReqDto dto) {
dto.setUserId(UserHolder.getUserId());
return authorService.register(dto);
}
/**
* 查询作家状态接口
*/
@Operation(summary = "作家状态查询接口")
@GetMapping("status")
public RestResp<Integer> getStatus() {
return authorService.getStatus(UserHolder.getUserId());
}
/**
* 小说发布接口
*/
@Operation(summary = "小说发布接口")
@PostMapping("book")
public RestResp<Void> publishBook(@Valid @RequestBody BookAddReqDto dto) {
return bookFeignManager.publishBook(dto);
}
/**
* 小说发布列表查询接口
*/
@Operation(summary = "小说发布列表查询接口")
@GetMapping("books")
public RestResp<PageRespDto<BookInfoRespDto>> listBooks(@ParameterObject BookPageReqDto dto) {
dto.setAuthorId(UserHolder.getAuthorId());
return bookFeignManager.listPublishBooks(dto);
}
/**
* 小说章节发布接口
*/
@Operation(summary = "小说章节发布接口")
@PostMapping("book/chapter/{bookId}")
public RestResp<Void> publishBookChapter(
@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId,
@Valid @RequestBody ChapterAddReqDto dto) {
dto.setAuthorId(UserHolder.getAuthorId());
dto.setBookId(bookId);
return bookFeignManager.publishBookChapter(dto);
}
/**
* 小说章节发布列表查询接口
*/
@Operation(summary = "小说章节发布列表查询接口")
@GetMapping("book/chapters/{bookId}")
public RestResp<PageRespDto<BookChapterRespDto>> listBookChapters(
@Parameter(description = "小说ID") @PathVariable("bookId") Long bookId,
@ParameterObject PageReqDto dto) {
ChapterPageReqDto chapterPageReqReqDto = new ChapterPageReqDto();
chapterPageReqReqDto.setBookId(bookId);
chapterPageReqReqDto.setPageNum(dto.getPageNum());
chapterPageReqReqDto.setPageSize(dto.getPageSize());
return bookFeignManager.listPublishBookChapters(chapterPageReqReqDto);
}
}

View File

@ -0,0 +1,114 @@
package io.github.xxyopen.novel.author.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 作家邀请码
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
@TableName("author_code")
public class AuthorCode implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 邀请码
*/
private String inviteCode;
/**
* 有效时间
*/
private LocalDateTime validityTime;
/**
* 是否使用过;0-未使用 1-使用过
*/
private Integer isUsed;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getInviteCode() {
return inviteCode;
}
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode;
}
public LocalDateTime getValidityTime() {
return validityTime;
}
public void setValidityTime(LocalDateTime validityTime) {
this.validityTime = validityTime;
}
public Integer getIsUsed() {
return isUsed;
}
public void setIsUsed(Integer isUsed) {
this.isUsed = isUsed;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "AuthorCode{" +
"id=" + id +
", inviteCode=" + inviteCode +
", validityTime=" + validityTime +
", isUsed=" + isUsed +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,185 @@
package io.github.xxyopen.novel.author.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* <p>
* 稿费收入统计
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
@TableName("author_income")
public class AuthorIncome implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 作家ID
*/
private Long authorId;
/**
* 小说ID
*/
private Long bookId;
/**
* 收入月份
*/
private LocalDate incomeMonth;
/**
* 税前收入;单位
*/
private Integer preTaxIncome;
/**
* 税后收入;单位
*/
private Integer afterTaxIncome;
/**
* 支付状态;0-待支付 1-已支付
*/
private Integer payStatus;
/**
* 稿费确认状态;0-待确认 1-已确认
*/
private Integer confirmStatus;
/**
* 详情
*/
private String detail;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getAuthorId() {
return authorId;
}
public void setAuthorId(Long authorId) {
this.authorId = authorId;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public LocalDate getIncomeMonth() {
return incomeMonth;
}
public void setIncomeMonth(LocalDate incomeMonth) {
this.incomeMonth = incomeMonth;
}
public Integer getPreTaxIncome() {
return preTaxIncome;
}
public void setPreTaxIncome(Integer preTaxIncome) {
this.preTaxIncome = preTaxIncome;
}
public Integer getAfterTaxIncome() {
return afterTaxIncome;
}
public void setAfterTaxIncome(Integer afterTaxIncome) {
this.afterTaxIncome = afterTaxIncome;
}
public Integer getPayStatus() {
return payStatus;
}
public void setPayStatus(Integer payStatus) {
this.payStatus = payStatus;
}
public Integer getConfirmStatus() {
return confirmStatus;
}
public void setConfirmStatus(Integer confirmStatus) {
this.confirmStatus = confirmStatus;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "AuthorIncome{" +
"id=" + id +
", authorId=" + authorId +
", bookId=" + bookId +
", incomeMonth=" + incomeMonth +
", preTaxIncome=" + preTaxIncome +
", afterTaxIncome=" + afterTaxIncome +
", payStatus=" + payStatus +
", confirmStatus=" + confirmStatus +
", detail=" + detail +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,157 @@
package io.github.xxyopen.novel.author.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* <p>
* 稿费收入明细统计
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
@TableName("author_income_detail")
public class AuthorIncomeDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 作家ID
*/
private Long authorId;
/**
* 小说ID;0表示全部作品
*/
private Long bookId;
/**
* 收入日期
*/
private LocalDate incomeDate;
/**
* 订阅总额
*/
private Integer incomeAccount;
/**
* 订阅次数
*/
private Integer incomeCount;
/**
* 订阅人数
*/
private Integer incomeNumber;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getAuthorId() {
return authorId;
}
public void setAuthorId(Long authorId) {
this.authorId = authorId;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public LocalDate getIncomeDate() {
return incomeDate;
}
public void setIncomeDate(LocalDate incomeDate) {
this.incomeDate = incomeDate;
}
public Integer getIncomeAccount() {
return incomeAccount;
}
public void setIncomeAccount(Integer incomeAccount) {
this.incomeAccount = incomeAccount;
}
public Integer getIncomeCount() {
return incomeCount;
}
public void setIncomeCount(Integer incomeCount) {
this.incomeCount = incomeCount;
}
public Integer getIncomeNumber() {
return incomeNumber;
}
public void setIncomeNumber(Integer incomeNumber) {
this.incomeNumber = incomeNumber;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "AuthorIncomeDetail{" +
"id=" + id +
", authorId=" + authorId +
", bookId=" + bookId +
", incomeDate=" + incomeDate +
", incomeAccount=" + incomeAccount +
", incomeCount=" + incomeCount +
", incomeNumber=" + incomeNumber +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,184 @@
package io.github.xxyopen.novel.author.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 作者信息
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
@TableName("author_info")
public class AuthorInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 邀请码
*/
private String inviteCode;
/**
* 笔名
*/
private String penName;
/**
* 手机号码
*/
private String telPhone;
/**
* QQ或微信账号
*/
private String chatAccount;
/**
* 电子邮箱
*/
private String email;
/**
* 作品方向;0-男频 1-女频
*/
private Integer workDirection;
/**
* 0正常;1-封禁
*/
private Integer status;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getInviteCode() {
return inviteCode;
}
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode;
}
public String getPenName() {
return penName;
}
public void setPenName(String penName) {
this.penName = penName;
}
public String getTelPhone() {
return telPhone;
}
public void setTelPhone(String telPhone) {
this.telPhone = telPhone;
}
public String getChatAccount() {
return chatAccount;
}
public void setChatAccount(String chatAccount) {
this.chatAccount = chatAccount;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getWorkDirection() {
return workDirection;
}
public void setWorkDirection(Integer workDirection) {
this.workDirection = workDirection;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "AuthorInfo{" +
"id=" + id +
", userId=" + userId +
", inviteCode=" + inviteCode +
", penName=" + penName +
", telPhone=" + telPhone +
", chatAccount=" + chatAccount +
", email=" + email +
", workDirection=" + workDirection +
", status=" + status +
", createTime=" + createTime +
", updateTime=" + updateTime +
"}";
}
}

View File

@ -0,0 +1,17 @@
package io.github.xxyopen.novel.author.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.author.dao.entity.AuthorCode;
/**
* <p>
* 作家邀请码 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
public interface AuthorCodeMapper extends BaseMapper<AuthorCode> {
}

View File

@ -0,0 +1,16 @@
package io.github.xxyopen.novel.author.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.author.dao.entity.AuthorIncomeDetail;
/**
* <p>
* 稿费收入明细统计 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
public interface AuthorIncomeDetailMapper extends BaseMapper<AuthorIncomeDetail> {
}

View File

@ -0,0 +1,16 @@
package io.github.xxyopen.novel.author.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.author.dao.entity.AuthorIncome;
/**
* <p>
* 稿费收入统计 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
public interface AuthorIncomeMapper extends BaseMapper<AuthorIncome> {
}

View File

@ -0,0 +1,16 @@
package io.github.xxyopen.novel.author.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.github.xxyopen.novel.author.dao.entity.AuthorInfo;
/**
* <p>
* 作者信息 Mapper 接口
* </p>
*
* @author xiongxiaoyang
* @date 2022/05/11
*/
public interface AuthorInfoMapper extends BaseMapper<AuthorInfo> {
}

View File

@ -0,0 +1,54 @@
package io.github.xxyopen.novel.author.manager.cache;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.github.xxyopen.novel.author.dao.entity.AuthorInfo;
import io.github.xxyopen.novel.author.dao.mapper.AuthorInfoMapper;
import io.github.xxyopen.novel.author.dto.AuthorInfoDto;
import io.github.xxyopen.novel.common.constant.CacheConsts;
import io.github.xxyopen.novel.common.constant.DatabaseConsts;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* 作家信息 缓存管理类
*
* @author xiongxiaoyang
* @date 2022/5/12
*/
@Component
@RequiredArgsConstructor
public class AuthorInfoCacheManager {
private final AuthorInfoMapper authorInfoMapper;
/**
* 查询作家信息并放入缓存中
*/
@Cacheable(cacheManager = CacheConsts.REDIS_CACHE_MANAGER,
value = CacheConsts.AUTHOR_INFO_CACHE_NAME, unless = "#result == null")
public AuthorInfoDto getAuthor(Long userId) {
QueryWrapper<AuthorInfo> queryWrapper = new QueryWrapper<>();
queryWrapper
.eq(DatabaseConsts.AuthorInfoTable.COLUMN_USER_ID, userId)
.last(DatabaseConsts.SqlEnum.LIMIT_1.getSql());
AuthorInfo authorInfo = authorInfoMapper.selectOne(queryWrapper);
if (Objects.isNull(authorInfo)) {
return null;
}
return AuthorInfoDto.builder()
.id(authorInfo.getId())
.penName(authorInfo.getPenName())
.status(authorInfo.getStatus()).build();
}
@CacheEvict(cacheManager = CacheConsts.REDIS_CACHE_MANAGER,
value = CacheConsts.AUTHOR_INFO_CACHE_NAME)
public void evictAuthorCache() {
// 调用此方法自动清除作家信息的缓存
}
}

View File

@ -0,0 +1,60 @@
package io.github.xxyopen.novel.author.manager.feign;
import io.github.xxyopen.novel.author.dto.AuthorInfoDto;
import io.github.xxyopen.novel.author.manager.cache.AuthorInfoCacheManager;
import io.github.xxyopen.novel.book.dto.req.BookAddReqDto;
import io.github.xxyopen.novel.book.dto.req.BookPageReqDto;
import io.github.xxyopen.novel.book.dto.req.ChapterAddReqDto;
import io.github.xxyopen.novel.book.dto.req.ChapterPageReqDto;
import io.github.xxyopen.novel.book.dto.resp.BookChapterRespDto;
import io.github.xxyopen.novel.book.dto.resp.BookEsRespDto;
import io.github.xxyopen.novel.book.dto.resp.BookInfoRespDto;
import io.github.xxyopen.novel.book.feign.BookFeign;
import io.github.xxyopen.novel.common.auth.UserHolder;
import io.github.xxyopen.novel.common.constant.ErrorCodeEnum;
import io.github.xxyopen.novel.common.req.PageReqDto;
import io.github.xxyopen.novel.common.resp.PageRespDto;
import io.github.xxyopen.novel.common.resp.RestResp;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 小说微服务调用 Feign 客户端管理
*
* @author xiongxiaoyang
* @date 2023/3/29
*/
@Component
@AllArgsConstructor
public class BookFeignManager {
private final BookFeign bookFeign;
private final AuthorInfoCacheManager authorInfoCacheManager;
public RestResp<Void> publishBook(BookAddReqDto dto) {
AuthorInfoDto author = authorInfoCacheManager.getAuthor(UserHolder.getUserId());
dto.setAuthorId(author.getId());
dto.setPenName(author.getPenName());
return bookFeign.publishBook(dto);
}
public RestResp<PageRespDto<BookInfoRespDto>> listPublishBooks(BookPageReqDto dto) {
authorInfoCacheManager.getAuthor(UserHolder.getUserId());
return bookFeign.listPublishBooks(dto);
}
public RestResp<Void> publishBookChapter(ChapterAddReqDto dto) {
return bookFeign.publishBookChapter(dto);
}
public RestResp<PageRespDto<BookChapterRespDto>> listPublishBookChapters(ChapterPageReqDto dto) {
return bookFeign.listPublishBookChapters(dto);
}
}

View File

@ -0,0 +1,30 @@
package io.github.xxyopen.novel.author.service;
import io.github.xxyopen.novel.author.dto.req.AuthorRegisterReqDto;
import io.github.xxyopen.novel.common.resp.RestResp;
/**
* 作家模块 业务服务类
*
* @author xiongxiaoyang
* @date 2022/5/23
*/
public interface AuthorService {
/**
* 作家注册
*
* @param dto 注册参数
* @return void
*/
RestResp<Void> register(AuthorRegisterReqDto dto);
/**
* 查询作家状态
*
* @param userId 用户ID
* @return 作家状态
*/
RestResp<Integer> getStatus(Long userId);
}

View File

@ -0,0 +1,63 @@
package io.github.xxyopen.novel.author.service.impl;
import io.github.xxyopen.novel.author.dao.entity.AuthorInfo;
import io.github.xxyopen.novel.author.dao.mapper.AuthorInfoMapper;
import io.github.xxyopen.novel.author.dto.AuthorInfoDto;
import io.github.xxyopen.novel.author.dto.req.AuthorRegisterReqDto;
import io.github.xxyopen.novel.author.manager.cache.AuthorInfoCacheManager;
import io.github.xxyopen.novel.author.service.AuthorService;
import io.github.xxyopen.novel.common.resp.RestResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* 作家模块 服务实现类
*
* @author xiongxiaoyang
* @date 2022/5/23
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class AuthorServiceImpl implements AuthorService {
private final AuthorInfoCacheManager authorInfoCacheManager;
private final AuthorInfoMapper authorInfoMapper;
@Override
public RestResp<Void> register(AuthorRegisterReqDto dto) {
// 校验该用户是否已注册为作家
AuthorInfoDto author = authorInfoCacheManager.getAuthor(dto.getUserId());
if (Objects.nonNull(author)) {
// 该用户已经是作家直接返回
return RestResp.ok();
}
// 保存作家注册信息
AuthorInfo authorInfo = new AuthorInfo();
authorInfo.setUserId(dto.getUserId());
authorInfo.setChatAccount(dto.getChatAccount());
authorInfo.setEmail(dto.getEmail());
authorInfo.setInviteCode("0");
authorInfo.setTelPhone(dto.getTelPhone());
authorInfo.setPenName(dto.getPenName());
authorInfo.setWorkDirection(dto.getWorkDirection());
authorInfo.setCreateTime(LocalDateTime.now());
authorInfo.setUpdateTime(LocalDateTime.now());
authorInfoMapper.insert(authorInfo);
// 清除作家缓存
authorInfoCacheManager.evictAuthorCache();
return RestResp.ok();
}
@Override
public RestResp<Integer> getStatus(Long userId) {
AuthorInfoDto author = authorInfoCacheManager.getAuthor(userId);
return Objects.isNull(author) ? RestResp.ok(null) : RestResp.ok(author.getStatus());
}
}

View File

@ -0,0 +1,15 @@
server:
port: 9010
spring:
profiles:
include: common
active: dev
management:
# 端点启用配置
endpoint:
logfile:
# 启用返回日志文件内容的端点
enabled: true
# 外部日志文件路径
external-file: logs/novel-author-service.log

View File

@ -0,0 +1,6 @@
spring:
application:
name: novel-author-service
profiles:
include: common

View File

@ -0,0 +1,79 @@
<?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"/>
<!-- 彩色日志格式 -->
<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>${CONSOLE_LOG_PATTERN}</pattern>
<!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- RollingFileAppender滚动记录文件先将日志记录到指定文件当符合某个条件时将日志记录到其他文件 -->
<!-- 以下的大概意思是1.先按日期存日志日期变了将前一天的日志文件名重命名为XXX%日期%索引新的日志仍然是demo.log -->
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过1KB时对当前日志进行分割 重命名 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/novel-author-service.log</File>
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- TimeBasedRollingPolicy 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值每隔一段时间改变一次 -->
<!-- 文件名logs/demo.2017-12-05.0.log -->
<fileNamePattern>logs/debug.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件该日志文件的保存期限为30天 -->
<maxHistory>30</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小默认值是10MB测试时可改成1KB看效果 -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- pattern节点用来设置日志的输入格式 -->
<pattern>
%d %p (%file:%line\)- %m%n
</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<springProfile name="dev">
<!-- ROOT 日志级别 -->
<root level="INFO">
<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>
</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

@ -4,19 +4,32 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>novel-cloud</artifactId>
<groupId>com.java2nb.novel</groupId>
<version>1.3.0</version>
<groupId>io.github.xxyopen</groupId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>novel-author</artifactId>
<packaging>pom</packaging>
<modules>
<module>author-api</module>
<module>author-service</module>
<module>novel-author-api</module>
<module>novel-author-service</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-common</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>io.github.xxyopen</groupId>
<artifactId>novel-config</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -1,24 +0,0 @@
<?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">
<parent>
<artifactId>novel-book</artifactId>
<groupId>com.java2nb.novel</groupId>
<version>1.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>book-api</artifactId>
<dependencies>
<dependency>
<groupId>com.java2nb.novel</groupId>
<artifactId>novel-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,95 +0,0 @@
package com.java2nb.novel.book.api;
import com.java2nb.novel.book.entity.Book;
import com.java2nb.novel.book.entity.BookComment;
import com.java2nb.novel.book.vo.BookCommentVO;
import com.java2nb.novel.common.bean.PageBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Date;
import java.util.List;
/**
* 小说微服务API接口定义内部
* @author xiongxiaoyang
* @version 1.0
* @since 2020/5/28
*/
public interface BookApi {
/**
* 根据最小更新时间分页查询书籍列表
* @param minDate 最小时间包括该时间
* @param limit 查询数量
* @return 书籍列表
* */
@GetMapping("api/book/queryBookByMinUpdateTime")
List<Book> queryBookByMinUpdateTime(@RequestParam("minDate") Date minDate,@RequestParam("limit") int limit);
/**
* 根据小说ID集合查询书籍列表
* @param ids 小说ID集合
* @return 书籍列表
* */
@GetMapping("api/book/queryBookByIds")
List<Book> queryBookByIds(@RequestBody List<Long> ids);
/**
* 小说排行数据查询列表
* @param type 排行类型1更新排行2新书排行3评论排行
* @param limit 查询数量
* @return 书籍列表
* */
@GetMapping("api/book/listRank")
List<Book> listRank(@RequestParam("type") Byte type, @RequestParam("limit") Integer limit);
/**
* 根据小说ID查询书籍
* @param id 小说ID
* @return 书籍对象
* */
@GetMapping("api/book/queryBookById")
Book queryBookById(@RequestParam("id") Long id);
/**
* 新增评论
* @param userId 用户ID
* @param comment 评论数据
* @return true:评论成功false:评论失败
* */
@PostMapping("api/book/addBookComment")
boolean addBookComment(@RequestParam("userId") Long userId,@RequestBody BookComment comment);
/**
* 分页查询用户评论
* @param userId 用户ID
* @param page 查询页码
* @param pageSize 分页大小
* @return 评论数据
* */
@GetMapping("api/book/listUserCommentByPage")
PageBean<BookComment> listUserCommentByPage(@RequestParam("userId") Long userId, @RequestParam("page") int page, @RequestParam("pageSize") int pageSize);
/**
* 查询网络图片的小说
*
* @param localPicPrefix
* @param limit 查询条数
* @return 返回小说集合
* */
@GetMapping("api/book/queryNetworkPicBooks")
List<Book> queryNetworkPicBooks(@RequestParam("localPicPrefix") String localPicPrefix,@RequestParam("limit") int limit);
/**
* 更新图片路径
* @param picUrl 图片路径
* @param bookId 小说ID
* @return true:更新成功false:更新失败
*/
@PostMapping("api/book/updateBookPic")
boolean updateBookPic(@RequestParam("picUrl") String picUrl,@RequestParam("bookId") Long bookId);
}

View File

@ -1,60 +0,0 @@
package com.java2nb.novel.book.api.fallback;
import com.java2nb.novel.book.api.BookApi;
import com.java2nb.novel.book.entity.Book;
import com.java2nb.novel.book.entity.BookComment;
import com.java2nb.novel.common.bean.PageBean;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 小说微服务API接口降级处理类服务提供端默认降级处理
* @author xiongxiaoyang
* @version 1.0
* @since 2020/6/7
*/
public class BookApiFallback implements BookApi {
@Override
public List<Book> queryBookByMinUpdateTime(Date minDate, int limit) {
return null;
}
@Override
public List<Book> queryBookByIds(List<Long> ids) {
return new ArrayList<>();
}
@Override
public List<Book> listRank(Byte type, Integer limit) {
return new ArrayList<>();
}
@Override
public Book queryBookById(Long id) {
return null;
}
@Override
public boolean addBookComment(Long userId, BookComment comment) {
return false;
}
@Override
public PageBean<BookComment> listUserCommentByPage(Long userId, int page, int pageSize) {
return new PageBean<>(new ArrayList<>());
}
@Override
public List<Book> queryNetworkPicBooks(String localPicPrefix, int limit) {
return new ArrayList<>();
}
@Override
public boolean updateBookPic(String picUrl, Long bookId) {
return false;
}
}

View File

@ -1,359 +0,0 @@
package com.java2nb.novel.book.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.io.Serializable;
import java.util.Date;
public class Book implements Serializable {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "作品方向0男频1女频'")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte workDirection;
@ApiModelProperty(value = "分类ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer catId;
@ApiModelProperty(value = "分类名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String catName;
@ApiModelProperty(value = "小说封面")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String picUrl;
@ApiModelProperty(value = "小说名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String bookName;
@ApiModelProperty(value = "作者id")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long authorId;
@ApiModelProperty(value = "作者名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String authorName;
@ApiModelProperty(value = "书籍描述")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String bookDesc;
@ApiModelProperty(value = "评分")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Float score;
@ApiModelProperty(value = "书籍状态0连载中1已完结")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte bookStatus;
@ApiModelProperty(value = "点击量")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long visitCount;
@ApiModelProperty(value = "总字数")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer wordCount;
@ApiModelProperty(value = "评论数")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer commentCount;
@ApiModelProperty(value = "最新目录ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long lastIndexId;
@ApiModelProperty(value = "最新目录名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String lastIndexName;
@ApiModelProperty(value = "最新目录更新时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date lastIndexUpdateTime;
@ApiModelProperty(value = "是否收费1收费0免费")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte isVip;
@ApiModelProperty(value = "状态0入库1上架")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte status;
@ApiModelProperty(value = "更新时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date updateTime;
@ApiModelProperty(value = "创建时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@ApiModelProperty(value = "爬虫源站ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer crawlSourceId;
@ApiModelProperty(value = "抓取的源站小说ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String crawlBookId;
@ApiModelProperty(value = "最后一次的抓取时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date crawlLastTime;
@ApiModelProperty(value = "是否已停止更新0未停止1已停止")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte crawlIsStop;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getWorkDirection() {
return workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setWorkDirection(Byte workDirection) {
this.workDirection = workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getCatId() {
return catId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCatId(Integer catId) {
this.catId = catId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getCatName() {
return catName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCatName(String catName) {
this.catName = catName == null ? null : catName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getPicUrl() {
return picUrl;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setPicUrl(String picUrl) {
this.picUrl = picUrl == null ? null : picUrl.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getBookName() {
return bookName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookName(String bookName) {
this.bookName = bookName == null ? null : bookName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getAuthorId() {
return authorId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setAuthorId(Long authorId) {
this.authorId = authorId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getAuthorName() {
return authorName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setAuthorName(String authorName) {
this.authorName = authorName == null ? null : authorName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getBookDesc() {
return bookDesc;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookDesc(String bookDesc) {
this.bookDesc = bookDesc == null ? null : bookDesc.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Float getScore() {
return score;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setScore(Float score) {
this.score = score;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getBookStatus() {
return bookStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookStatus(Byte bookStatus) {
this.bookStatus = bookStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getVisitCount() {
return visitCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setVisitCount(Long visitCount) {
this.visitCount = visitCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getWordCount() {
return wordCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setWordCount(Integer wordCount) {
this.wordCount = wordCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getCommentCount() {
return commentCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCommentCount(Integer commentCount) {
this.commentCount = commentCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getLastIndexId() {
return lastIndexId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setLastIndexId(Long lastIndexId) {
this.lastIndexId = lastIndexId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getLastIndexName() {
return lastIndexName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setLastIndexName(String lastIndexName) {
this.lastIndexName = lastIndexName == null ? null : lastIndexName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getLastIndexUpdateTime() {
return lastIndexUpdateTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setLastIndexUpdateTime(Date lastIndexUpdateTime) {
this.lastIndexUpdateTime = lastIndexUpdateTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getIsVip() {
return isVip;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIsVip(Byte isVip) {
this.isVip = isVip;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getStatus() {
return status;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setStatus(Byte status) {
this.status = status;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getUpdateTime() {
return updateTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getCrawlSourceId() {
return crawlSourceId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCrawlSourceId(Integer crawlSourceId) {
this.crawlSourceId = crawlSourceId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getCrawlBookId() {
return crawlBookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCrawlBookId(String crawlBookId) {
this.crawlBookId = crawlBookId == null ? null : crawlBookId.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCrawlLastTime() {
return crawlLastTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCrawlLastTime(Date crawlLastTime) {
this.crawlLastTime = crawlLastTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getCrawlIsStop() {
return crawlIsStop;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCrawlIsStop(Byte crawlIsStop) {
this.crawlIsStop = crawlIsStop;
}
}

View File

@ -1,116 +0,0 @@
package com.java2nb.novel.book.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.util.Date;
public class BookCategory {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer id;
@ApiModelProperty(value = "作品方向0男频1女频'")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte workDirection;
@ApiModelProperty(value = "分类名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String name;
@ApiModelProperty(value = "排序")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte sort;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long updateUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date updateTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Integer id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getWorkDirection() {
return workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setWorkDirection(Byte workDirection) {
this.workDirection = workDirection;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getName() {
return name;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getSort() {
return sort;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setSort(Byte sort) {
this.sort = sort;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getCreateUserId() {
return createUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getUpdateUserId() {
return updateUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getUpdateTime() {
return updateTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -1,107 +0,0 @@
package com.java2nb.novel.book.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.io.Serializable;
import java.util.Date;
public class BookComment implements Serializable {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "小说ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long bookId;
@ApiModelProperty(value = "评价内容")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String commentContent;
@ApiModelProperty(value = "回复数量")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer replyCount;
@ApiModelProperty(value = "审核状态0待审核1审核通过2审核不通过")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte auditStatus;
@ApiModelProperty(value = "评价时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@ApiModelProperty(value = "评价人")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getBookId() {
return bookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookId(Long bookId) {
this.bookId = bookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getCommentContent() {
return commentContent;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCommentContent(String commentContent) {
this.commentContent = commentContent == null ? null : commentContent.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getReplyCount() {
return replyCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setReplyCount(Integer replyCount) {
this.replyCount = replyCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getAuditStatus() {
return auditStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setAuditStatus(Byte auditStatus) {
this.auditStatus = auditStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getCreateUserId() {
return createUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
}

View File

@ -1,92 +0,0 @@
package com.java2nb.novel.book.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.util.Date;
public class BookCommentReply {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "评论ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long commentId;
@ApiModelProperty(value = "回复内容")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String replyContent;
@ApiModelProperty(value = "审核状态0待审核1审核通过2审核不通过")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte auditStatus;
@ApiModelProperty(value = "回复用户ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@ApiModelProperty(value = "回复时间")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long createUserId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getCommentId() {
return commentId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCommentId(Long commentId) {
this.commentId = commentId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getReplyContent() {
return replyContent;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setReplyContent(String replyContent) {
this.replyContent = replyContent == null ? null : replyContent.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getAuditStatus() {
return auditStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setAuditStatus(Byte auditStatus) {
this.auditStatus = auditStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getCreateUserId() {
return createUserId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
}

View File

@ -1,49 +0,0 @@
package com.java2nb.novel.book.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
public class BookContent {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "目录ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long indexId;
@ApiModelProperty(value = "小说章节内容")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String content;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getIndexId() {
return indexId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIndexId(Long indexId) {
this.indexId = indexId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getContent() {
return content;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setContent(String content) {
this.content = content == null ? null : content.trim();
}
}

View File

@ -1,118 +0,0 @@
package com.java2nb.novel.book.entity;
import io.swagger.annotations.ApiModelProperty;
import javax.annotation.Generated;
import java.util.Date;
public class BookIndex {
@ApiModelProperty(value = "主键")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@ApiModelProperty(value = "小说ID")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long bookId;
@ApiModelProperty(value = "目录号")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer indexNum;
@ApiModelProperty(value = "目录名")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String indexName;
@ApiModelProperty(value = "字数")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer wordCount;
@ApiModelProperty(value = "是否收费1收费0免费")
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte isVip;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date updateTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getBookId() {
return bookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setBookId(Long bookId) {
this.bookId = bookId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getIndexNum() {
return indexNum;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIndexNum(Integer indexNum) {
this.indexNum = indexNum;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getIndexName() {
return indexName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIndexName(String indexName) {
this.indexName = indexName == null ? null : indexName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getWordCount() {
return wordCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setWordCount(Integer wordCount) {
this.wordCount = wordCount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getIsVip() {
return isVip;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setIsVip(Byte isVip) {
this.isVip = isVip;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getUpdateTime() {
return updateTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -1,31 +0,0 @@
package com.java2nb.novel.book.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.java2nb.novel.book.entity.BookComment;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 小说评论VO对象
* @author xiongxiaoyang
* @version 1.0
* @since 2020/5/28
*/
@Data
public class BookCommentVO extends BookComment {
private String createUserName;
private String createUserPhoto;
@ApiModelProperty(value = "评价时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Override
public String toString() {
return super.toString();
}
}

View File

@ -1,24 +0,0 @@
package com.java2nb.novel.book.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.java2nb.novel.book.entity.Book;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* 小说VO对象
* @author xiongxiaoyang
* @version 1.0
* @since 2020/5/27
*/
@Data
public class BookVO extends Book{
@ApiModelProperty(value = "最新目录更新时间")
@JsonFormat(timezone = "GMT+8", pattern = "MM/dd HH:mm")
private Date lastIndexUpdateTime;
}

View File

@ -1,93 +0,0 @@
<?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">
<parent>
<artifactId>novel-book</artifactId>
<groupId>com.java2nb.novel</groupId>
<version>1.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>book-service</artifactId>
<dependencies>
<dependency>
<groupId>com.java2nb.novel</groupId>
<artifactId>book-api</artifactId>
</dependency>
<dependency>
<groupId>com.java2nb.novel</groupId>
<artifactId>user-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<!-- 分库分表-->
<!-- sharding jdbc依赖 -->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.maven.plugin.version}</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>201206030/${project.artifactId}:${project.version}</imageName>
<dockerHost>${docker.host}</dockerHost>
<baseImage>java:8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>-->
</plugins>
</build>
</project>

View File

@ -1,30 +0,0 @@
package com.java2nb.novel;
import com.java2nb.novel.common.cache.CacheService;
import com.java2nb.novel.common.cache.impl.RedisServiceImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
/**
* 小说微服务启动器
* @author xiongxiaoyang
* @version 1.0
* @since 2020/5/27
*/
@SpringBootApplication(exclude={
RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class
})
//@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {CacheService.class})})
@EnableFeignClients
public class BookApplication {
public static void main(String[] args) {
SpringApplication.run(BookApplication.class);
}
}

View File

@ -1,171 +0,0 @@
package com.java2nb.novel.book.controller;
import com.java2nb.novel.book.entity.*;
import com.java2nb.novel.book.service.BookService;
import com.java2nb.novel.book.vo.BookCommentVO;
import com.java2nb.novel.common.bean.PageBean;
import com.java2nb.novel.common.bean.ResultBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 小说微服务Controller
* @author xiongxiaoyang
* @version 1.0
* @since 2020/5/27
*/
@RestController
@RequestMapping("book")
@RequiredArgsConstructor
@Slf4j
@Api(tags = "小说相关接口")
public class BookController {
private final BookService bookService;
private final RabbitTemplate rabbitTemplate;
/**
* 小说分类列表查询接口
*/
@ApiOperation("小说分类列表查询接口")
@GetMapping("listBookCategory")
public ResultBean<List<BookCategory>> listBookCategory() {
return ResultBean.ok(bookService.listBookCategory());
}
/**
* 小说详情信息查询接口
*/
@ApiOperation("小说详情信息查询接口")
@GetMapping("{id}")
public ResultBean<Book> queryBookDetail(@ApiParam("小说ID") @PathVariable("id") Long id) {
return ResultBean.ok(bookService.queryBookDetail(id));
}
/**
* 小说排行信息查询接口
*/
@ApiOperation("小说排行信息查询接口")
@GetMapping("listRank")
public ResultBean<List<Book>> listRank(@ApiParam(value = "排行类型0:点击排行1更新排行2新书排行3评论排行", defaultValue = "0") @RequestParam(value = "type", defaultValue = "0") Byte type) {
return ResultBean.ok(bookService.listRank(type, 30));
}
/**
* 点击量新增接口
*/
@ApiOperation("点击量新增接口")
@PostMapping("addVisitCount")
public ResultBean addVisitCount(@ApiParam("小说ID") @RequestParam("bookId") Long bookId) {
rabbitTemplate.convertAndSend("ADD-BOOK-VISIT-EXCHANGE", null, bookId);
return ResultBean.ok();
}
/**
* 章节相关信息查询接口
* */
@ApiOperation("章节相关信息查询接口")
@GetMapping("queryBookIndexAbout")
public ResultBean<Map<String,Object>> queryBookIndexAbout(@ApiParam("小说ID") @RequestParam("bookId") Long bookId,@ApiParam("最新章节目录ID") @RequestParam("lastBookIndexId") Long lastBookIndexId) {
Map<String,Object> data = new HashMap<>(2);
//查询章节总数
data.put("bookIndexCount",bookService.queryIndexCount(bookId));
//查询最新章节内容
String lastBookContent = bookService.queryBookContent(lastBookIndexId).getContent();
if(lastBookContent.length()>42){
lastBookContent=lastBookContent.substring(0,42);
}
data.put("lastBookContent",lastBookContent);
return ResultBean.ok(data);
}
/**
* 同类推荐书籍查询接口
* */
@ApiOperation("同类推荐书籍查询接口")
@GetMapping("listRecBookByCatId")
public ResultBean<List<Book>> listRecBookByCatId(@ApiParam("小说分类ID") @RequestParam("catId") Integer catId) {
return ResultBean.ok(bookService.listRecBookByCatId(catId));
}
/**
*书籍评论列表分页查询接口
* */
@ApiOperation("书籍评论列表分页查询接口")
@GetMapping("listCommentByPage")
public ResultBean<PageBean<BookComment>> listCommentByPage(@ApiParam("小说ID") @RequestParam("bookId") Long bookId, @ApiParam("当前页码") @RequestParam(value = "curr", defaultValue = "1") int page, @ApiParam("分页大小") @RequestParam(value = "limit", defaultValue = "5") int pageSize) {
return ResultBean.ok(bookService.listBookCommentByPage(bookId,page,pageSize));
}
/**
* 小说目录列表查询接口
* */
@ApiOperation("小说目录列表查询接口")
@GetMapping("listNewIndex")
public ResultBean<List<BookIndex>> listNewIndex(@ApiParam("小说ID") @RequestParam("bookId") Long bookId,@ApiParam(value = "排序字符串,为空则按目录号排序") @RequestParam("orderBy") String orderBy,@ApiParam(value = "查询数量,为空则全部查询") @RequestParam("limit") Integer limit){
return ResultBean.ok(bookService.listNewIndex(bookId,orderBy,limit));
}
/**
* 首章目录ID查询接口
* */
@ApiOperation("首章目录ID查询接口")
@GetMapping("queryFirstBookIndexId")
public ResultBean<Long> queryFirstBookIndexId(@ApiParam("小说ID") @RequestParam("bookId") Long bookId){
return ResultBean.ok(bookService.queryFirstBookIndexId(bookId));
}
/**
* 目录查询接口
* */
@ApiOperation("目录查询接口")
@GetMapping("queryBookIndex")
public ResultBean<BookIndex> queryBookIndex(@ApiParam("目录ID") @RequestParam("bookIndexId") Long bookIndexId){
return ResultBean.ok(bookService.queryBookIndex(bookIndexId));
}
/**
* 上一章节和下一章节目录ID查询接口
* */
@ApiOperation("上一章节和下一章节目录ID查询接口")
@GetMapping("queryPreAndNextBookIndexId")
public ResultBean<Map<String,Long>> queryPreAndNextBookIndexId(@ApiParam("小说ID") @RequestParam("bookId") Long bookId,@ApiParam("目录号") @RequestParam("indexNum") Integer indexNum){
return ResultBean.ok(bookService.queryPreAndNextBookIndexId(bookId,indexNum));
}
/**
* 内容查询接口
* */
@ApiOperation("内容查询接口")
@GetMapping("queryBookContent")
public ResultBean<BookContent> queryBookContent(@ApiParam("目录ID") @RequestParam("bookIndexId") Long bookIndexId){
return ResultBean.ok(bookService.queryBookContent(bookIndexId));
}
}

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