Compare commits

..

258 Commits

Author SHA1 Message Date
禾几海
9d462cc876 feat: 拆分为数据库地址 2020-11-22 23:03:37 +08:00
禾几海
ec96a787ef fix(DruidConfig): validationQuery not set error 2020-11-14 21:24:23 +08:00
禾几海
91de56cb32 feat: 参数校验 2020-10-23 17:09:10 +08:00
禾几海
e2a3fb6a6c refactor: 将实现逻辑放到service中 2020-10-23 16:33:29 +08:00
禾几海
49ff1865bb feat: 安装页面布局 loading动画 2020-10-22 15:41:34 +08:00
禾几海
b920034ad6 feat: 安装页面布局 2020-10-22 14:12:01 +08:00
禾几海
76f3d16e09 feat: 安装页面 2020-10-22 00:21:23 +08:00
禾几海
9dafc6d5a7 feat: 安装功能 2020-10-18 19:49:19 +08:00
禾几海
ec693da079 fix: 设置为共有访问 2020-10-18 13:57:39 +08:00
禾几海
58498ef225 fix: 测试环境仍然使用test环境中的数据库连接 并在单元测试中mock profiles 2020-10-18 13:56:20 +08:00
禾几海
c56a3eaf83 fix: 修复测试完成后产生的测试配置文件无法删除的异常 2020-10-18 13:20:10 +08:00
禾几海
e0abfb7d70 feat: 存储博客的默认数据存储路径 2020-10-18 13:19:25 +08:00
禾几海
96cb2dcee4 feat: 启动时首选本地文件中数据库的配置进行加载 2020-10-18 11:38:05 +08:00
禾几海
e39763ad0c style: rename 'schema_h2' to 'schema-h2' 2020-10-18 11:36:12 +08:00
禾几海
a3edc00a03 feat: 从配置文件中初始化配置 2020-10-17 00:13:17 +08:00
禾几海
c0687b4776 refactor: 修改FileResponse属性bucket为type 2020-10-17 00:12:37 +08:00
禾几海
b3b3a7a908 refactor: 添加修改配置项 2020-10-16 23:30:59 +08:00
禾几海
56efdc44d7 fix: 由配置信息来初始化对象 2020-10-16 23:28:24 +08:00
禾几海
e4684e6150 fix: 配置修改后不生效的异常 2020-10-16 22:49:17 +08:00
禾几海
65d65221e8 feat: 配置管理接口 2020-10-16 22:41:55 +08:00
禾几海
47df223655 test: fileService的mock 2020-10-16 19:01:17 +08:00
禾几海
fa95f2f69e test: fileManager测试 2020-10-16 18:53:51 +08:00
禾几海
5598804ddc feat: 本地文件存储 2020-10-16 18:05:26 +08:00
禾几海
ed7d18d491 feat: 项目启动注入配置表中配置到内存中 2020-10-16 16:36:05 +08:00
禾几海
2fbe030da9 feat: 添加配置存储表及其处理类 2020-10-16 16:35:28 +08:00
禾几海
5f3cbece7b feat: 本地文件服务 2020-10-16 15:16:17 +08:00
禾几海
4942daf900 ci: 调整配置文件 2020-10-16 14:35:50 +08:00
禾几海
9f070169b4 ci: 调整配置文件 2020-10-16 14:30:58 +08:00
禾几海
4fa114eb1e test: 完善测试例 2020-10-16 14:30:35 +08:00
禾几海
431ce8ac28 feat: 修复空值异常,完善删除接口功能 2020-10-16 14:29:39 +08:00
禾几海
49000e9ee6 feat: 删除文件 2020-10-15 23:30:19 +08:00
禾几海
19068ff14d refactor(文件服务): 接口修改返回值 2020-10-15 22:46:55 +08:00
禾几海
3d0253a35a refactor(文件服务): 修改类文件包路径 2020-10-15 22:07:48 +08:00
禾几海
0283bd11dc fix(文件服务): 修复无法获取到文件服务的异常 2020-10-15 19:45:43 +08:00
禾几海
60347c7629 refactor: 重命名QiniuService ->FileService
重命名为FileService 并修改方法为获取File Manager来处理文件
2020-10-15 18:29:52 +08:00
禾几海
8de0cbded8 feat(resources): 新增简易部署配置文件 2020-10-15 18:02:53 +08:00
禾几海
0ba7e06695 Merge pull request #12 from xiaohai2271/dependabot/maven/junit-junit-4.13.1
build(deps): bump junit from 4.12 to 4.13.1
2020-10-14 07:56:21 +08:00
dependabot[bot]
512d04f3e9 build(deps): bump junit from 4.12 to 4.13.1
Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 17:49:19 +00:00
禾几海
ada8f67171 Merge remote-tracking branch 'origin/master' 2020-10-09 18:57:42 +08:00
禾几海
6e12331e61 feat: 添加文件上传接口 2020-10-09 18:56:59 +08:00
禾几海
81ee71adf1 Create codeql-analysis.yml 2020-10-03 18:02:48 +08:00
禾几海
7e7332694e docs: typo 2020-09-07 12:28:07 +08:00
禾几海
8db690a55f Update issue templates 2020-09-07 12:23:44 +08:00
禾几海
0b40522e93 feat: 默认返回位置信息 2020-09-05 16:35:45 +08:00
禾几海
9026ba0732 refactor: 简化代码 2020-09-05 15:43:43 +08:00
禾几海
f5f2437fa4 refactor: 简化代码 2020-09-05 15:42:03 +08:00
禾几海
0bcca091e1 refactor: 简化代码 2020-09-04 13:02:36 +08:00
禾几海
3c69baa4ad Merge branch 'feature-ip2region' 2020-09-04 12:29:18 +08:00
禾几海
baf5b1bbb7 feat: 添加对jdk8以上环境的支持 2020-09-04 12:23:15 +08:00
禾几海
38621bcfa4 refactor: 换用ip2region 2020-09-04 12:11:14 +08:00
禾几海
cf435a588f refactor: 添加ip2region 2020-09-04 09:42:55 +08:00
禾几海
feab26f4f7 docs: add some badge 2020-09-01 08:30:26 +08:00
禾几海
578dbe6cc5 docs: api参数变化
- '/admin/articles' deleted 参数   可缺省
- '/admin/users'    status  参数
可缺省
- '/admin/links'    deleted 参数   可缺省
2020-08-31 13:14:37 +08:00
禾几海
f3b03f4853 ci: 调整webhook地址 2020-08-31 13:06:35 +08:00
禾几海
ee85b1f175 Merge pull request #11 from xiaohai2271/dev
分离不同状态的数据
2020-08-31 13:01:09 +08:00
禾几海
925e816f7a fix(login): 账户不存在时引发的空值异常 2020-08-31 12:47:19 +08:00
禾几海
a59bb7f231 feat(login): 非正常账户不可登录 2020-08-31 12:45:49 +08:00
禾几海
7f17c20e01 移除无效脚本 2020-08-31 10:34:34 +08:00
禾几海
6eabb3ab22 refactor: 精简代码 2020-08-31 10:10:21 +08:00
禾几海
72674f4612 test: 补单元测试 2020-08-31 10:02:12 +08:00
禾几海
9b460ff33c feat(link): 分离不同状态的数据 2020-08-31 09:46:15 +08:00
禾几海
a26946a583 feat: 反序列化 2020-08-31 01:10:12 +08:00
禾几海
01407aba7e feat: 分离不同状态的数据 2020-08-31 00:53:48 +08:00
禾几海
a54e04abf3 feat: 序列化 2020-08-31 00:51:01 +08:00
禾几海
450b4a40bd feat(user): 修改status字段类型 2020-08-31 00:17:21 +08:00
禾几海
9f883d12df feat(article): 修改参数 2020-08-30 23:45:18 +08:00
禾几海
c17b56b436 style: 修改部分代码格式 2020-08-30 14:17:34 +08:00
禾几海
b55a50d548 fix(test): 不合理的测试例 2020-08-30 14:01:19 +08:00
禾几海
4c9b193857 Merge branch 'dev' 2020-08-15 16:08:44 +08:00
禾几海
18a8c916c3 Update README.md 2020-08-15 16:07:41 +08:00
禾几海
99f2907621 Update README.md 2020-08-15 16:07:41 +08:00
禾几海
939b06d0a9 切换到jackson(#10)
切换到jackson
2020-08-15 16:05:39 +08:00
禾几海
a7f947a017 fix: 修复部分测试异常 2020-08-15 16:03:22 +08:00
禾几海
40e1f4d6ab fix: 空值异常 2020-08-15 16:00:05 +08:00
禾几海
6b77655c16 style: optimize imports 2020-08-15 15:44:34 +08:00
禾几海
7ff44fd73e Merge branch 'dev' into feature-trans2jackson 2020-08-15 15:33:04 +08:00
禾几海
c9f91bf2c1 fix(test):外键约束引发的异常,替换随机字符串的生成 2020-08-15 15:26:41 +08:00
禾几海
03fcddb971 fix(test):外键约束引发的异常,替换随机字符串的生成 2020-08-15 15:12:07 +08:00
禾几海
dc851e84a4 fix(test): 唯一索引引发的异常 2020-08-15 15:03:16 +08:00
禾几海
b34acee733 refactor: 修改当日剩余时间的计算方法 2020-08-15 15:00:07 +08:00
禾几海
d46dada23a refactor: 替换net.sf.json为fastJson 2020-08-15 14:59:45 +08:00
禾几海
47e5030f52 refactor: 替换net.sf.json为fastJson 2020-08-15 14:39:39 +08:00
禾几海
94c9fc1c46 refactor(Test): 将测试类中随机字符串的生成提到基类中 2020-08-15 12:16:39 +08:00
禾几海
bdcfaef5f8 refactor(Test): 重构 MultipleSubmitFilter 2020-08-15 12:13:08 +08:00
禾几海
3b6439c5cf refactor(Test): 重构 AuthorizationFilter 2020-08-15 12:10:48 +08:00
禾几海
938a051487 refactor(Test): 重构 WebUpdateInfoControllerTest 2020-08-15 12:01:41 +08:00
禾几海
a04b51a82e refactor(Test): 重构 VisitorControllerTest 2020-08-15 11:49:19 +08:00
禾几海
ee4c4bd87e Update README.md 2020-08-15 09:48:19 +08:00
禾几海
e70ad72523 Update README.md 2020-08-15 09:47:34 +08:00
禾几海
c466ddddea 重新配置集成测试(#9) 2020-08-15 02:39:45 +08:00
禾几海
7257f23ef6 refactor(ci): 重新配置ci 2020-08-15 02:27:40 +08:00
禾几海
7c96151830 fix(test): 修复后台服务未开启时测试不通过的情况 2020-08-14 21:37:17 +08:00
禾几海
5a47803611 fix(test): 修改内嵌redis的启动端口 2020-08-14 21:30:40 +08:00
禾几海
af9f243a83 refactor(ci): 重新配置ci 2020-08-14 21:19:53 +08:00
禾几海
3c8abc895a fix(mvnw): 重新生成mvnw 2020-08-14 21:06:14 +08:00
禾几海
9ffa293d24 refactor(Test): 修改上传文件到图床的实现方式 2020-08-14 17:58:08 +08:00
禾几海
d13ab4e522 add(Test): 测试的配置文件 2020-08-14 17:55:36 +08:00
禾几海
2fce2d8a1c refactor(Test): 内嵌redis 2020-08-14 17:17:36 +08:00
禾几海
6eb7d01875 style:修改sql格式 2020-08-14 17:17:35 +08:00
禾几海
aa751dbba1 refactor(Test):内嵌h2 2020-08-14 17:16:49 +08:00
禾几海
14ff60ecfc Update README.md 2020-08-10 16:43:50 +08:00
禾几海
5dae647885 Merge remote-tracking branch 'origin/master' 2020-08-10 16:40:12 +08:00
禾几海
bf2abd6072 Update README.md 2020-08-10 16:39:50 +08:00
禾几海
a62b395a8a Update LICENSE 2020-08-10 16:24:06 +08:00
禾几海
5059859ae4 Update README.md 2020-08-10 16:20:28 +08:00
禾几海
ecdbf8e21c Add Build document 2020-08-10 16:15:43 +08:00
禾几海
c69eee7027 Add api document 2020-08-10 15:59:30 +08:00
禾几海
8e8a7c809d 修复id异常 2020-08-04 22:25:20 +08:00
禾几海
c6a97e4c5b 外键约束 2020-08-04 22:01:02 +08:00
禾几海
d50cd93e55 移动sql位置,开启初始化数据库的设置 2020-08-04 21:47:46 +08:00
禾几海
e32600d892 Update README.md 2020-08-02 11:45:44 +08:00
禾几海
d473b5931b Update test.yml 2020-08-02 11:40:34 +08:00
禾几海
ab6f9d894d Rename deplay.yml to build.yml 2020-08-02 11:38:34 +08:00
禾几海
49ee7c73e2 空值异常 2020-08-01 23:56:10 +08:00
禾几海
4a65df2a7d Update deplay.yml 2020-08-01 21:46:17 +08:00
禾几海
b6c6cda4ae Merge pull request #7 from xiaohai2271/dev
最近的一些修改
2020-08-01 21:26:45 +08:00
禾几海
a9efb1c04d Merge pull request #6 from xiaohai2271/feature-#5
Feature #5  申请友链时自动抓取网页信息
2020-08-01 21:24:46 +08:00
禾几海
4ac430445d remove jacoco 2020-08-01 21:09:29 +08:00
禾几海
7ac3d69da4 单元测试 2020-08-01 12:21:25 +08:00
禾几海
657a200d81 ... 2020-08-01 12:21:03 +08:00
禾几海
85c3541445 修改emailService的bean 2020-08-01 12:20:44 +08:00
禾几海
c6877c2b4a 添加unique约束 2020-08-01 12:19:55 +08:00
禾几海
9e98134003 空值异常 2020-08-01 09:23:48 +08:00
禾几海
7a81d8e4ce 友链申请通过通知,数据防重 2020-08-01 01:41:17 +08:00
禾几海
1b52e27b72 reapply接口 2020-08-01 01:13:15 +08:00
禾几海
cd9d9ff0e6 ... 2020-08-01 01:00:47 +08:00
禾几海
dcf44cefb6 调整,非成功响应情况下返回数据 2020-08-01 01:00:07 +08:00
禾几海
d83e4de9a3 ... 2020-07-31 23:26:30 +08:00
禾几海
9c949576aa 抓取网页信息,进行数据处理 2020-07-31 23:18:05 +08:00
禾几海
85b24891be 使用htmlunit获取js渲染后的数据 2020-07-31 23:16:56 +08:00
禾几海
da95470993 修改异常 2020-07-31 21:49:05 +08:00
禾几海
3b368c92cb 修改数据库字段 2020-07-31 21:19:48 +08:00
禾几海
ad5271f740 添加请求实体,修改请求 2020-07-31 21:19:33 +08:00
禾几海
d2cf640133 调整 2020-07-31 21:19:10 +08:00
禾几海
4a2abc47cc 修改HttpUtil 2020-07-31 21:17:35 +08:00
禾几海
6b29cd39d4 修改getResponse的类型参数 2020-07-31 20:34:00 +08:00
禾几海
69da168fc1 抽离json -> Response 对象的方法 2020-07-31 20:28:37 +08:00
禾几海
f375def613 active-profiles 2020-07-25 17:32:02 +08:00
禾几海
d6cede718b null值异常 2020-07-25 12:08:44 +08:00
禾几海
7922ea558f 调整UserController的测试类 2020-07-25 11:23:03 +08:00
禾几海
f65c96fa2d 调整TagController的测试类 2020-07-24 22:02:24 +08:00
禾几海
af43657b5b null值异常 2020-07-24 21:09:17 +08:00
禾几海
1bfd2d713e . 2020-07-24 21:08:49 +08:00
禾几海
ffed0d5cd0 调整LinkController的测试类 2020-07-24 21:08:40 +08:00
禾几海
b9094c1345 . 2020-07-24 20:24:34 +08:00
禾几海
e9209d1852 调整CommentController的测试类 2020-07-24 20:24:13 +08:00
禾几海
9900605e1a . 2020-07-24 20:06:59 +08:00
禾几海
883a78e872 调整CategoryController的测试类 2020-07-24 20:06:01 +08:00
禾几海
c7016dcf5f 修改getResponse的类型参数 2020-07-24 20:05:17 +08:00
禾几海
526b73b4f8 优化提示 2020-07-24 16:47:26 +08:00
禾几海
66b2b26b15 注销导致token无效的bug 2020-07-24 16:46:35 +08:00
禾几海
f1d3a79919 ... 2020-07-24 13:51:44 +08:00
禾几海
003f74f5f1 调整ArticleController的测试类 2020-07-24 13:49:18 +08:00
禾几海
2f6253c175 抽离json -> Response 对象的方法 2020-07-24 13:48:50 +08:00
禾几海
aa3ee5db72 ... 2020-07-24 00:46:46 +08:00
禾几海
d340ba8218 ... 2020-07-24 00:36:13 +08:00
禾几海
7be1c9dfb0 调整ArticleController的测试类 2020-07-24 00:22:40 +08:00
禾几海
b7f26cbfdb 调整测试基类 2020-07-24 00:21:55 +08:00
禾几海
d9db98849a 调整测试基类 2020-07-23 23:32:42 +08:00
禾几海
6c3645ba15 增加获取已删除数据的选项 2020-07-23 23:08:03 +08:00
禾几海
43a5e2ab2f 抽离Mock请求的方法,过渡到jackson 2020-07-23 23:02:53 +08:00
禾几海
739256424f . 2020-07-18 16:48:04 +08:00
禾几海
3c839ad8ca 数据库建表语句和测试数据 2020-07-18 13:33:33 +08:00
禾几海
efbd5b3d72 删除逻辑 2020-07-18 13:32:50 +08:00
禾几海
5ba7e684fa 生成sitemap过滤文章 2020-07-18 12:32:42 +08:00
禾几海
f7c1726d51 添加deleted字段 2020-07-18 12:30:53 +08:00
禾几海
5504abe3e0 Other.java -> CommonController.java 2020-07-18 12:29:07 +08:00
禾几海
5aeec0cfe4 . 2020-07-11 14:14:36 +08:00
禾几海
e2fe41c2e0 换用knife4j,swaggerUI 2020-07-11 14:12:57 +08:00
禾几海
48f485b378 . 2020-07-11 10:52:24 +08:00
禾几海
6ee8fb65c3 ci 2020-07-11 10:52:13 +08:00
禾几海
de5e40e6b8 pr进行ci测试 2020-05-27 18:30:08 +08:00
禾几海
2106bf4d94 pr 的ci测试 2020-05-27 18:11:27 +08:00
禾几海
72cef158a1 异常 2020-05-27 18:07:55 +08:00
禾几海
d1f08b58c0 Merge pull request #1 from xiaohai2271/dev
调整数据库字段,优化部分接口
2020-05-27 16:45:02 +08:00
禾几海
2ef9073650 调整评论的接口 2020-05-27 16:30:17 +08:00
禾几海
260ae53c8d 调整 2020-05-27 13:28:48 +08:00
禾几海
21adedea84 IDEA代码优化 2020-05-26 14:03:46 +08:00
禾几海
7d7a0fc82d 修改对象类型 2020-05-26 14:01:27 +08:00
禾几海
4770c37f4f 修改Response 2020-05-26 14:00:17 +08:00
禾几海
450978ecd9 修改Response 的date响应字段 2020-05-26 13:59:36 +08:00
禾几海
4035c7e024 更改sql文件 2020-05-26 12:56:57 +08:00
禾几海
7aebaaa98b . 2020-05-26 12:54:51 +08:00
禾几海
03cb04ab06 修复bug 2020-05-26 12:54:24 +08:00
禾几海
aa882406d0 Service,dao层,视图,模型修改 单元测试 2020-05-26 12:34:35 +08:00
禾几海
fde9b8511c Service层修改 单元测试 2020-05-26 00:27:50 +08:00
禾几海
9582725b3a 修改 单元测试 2020-05-26 00:16:09 +08:00
禾几海
2f27578bb0 dao层修改 2020-05-26 00:13:57 +08:00
禾几海
d3757c5880 dao层修改 2020-05-26 00:10:34 +08:00
禾几海
c39dac30fb Service层修改 单元测试 2020-05-26 00:10:09 +08:00
禾几海
73a1d3eadf Service层修改 单元测试 2020-05-25 23:04:41 +08:00
禾几海
4e383b6598 Service层修改 单元测试 2020-05-25 22:48:57 +08:00
禾几海
030aaaca25 Service层修改 单元测试 2020-05-25 22:44:18 +08:00
禾几海
d19e5b6286 Service层修改 单元测试 2020-05-25 22:18:50 +08:00
禾几海
c4ed6602e7 rename method 2020-05-25 22:06:13 +08:00
禾几海
ae7d063fdd Service层修改 单元测试 2020-05-25 22:05:46 +08:00
禾几海
67a1b1faf9 Service层修改 单元测试 2020-05-25 21:43:53 +08:00
禾几海
9e6868b638 dao层修改 单元测试 2020-05-25 14:48:05 +08:00
禾几海
9185ff8f58 dao层修改 单元测试 2020-05-25 13:50:11 +08:00
禾几海
190e1624ca dao层修改 单元测试 2020-05-25 00:20:36 +08:00
禾几海
86b6bae6e6 dao层修改 单元测试 2020-05-25 00:02:26 +08:00
禾几海
0adf936085 dao层修改 单元测试 2020-05-24 23:54:13 +08:00
禾几海
4f63f7b3d5 dao层修改 单元测试 2020-05-24 22:54:51 +08:00
禾几海
0136435a41 dao层修改 单元测试 2020-05-24 22:02:41 +08:00
禾几海
87de48b5a0 dao层修改 单元测试 2020-05-24 22:00:06 +08:00
禾几海
732bbe4444 修改sql 2020-05-24 19:22:38 +08:00
禾几海
9b6293fbeb 修改查询语句 2020-05-23 13:27:30 +08:00
禾几海
bc20173084 数据表改动 2020-05-23 00:16:08 +08:00
禾几海
8b255372dd Merge remote-tracking branch 'origin/master' 2020-05-19 19:56:02 +08:00
小海
f88bf105a9 Update README.md 2020-05-19 19:55:26 +08:00
禾几海
59b7be00eb 添加密码修改的api 2020-05-19 19:53:38 +08:00
禾几海
0e26eab2e6 Merge branch 'dev' 2020-05-18 08:36:19 +08:00
禾几海
2f6a9679da 修复跨域情况下前台获取不到Authorization响应字段 2020-05-18 08:30:50 +08:00
小海
778c2dba58 Update README.md 2020-05-03 22:32:48 +08:00
小海
5b8700930b 修改测试的接口地址 2020-04-23 17:57:05 +08:00
小海
18477706d1 添加github对应的url 2020-04-23 17:30:57 +08:00
小海
cd7e6b6378 修改接口名和响应内容 2020-04-23 16:34:04 +08:00
小海
d934fbe284 提取网络请求部分 2020-04-23 16:12:03 +08:00
小海
55589c6a59 修复响应码错误bug 2020-04-22 15:23:19 +08:00
小海
4ab402ccf8 更新readme 2020-04-17 13:27:21 +08:00
小海
c74aea6c3b 移除gitlab ci 2020-04-17 13:27:06 +08:00
小海
7c2b8d8d28 更新配置文件 2020-04-17 13:01:42 +08:00
小海
6798cae1b8 忘记添加环境变量 2020-04-17 12:41:19 +08:00
小海
ba7a02c5c0 Update mavenpublish.yml 2020-04-17 12:37:35 +08:00
小海
bd50cfc339 Update mavenpublish.yml 2020-04-17 12:13:51 +08:00
小海
e282e16fd3 update mavenpublish.yml 2020-04-17 11:56:43 +08:00
小海
18366b7aa4 Merge branch 'master' of https://github.com/xiaohai2271/blog-backEnd 2020-04-17 11:43:27 +08:00
小海
66dffbfefe 配置ci调整配置文件 2020-04-17 11:29:52 +08:00
小海
a7cd83a6b5 Update mavenpublish.yml 2020-04-17 11:11:12 +08:00
小海
0a5921b66d add github ci 2020-04-17 11:09:48 +08:00
小海
e04238f0c9 更新token 2020-04-16 23:26:41 +08:00
小海
09cb012b14 可能出现为空的情况 2020-04-16 23:25:49 +08:00
小海
922b83e169 修复小bug 2020-04-06 19:47:32 +08:00
小海
1cd6e0d7c9 修改部分api以及响应数据结构 2020-04-06 15:26:41 +08:00
小海
ec0b17151c 新增必应每日一图图片获取接口 2020-04-03 17:22:10 +08:00
小海
98430a34f6 修复一个小Bug 2020-03-29 14:17:29 +08:00
小海
23ee331609 修改响应码 2020-03-29 14:16:46 +08:00
小海
ebddbc0ecf 修改响应的Tag的articles字段类型 2020-03-29 14:16:17 +08:00
小海
8181fab48d 修改响应的Category的articles字段类型 2020-03-29 13:55:59 +08:00
小海
7ba287d261 更新Tag 2019-12-04 16:30:51 +08:00
小海
1745a5d821 Fix NullPointer Exception 2019-12-04 15:54:45 +08:00
小海
9a4a930426 用户访问情况记录 2019-12-04 15:28:01 +08:00
小海
a0eaddafec . 2019-12-04 15:25:50 +08:00
小海
450f308f1e 自动注入HttpServletRequest 2019-12-04 14:43:10 +08:00
小海
86bb5e1b13 . 2019-12-04 14:38:49 +08:00
小海
a4c2ec1272 修改JwtUtil的部分方法 2019-12-04 14:08:45 +08:00
小海
2945d091ee Update README.md 2019-12-04 12:08:03 +08:00
小海
900d84b15e Add Test coverage 2019-12-04 11:35:42 +08:00
小海
d9aac0fbd8 自动部署 2019-12-01 13:28:19 +08:00
小海
28aa7cf7e3 Add maven wrapper 2019-12-01 12:42:01 +08:00
小海
7972f4d473 . 2019-11-30 23:08:30 +08:00
小海
79ec6fcc91 Add CI status 2019-11-30 22:56:56 +08:00
小海
1f736dc9c9 修改获取测试资源的方式 2019-11-29 23:58:55 +08:00
小海
55ccff3451 关闭两个不稳定的测试 2019-11-29 23:26:53 +08:00
小海
a5811364c7 添加CI测试 2019-11-29 23:22:20 +08:00
小海
a77dc695f6 修复可能存在的异常 2019-11-29 23:21:32 +08:00
小海
753ea5c9a1 将私钥都分离放到配置文件中 2019-11-29 21:29:48 +08:00
小海
19e0697a01 . 2019-11-29 21:29:07 +08:00
174 changed files with 13196 additions and 4550 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

28
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path
name: Build
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
env:
KEY: ${{ secrets.WEB_HOOK_ACCESS_KEY }}
QINIU_ACCESSKEY: ${{ secrets.QINIU_ACCESSKEY }}
QINIU_SECRETKEY: ${{ secrets.QINIU_SECRETKEY }}
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Deploy
run: mvn -B test --file pom.xml && curl http://bt.celess.cn:2271/hook?access_key=$KEY

71
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 14 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['java']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

29
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path
name: Test
on:
push:
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
env:
QINIU_ACCESSKEY: ${{ secrets.QINIU_ACCESSKEY }}
QINIU_SECRETKEY: ${{ secrets.QINIU_SECRETKEY }}
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Test
run: mvn -B test --file pom.xml

4
.gitignore vendored
View File

@@ -1,8 +1,8 @@
.idea/
*.imi
*.iml
target/
# 本地项目的私有文件
back-end/blog-dev.sql
src/main/resources/application-prod.properties
src/main/resources/application-dev.properties
src/main/resources/application-prod.properties

View File

@@ -1,114 +1,117 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Properties;
public class MavenWrapperDownloader {
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: : " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
/*
* Copyright 2007-present the original author or authors.
*
* 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.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@@ -1 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 小
Copyright (c) 2020 禾几
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,13 +1,23 @@
# 小海博客后端管理系统
<h1 align="center">
小海博客后端管理系统
</h1>
<div align="center">
## 基于Springboot的后端博客管理系统
基于Springboot的后端博客管理系统
[![Build](https://github.com/xiaohai2271/blog-backEnd/workflows/Build/badge.svg)](https://github.com/xiaohai2271/blog-backEnd)
[![Test](https://github.com/xiaohai2271/blog-backEnd/workflows/Test/badge.svg)](https://github.com/xiaohai2271/blog-backEnd)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/xiaohai2271/blog-backEnd)](https://github.com/xiaohai2271/blog-backEnd)
[![GitHub](https://img.shields.io/github/license/xiaohai2271/blog-backEnd)](https://github.com/xiaohai2271/blog-backEnd)
[![GitHub top language](https://img.shields.io/github/languages/top/xiaohai2271/blog-backEnd)](https://github.com/xiaohai2271/blog-backEnd)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/xiaohai2271/blog-backEnd)](https://github.com/xiaohai2271/blog-backEnd)
[![GitHub last commit](https://img.shields.io/github/last-commit/xiaohai2271/blog-backEnd)](https://github.com/xiaohai2271/blog-backEnd)
[![Website](https://img.shields.io/website?up_message=%E5%B0%8F%E6%B5%B7%E5%8D%9A%E5%AE%A2&url=https%3A%2F%2Fwww.celess.cn)](https://www.celess.cn)
</div>
### 主要使用的技术
> 请配合前端项目一起食用 [https://github.com/xiaohai2271/blog-frontEnd](https://github.com/xiaohai2271/blog-frontEnd)
## 🎈主要使用的技术
| 使用的技术 | 名称 | 版本 |
| :--------------: | :--------: | :-----------: |
@@ -20,18 +30,16 @@
| 接口文档 | Swagger | 2.6.1 |
| 数据库连接池 | druid | 1.1.14 |
| 缓存(线上环境) | redis | 3.0.6 |
|数据库|mysql|5.7|
| 数据库 |mysql |5.7 |
### 接口文档
## 🔨如何构建
详情参照[Build](./doc/Build.md)文档
项目采用swagger2接口文档自动生成具体为 http://ip:端口/swagger-ui.html
### 📝TODO
## 📒接口文档
项目采用swagger2接口文档自动生成具体为 http://ip:port/doc.html
- [x] 密码重置
- [x] 信息修改
- [ ] 接入qq登录
或者参照[离线API文档](./doc/API.md)
### 📌FIXME
- [ ] `/write` 图片上传的跨域问题
## ☀授权协议
[MIT](./LICENSE)

149
blog.iml
View File

@@ -1,149 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/java" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.23" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.16" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.16" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.16" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.14.Final" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.5.RELEASE" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:8.0.15" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.1.3.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.1.3.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.1.3.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.11.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.23.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.9.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.9.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.5.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.1.5.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.6.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: javax.xml.bind:jaxb-api:2.3.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: javax.activation:javax.activation-api:1.2.0" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.1.14" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.6" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger2:2.6.1" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-annotations:1.5.10" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-models:1.5.10" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spi:2.6.1" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-core:2.6.1" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-schema:2.6.1" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger-common:2.6.1" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-web:2.6.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:18.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-core:1.2.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-metadata:1.2.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mapstruct:mapstruct:1.0.0.Final" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger-ui:2.6.1" level="project" />
<orderEntry type="library" name="Maven: com.youbenzi:MDTool:1.2.3" level="project" />
<orderEntry type="library" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" name="Maven: net.sf.json-lib:json-lib:jdk15:2.4" level="project" />
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.0" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.5" level="project" />
<orderEntry type="library" name="Maven: commons-logging:commons-logging:1.1.1" level="project" />
<orderEntry type="library" name="Maven: net.sf.ezmorph:ezmorph:1.0.6" level="project" />
<orderEntry type="library" name="Maven: com.qiniu:qiniu-java-sdk:7.2.27" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.squareup.okhttp3:okhttp:3.14.4" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.squareup.okio:okio:1.17.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.google.code.gson:gson:2.8.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-mail:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sun.mail:javax.mail:1.6.2" level="project" />
<orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.lettuce:lettuce-core:5.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.33.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.33.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.33.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.33.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.33.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.33.Final" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.2.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.2" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.1.3.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.1" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.1" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.2.12" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.2.12" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.1.10" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:2.0" level="project" />
<orderEntry type="library" name="Maven: com.dyuproject.protostuff:protostuff-core:1.0.8" level="project" />
<orderEntry type="library" name="Maven: com.dyuproject.protostuff:protostuff-api:1.0.8" level="project" />
<orderEntry type="library" name="Maven: com.dyuproject.protostuff:protostuff-runtime:1.0.8" level="project" />
<orderEntry type="library" name="Maven: com.dyuproject.protostuff:protostuff-collectionschema:1.0.8" level="project" />
<orderEntry type="library" name="Maven: eu.bitwalker:UserAgentUtils:1.20" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.8" level="project" />
</component>
</module>

View File

@@ -1,92 +0,0 @@
CREATE DATABASE `blog`;
USE blog;
CREATE TABLE `article`
(
`a_id` bigint(20) primary key auto_increment,
`a_title` varchar(255) not null unique comment '文章标题',
`a_summary` varchar(255) not null comment '文章摘要',
`a_md_content` longtext not null comment '文章Markdown内容',
`a_tags_id` varchar(255) not null comment '标签id \',\'处于最尾端',
`a_category_id` bigint(20) not null comment '分类的id',
`a_url` tinytext default null comment '转载文章的原文链接',
`a_author_id` bigint(20) not null comment '作者id',
`a_is_open` boolean default true comment '文章是否可见',
`a_is_original` boolean default true comment '文章是否原创',
`next_a_id` bigint(20) default -1 comment '下篇文章id',
`pre_a_id` bigint(20) default -1 comment '前一篇文章的id',
`a_reading_number` int default 0 comment '文章阅读数',
`a_publish_date` datetime not null comment '文章发布时间',
`a_update_date` datetime default null comment '文章的更新时间'
) DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci,comment '文章表';
CREATE TABLE `tag`
(
`tag_id` bigint(20) primary key auto_increment,
`tag_name` varchar(255) unique not null,
`articles` tinytext default null comment 'tag对应的文章id'
) comment '标签表';
CREATE table `category`
(
`c_id` bigint(20) primary key auto_increment,
`c_name` varchar(255) unique not null,
`articles` varchar(255) comment '分类下的文章'
)comment '分类表';
CREATE TABLE `comment`
(
`co_id` bigint(20) primary key auto_increment,
`co_article_id` bigint(20) default -1 comment '文章id',
`is_comment` boolean default true comment '是否是评论',
`author_id` bigint(20) not null comment '留言者id',
`co_content` text not null comment '评论/留言内容',
`co_date` datetime not null comment '评论/留言的日期',
`co_pid` bigint not null default -1 comment '评论/留言的父id',
`co_response_id` tinytext
) DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci,comment '评论/留言表';
CREATE TABLE `links`
(
`site_id` bigint(20) primary key auto_increment,
`site_name` varchar(255) not null comment '友站名称',
`is_open` boolean default true comment '是否公开',
`site_url` varchar(255) not null comment '首页地址'
) comment '友站表';
CREATE TABLE `visitor`
(
`v_id` bigint(20) primary key auto_increment,
`v_date` datetime not null comment '访问时间',
`v_ip` varchar(255) not null comment '访客ip',
`v_user_agent` text comment '访客ua'
) comment '访客表';
CREATE TABLE IF NOT EXISTS `web_update`
(
`update_id` bigint(20) primary key auto_increment,
`update_info` varchar(255) not null comment '更新内容',
`update_time` datetime not null comment '更新时间'
) comment '更新内容表';
create table `user`
(
`u_id` int not null primary key auto_increment,
`u_email` varchar(50) not null,
`u_uid` varchar(40) default null comment '用户唯一标识码',
`u_pwd` varchar(40) not null comment '密码',
`email_status` boolean default false comment '邮箱验证状态',
`u_avatar` varchar(255) comment '用户头像',
`u_desc` tinytext comment '用户的描述',
`recently_landed_time` datetime comment '最近的登录时间',
`email_verify_id` varchar(40) comment '用于找回密码或验证邮箱的id',
`display_name` varchar(30) comment '展示的昵称',
`role` varchar(40) not null default 'user' comment '权限组',
unique key `uni_user_id` (`u_id`),
unique key `uni_user_uid` (`u_uid`),
unique key `uni_user_email` (`u_email`)
) comment '用户表';

4376
doc/API.md Normal file

File diff suppressed because it is too large Load Diff

33
doc/Build.md Normal file
View File

@@ -0,0 +1,33 @@
# 如何构建
### 1. 构建前准备
- 安装jdk
- 安装maven(也可使使用项目中的maven wrapper)
- 安装mysql
- 安装redis
- 获取七牛云的AccessKey/SecretKey (个人中心-密钥管理) [七牛云官网](https://www.qiniu.com/)
### 2. 拉取项目到本地
``` shell script
git clone https://github.com/xiaohai2271/blog-backEnd.git
# 或
git clone git@github.com:xiaohai2271/blog-backEnd.git
```
### 3. maven构建
```shell script
mvn package
```
### 4. 运行
```shell script
java -jar target/blog-0.0.1-SNAPSHOT.jar
```
### 5. 其他命令
```shell script
mvn clean # 清理项目资源
mvn clean package # 清理项目资源并重新打包
mvn clean package -DskipTests # 清理项目资源,重新打包并跳过测试
mvn test # 运行测试
..... #待添加
```

596
mvnw vendored
View File

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

343
mvnw.cmd vendored
View File

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

95
pom.xml
View File

@@ -55,12 +55,12 @@
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<!--MarkDown 2 html -->
@@ -76,14 +76,6 @@
<scope>compile</scope>
</dependency>
<!--Json-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- 七牛云SDK -->
<dependency>
<groupId>com.qiniu</groupId>
@@ -139,7 +131,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<version>4.13.1</version>
</dependency>
<!-- JJwt -->
@@ -148,6 +140,69 @@
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- OkHttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.3.72</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.42.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>
<build>
@@ -156,6 +211,20 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>1.3.72</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -1,20 +1,34 @@
package cn.celess.blog;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @author zheng
*/
@SpringBootApplication
@EnableAsync
@MapperScan("cn.celess.blog.mapper")
public class BlogApplication {
public static final Logger logger = LoggerFactory.getLogger(BlogApplication.class);
public static ConfigurableApplicationContext context;
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
logger.info("启动完成!");
context = SpringApplication.run(BlogApplication.class, args);
}
public static void restart() {
ApplicationArguments args = context.getBean(ApplicationArguments.class);
Thread thread = new Thread(() -> {
context.close();
context = SpringApplication.run(BlogApplication.class, args.getSourceArgs());
});
thread.setDaemon(false);
thread.start();
}
}

View File

@@ -0,0 +1,59 @@
package cn.celess.blog.configuration;
import cn.celess.blog.enmu.ConfigKeyEnum;
import cn.celess.blog.entity.Config;
import cn.celess.blog.mapper.ConfigMapper;
import cn.celess.blog.service.fileserviceimpl.LocalFileServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author : xiaohai
* @date : 2020/10/16 16:00
* @desc :
*/
@Component
@Slf4j
public class ApplicationListener implements ApplicationRunner {
@Autowired
ConfigMapper configMapper;
@Autowired
Environment env;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("博客启动!");
// 设置初始值
setProperty(ConfigKeyEnum.FILE_QINIU_SECRET_KEY);
setProperty(ConfigKeyEnum.FILE_QINIU_ACCESS_KEY);
setProperty(ConfigKeyEnum.FILE_QINIU_BUCKET);
setProperty(ConfigKeyEnum.BLOG_FILE_PATH);
List<Config> configurations = configMapper.getConfigurations()
.stream()
.filter(config -> config.getValue() != null && !"".equals(config.getValue()))
.collect(Collectors.toList());
configurations.forEach(config -> System.setProperty(config.getName(), config.getValue()));
log.debug("注入配置成功 {}", configurations.stream().map(Config::getName).collect(Collectors.toList()));
File path = new File(LocalFileServiceImpl.getPath(System.getProperty(ConfigKeyEnum.BLOG_FILE_PATH.getKey())));
if (!path.exists() && !path.mkdirs()) {
throw new IllegalAccessException("创建数据目录失败==>" + path.getAbsolutePath());
}
}
private void setProperty(ConfigKeyEnum e) {
String property = env.getProperty(e.getKey());
if (property != null) {
System.setProperty(e.getKey(), property);
}
}
}

View File

@@ -1,5 +1,6 @@
package cn.celess.blog.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
@@ -13,6 +14,9 @@ import org.springframework.web.filter.CorsFilter;
*/
@Configuration
public class CorsConfig {
@Value("${spring.profiles.active}")
private String activeModel;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
@@ -22,14 +26,17 @@ public class CorsConfig {
config.addAllowedOrigin("https://celess.cn");
config.addAllowedOrigin("https://www.celess.cn");
// 本地调试时的跨域
config.addAllowedOrigin("http://localhost:4200");
config.addAllowedOrigin("http://127.0.0.1:4200");
if (!"prod".equals(activeModel)) {
config.addAllowedOrigin("http://localhost:4200");
config.addAllowedOrigin("http://127.0.0.1:4200");
}
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
config.addExposedHeader("Authorization");
config.setAllowCredentials(true);
config.setMaxAge(10800L);
source.registerCorsConfiguration("/**", config);

View File

@@ -1,41 +1,81 @@
package cn.celess.blog.configuration;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
/**
* @author : xiaohai
* @date : 2019/03/28 14:26
*/
@Slf4j
@Configuration
public class DruidConfig {
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Autowired
Environment env;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
public static final String DB_CONFIG_PATH = System.getProperty("user.home") + "/blog/application.properties";
public static final String DB_CONFIG_URL_PREFIX = "spring.datasource.url";
public static final String DB_CONFIG_USERNAME_PREFIX = "spring.datasource.username";
public static final String DB_CONFIG_PASSWORD_PREFIX = "spring.datasource.password";
public static final String DB_CONFIG_DRIVER_CLASS_NAME_PREFIX = "spring.datasource.driver-class-name";
public static final String TEST_PROFILES = "test";
@Bean
public DruidDataSource druidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 数据库基本信息
dataSource.setUrl(dbUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
// 数据库连接池配置
public DruidDataSource initDataSource() throws IOException {
DruidDataSource dataSource;
File file = new File(DB_CONFIG_PATH);
if (file.exists() && !Arrays.asList(env.getActiveProfiles()).contains(TEST_PROFILES)) {
log.debug("从文件中获取数据库配置");
dataSource = readConfigFromFile(file);
} else {
log.debug("默认数据库配置");
dataSource = defaultDruidSource();
}
dataSource.setInitialSize(10);
dataSource.setMinIdle(10);
dataSource.setMaxActive(100);
dataSource.setValidationQuery("select 1");
return dataSource;
}
private DruidDataSource readConfigFromFile(File file) throws IOException {
Properties properties = new Properties();
FileInputStream fis = new FileInputStream(file);
properties.load(fis);
fis.close();
String url = properties.getProperty(DB_CONFIG_URL_PREFIX, null);
String username = properties.getProperty(DB_CONFIG_USERNAME_PREFIX, null);
String password = properties.getProperty(DB_CONFIG_PASSWORD_PREFIX, null);
String className = properties.getProperty(DB_CONFIG_DRIVER_CLASS_NAME_PREFIX, null);
if (url == null || username == null || password == null || className == null) {
return defaultDruidSource();
}
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(className);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
private DruidDataSource defaultDruidSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(env.getProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX));
dataSource.setUrl(env.getProperty(DruidConfig.DB_CONFIG_URL_PREFIX));
dataSource.setUsername(env.getProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX));
dataSource.setPassword(env.getProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX));
return dataSource;
}
}

View File

@@ -19,11 +19,9 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MultipleSubmitFilter()).addPathPatterns("/*");
registry.addInterceptor(new MultipleSubmitFilter()).addPathPatterns("/**");
registry.addInterceptor(new VisitorRecord()).addPathPatterns("/**");
registry.addInterceptor(authenticationFilter()).addPathPatterns("/**");
// visitor 输出信息杂乱 暂时放弃使用
// registry.addInterceptor(new VisitorRecord()).addPathPatterns("/*");
}
@Bean
@@ -31,11 +29,11 @@ public class InterceptorConfig implements WebMvcConfigurer {
return new AuthenticationFilter();
}
// // session listener register bean
// @Bean
// public ServletListenerRegistrationBean<SessionListener> servletListenerRegistrationBean() {
// ServletListenerRegistrationBean<SessionListener> slrBean = new ServletListenerRegistrationBean<SessionListener>();
// slrBean.setListener(new SessionListener());
// return slrBean;
// }
@Bean
public ServletListenerRegistrationBean<SessionListener> servletListenerRegistrationBean() {
// session listener register bean
ServletListenerRegistrationBean<SessionListener> slrBean = new ServletListenerRegistrationBean<SessionListener>();
slrBean.setListener(new SessionListener());
return slrBean;
}
}

View File

@@ -31,19 +31,16 @@ public class RedisConfig extends CachingConfigurerSupport {
@Override
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
String name = target.getClass().getName();
sb.append(name.substring(name.lastIndexOf(".") + 1));
sb.append(":");
sb.append(method.getName());
for (Object obj : params) {
sb.append("-").append(obj.toString());
}
return sb.toString();
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
String name = target.getClass().getName();
sb.append(name.substring(name.lastIndexOf(".") + 1));
sb.append(":");
sb.append(method.getName());
for (Object obj : params) {
sb.append("-").append(obj.toString());
}
return sb.toString();
};
}

View File

@@ -7,6 +7,7 @@ import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@@ -25,7 +26,7 @@ public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.enable("dev".equals(environment))
.enable(!"prod".equals(environment))
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.celess.blog"))
@@ -37,7 +38,7 @@ public class SwaggerConfig {
return new ApiInfoBuilder()
.title("小海博客的APi")
.description("小海博客的APi")
.contact("小海")
.contact(new Contact("小海", "https://www.celess.cn", "a@celess.cn"))
.version("1.0")
.build();
}

View File

@@ -1,11 +1,11 @@
package cn.celess.blog.configuration.filter;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.Response;
import cn.celess.blog.service.UserService;
import cn.celess.blog.util.JwtUtil;
import cn.celess.blog.util.RedisUtil;
import cn.celess.blog.util.ResponseUtil;
import net.sf.json.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -21,6 +21,11 @@ import java.io.IOException;
* @Description: 鉴权拦截器
*/
public class AuthenticationFilter implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationFilter.class);
private static final String USER_PREFIX = "/user";
private static final String ADMIN_PREFIX = "/admin";
private static final String ROLE_ADMIN = "admin";
private static final String ROLE_USER = "user";
@Autowired
JwtUtil jwtUtil;
@Autowired
@@ -28,25 +33,22 @@ public class AuthenticationFilter implements HandlerInterceptor {
@Autowired
UserService userService;
private static final Logger logger = LoggerFactory.getLogger(AuthenticationFilter.class);
private static final String USER_PREFIX = "/user";
private static final String ADMIN_PREFIX = "/admin";
private static final String ROLE_ADMIN = "admin";
private static final String ROLE_USER = "user";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String path = request.getRequestURI();
path = path.replaceAll("/+", "/");
int indexOf = path.indexOf("/", 1);
String rootPath = indexOf == -1 ? path : path.substring(0, indexOf);
String jwtStr = request.getHeader("Authorization");
if (jwtStr != null && !jwtStr.isEmpty() && !jwtUtil.isTokenExpired(jwtStr)) {
// 已登录 记录当前email
request.getSession().setAttribute("email", jwtUtil.getUsernameFromToken(jwtStr));
}
// 不需要鉴权的路径
if (!USER_PREFIX.equals(rootPath.toLowerCase()) && !ADMIN_PREFIX.equals(rootPath.toLowerCase())) {
return true;
}
String jwtStr = request.getHeader("Authorization");
if (jwtStr == null || jwtStr.isEmpty()) {
return writeResponse(ResponseEnum.HAVE_NOT_LOG_IN, response, request);
}
@@ -54,11 +56,19 @@ public class AuthenticationFilter implements HandlerInterceptor {
return writeResponse(ResponseEnum.LOGIN_EXPIRED, response, request);
}
String email = jwtUtil.getUsernameFromToken(jwtStr);
if (!redisUtil.hasKey(email + "-login") || jwtUtil.isTokenExpired(jwtStr)) {
if (jwtUtil.isTokenExpired(jwtStr)) {
// 登陆过期
return writeResponse(ResponseEnum.LOGIN_EXPIRED, response, request);
}
if (!redisUtil.hasKey(email + "-login")) {
return writeResponse(ResponseEnum.LOGOUT, response, request);
}
String role = userService.getUserRoleByEmail(email);
if (role.equals(ROLE_USER) || role.equals(ROLE_ADMIN)) {
// 更新token
String token = jwtUtil.updateTokenDate(jwtStr);
response.setHeader("Authorization", token);
}
if (role.equals(ROLE_ADMIN)) {
// admin
return true;
@@ -74,7 +84,7 @@ public class AuthenticationFilter implements HandlerInterceptor {
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try {
logger.info("鉴权失败,[code:{},msg:{},path:{}]", e.getCode(), e.getMsg(), request.getRequestURI() + "?" + request.getQueryString());
response.getWriter().println(JSONObject.fromObject(ResponseUtil.response(e, null)));
response.getWriter().println(new ObjectMapper().writeValueAsString(Response.response(e, null)));
} catch (IOException ex) {
ex.printStackTrace();
}

View File

@@ -28,7 +28,7 @@ public class MultipleSubmitFilter implements HandlerInterceptor {
// 请求参数和路径均相同 且请求时间间隔小于 WAIT_TIME
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
Response result = new Response(ResponseEnum.FAILURE.getCode(), "重复请求", null, System.currentTimeMillis());
Response result = new Response(ResponseEnum.FAILURE.getCode(), "重复请求", null);
response.getWriter().println(result.toString());
return false;
}

View File

@@ -21,14 +21,18 @@ public class VisitorRecord implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
HashMap<String, Integer> visitDetail = (HashMap<String, Integer>) session.getAttribute("visitDetail");
if (visitDetail == null) {
return true;
}
// 获取访问次数
Integer count = visitDetail.get(RequestUtil.getCompleteUrlAndMethod(request));
// 自增
count = count == null ? 1 : ++count;
// 更新
visitDetail.put(RequestUtil.getCompleteUrlAndMethod(request), count);
session.setAttribute("ip",request.getRemoteAddr());
session.setAttribute("ip", request.getRemoteAddr());
return true;
}
}

View File

@@ -1,9 +1,7 @@
package cn.celess.blog.configuration.listener;
import cn.celess.blog.entity.User;
import cn.celess.blog.util.RedisUserUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.annotation.WebListener;
@@ -17,20 +15,20 @@ import java.util.HashMap;
* @Date: 2019/10/18 15:33
* @Description: 监听session的情况
*/
@Log4j2
@WebListener
public class SessionListener implements HttpSessionListener {
@Autowired
RedisUserUtil redisUserUtil;
@Autowired
HttpServletRequest request;
private static final Logger logger = LoggerFactory.getLogger(SessionListener.class);
@Override
public void sessionCreated(HttpSessionEvent se) {
// TODO : can move 'visit' api to here
se.getSession().setAttribute("visitDetail", new HashMap<String, Integer>());
// se.getSession().setMaxInactiveInterval(10);// 10s for debug
logger.info("新增一个Session[{}]", se.getSession().getId());
// 10s for debug
// se.getSession().setMaxInactiveInterval(10);
// log.info("新增一个Session[{}]", se.getSession().getId());
}
@SuppressWarnings("unchecked")
@@ -39,12 +37,13 @@ public class SessionListener implements HttpSessionListener {
HashMap<String, Integer> visitDetail = (HashMap<String, Integer>) se.getSession().getAttribute("visitDetail");
StringBuilder sb = new StringBuilder();
sb.append("ip => ").append(se.getSession().getAttribute("ip"));
User user = redisUserUtil.get(request);
if (visitDetail.size() == 0) {
return;
}
sb.append("\t登录情况 => ");
sb.append(user == null ? "游客访问" : user.getEmail());
visitDetail.forEach((s, integer) -> {
sb.append("\n").append("Method:[").append(s.split(":")[1]).append("]\tTimes:[").append(integer).append("]\tPath:[").append(s.split(":")[0]).append("]");
});
logger.info(sb.toString());
String email = (String) se.getSession().getAttribute("email");
sb.append(email == null ? "游客访问" : email);
visitDetail.forEach((s, integer) -> sb.append("\n").append("Method:[").append(s.split(":")[1]).append("]\tTimes:[").append(integer).append("]\tPath:[").append(s.split(":")[0]).append("]"));
log.info(sb.toString());
}
}

View File

@@ -6,9 +6,9 @@ import cn.celess.blog.entity.model.ArticleModel;
import cn.celess.blog.entity.request.ArticleReq;
import cn.celess.blog.service.ArticleService;
import cn.celess.blog.util.RedisUserUtil;
import cn.celess.blog.util.ResponseUtil;
import cn.celess.blog.util.SitemapGenerateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@@ -25,6 +25,8 @@ public class ArticleController {
SitemapGenerateUtil sitemapGenerateUtil;
@Autowired
RedisUserUtil redisUserUtil;
@Value("${spring.profiles.active}")
private String activeModel;
/**
* 新建一篇文章
@@ -35,8 +37,10 @@ public class ArticleController {
@PostMapping("/admin/article/create")
public Response create(@RequestBody ArticleReq body) {
ArticleModel articleModel = articleService.create(body);
sitemapGenerateUtil.createSitemap();
return ResponseUtil.success(articleModel);
if ("prod".equals(activeModel)) {
sitemapGenerateUtil.createSitemap();
}
return Response.success(articleModel);
}
/**
@@ -48,8 +52,10 @@ public class ArticleController {
@DeleteMapping("/admin/article/del")
public Response delete(@RequestParam("articleID") long articleId) {
boolean delete = articleService.delete(articleId);
sitemapGenerateUtil.createSitemap();
return ResponseUtil.success(delete);
if ("prod".equals(activeModel)) {
sitemapGenerateUtil.createSitemap();
}
return Response.success(delete);
}
/**
@@ -61,8 +67,10 @@ public class ArticleController {
@PutMapping("/admin/article/update")
public Response update(@RequestBody ArticleReq body) {
ArticleModel update = articleService.update(body);
sitemapGenerateUtil.createSitemap();
return ResponseUtil.success(update);
if ("prod".equals(activeModel)) {
sitemapGenerateUtil.createSitemap();
}
return Response.success(update);
}
/**
@@ -80,13 +88,13 @@ public class ArticleController {
public Response retrieveOneById(@PathVariable("articleID") long articleId,
@RequestParam(value = "update", defaultValue = "false") boolean is4update,
HttpServletRequest request) {
ArticleModel article = articleService.retrieveOneByID(articleId, is4update);
ArticleModel article = articleService.retrieveOneById(articleId, is4update);
if (article.getOpen()) {
return ResponseUtil.success(article);
} else if (article.getAuthorId().equals(redisUserUtil.get(request).getId())) {
return ResponseUtil.success(article);
return Response.success(article);
} else if (article.getAuthor().getId().equals(redisUserUtil.get().getId())) {
return Response.success(article);
}
return ResponseUtil.response(ResponseEnum.PERMISSION_ERROR, null);
return Response.response(ResponseEnum.PERMISSION_ERROR, null);
}
/**
@@ -99,7 +107,7 @@ public class ArticleController {
@GetMapping("/articles")
public Response articles(@RequestParam(name = "page", defaultValue = "1") int page,
@RequestParam(name = "count", defaultValue = "5") int count) {
return ResponseUtil.success(articleService.retrievePageForOpen(count, page));
return Response.success(articleService.retrievePageForOpen(count, page));
}
/**
@@ -111,8 +119,9 @@ public class ArticleController {
*/
@GetMapping("/admin/articles")
public Response adminArticles(@RequestParam(name = "page", defaultValue = "1") int page,
@RequestParam(name = "count", defaultValue = "10") int count) {
return ResponseUtil.success(articleService.adminArticles(count, page));
@RequestParam(name = "count", defaultValue = "10") int count,
@RequestParam(name = "deleted", required = false) Boolean deleted) {
return Response.success(articleService.adminArticles(count, page, deleted));
}
/**
@@ -127,7 +136,7 @@ public class ArticleController {
public Response findByCategory(@PathVariable("name") String name,
@RequestParam(name = "page", defaultValue = "1") int page,
@RequestParam(name = "count", defaultValue = "10") int count) {
return ResponseUtil.success(articleService.findByCategory(name, page, count));
return Response.success(articleService.findByCategory(name, page, count));
}
/**
@@ -142,13 +151,13 @@ public class ArticleController {
public Response findByTag(@PathVariable("name") String name,
@RequestParam(name = "page", defaultValue = "1") int page,
@RequestParam(name = "count", defaultValue = "10") int count) {
return ResponseUtil.success(articleService.findByTag(name, page, count));
return Response.success(articleService.findByTag(name, page, count));
}
@GetMapping("/createSitemap")
public Response createSitemap() {
sitemapGenerateUtil.createSitemap();
return ResponseUtil.success(null);
return Response.success(null);
}
}

View File

@@ -2,7 +2,6 @@ package cn.celess.blog.controller;
import cn.celess.blog.entity.Response;
import cn.celess.blog.service.CategoryService;
import cn.celess.blog.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -24,7 +23,7 @@ public class CategoryController {
*/
@PostMapping("/admin/category/create")
public Response addOne(@RequestParam("name") String name) {
return ResponseUtil.success(categoryService.create(name));
return Response.success(categoryService.create(name));
}
/**
@@ -35,7 +34,7 @@ public class CategoryController {
*/
@DeleteMapping("/admin/category/del")
public Response deleteOne(@RequestParam("id") long id) {
return ResponseUtil.success(categoryService.delete(id));
return Response.success(categoryService.delete(id));
}
/**
@@ -48,7 +47,7 @@ public class CategoryController {
@PutMapping("/admin/category/update")
public Response updateOne(@RequestParam("id") Long id,
@RequestParam("name") String name) {
return ResponseUtil.success(categoryService.update(id, name));
return Response.success(categoryService.update(id, name));
}
/**
@@ -57,7 +56,8 @@ public class CategoryController {
* @return Response
*/
@GetMapping("/categories")
public Response getPage() {
return ResponseUtil.success(categoryService.retrievePage());
public Response getPage(@RequestParam(name = "page", defaultValue = "1") int page,
@RequestParam(name = "count", defaultValue = "1000") int count) {
return Response.success(categoryService.retrievePage(page, count));
}
}

View File

@@ -1,10 +1,8 @@
package cn.celess.blog.controller;
import cn.celess.blog.entity.Comment;
import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.request.CommentReq;
import cn.celess.blog.service.CommentService;
import cn.celess.blog.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -26,76 +24,96 @@ public class CommentController {
*/
@PostMapping("/user/comment/create")
public Response addOne(@RequestBody CommentReq reqBody) {
return ResponseUtil.success(commentService.create(reqBody));
return Response.success(commentService.create(reqBody));
}
@DeleteMapping("/user/comment/del")
public Response delete(@RequestParam("id") long id) {
return ResponseUtil.success(commentService.delete(id));
return Response.success(commentService.delete(id));
}
@PutMapping("/user/comment/update")
public Response update(@RequestBody CommentReq reqBody) {
return ResponseUtil.success(commentService.update(reqBody));
return Response.success(commentService.update(reqBody));
}
/**
* 获取所有的一级评论
* 获取所有的评论
*
* @param articleId 文章id
* @param count 单页数据量
* @param page 页码
* @param pagePath pagePath
* @param count 单页数据量
* @param page 页码
* @return Response
*/
@GetMapping("/comments")
public Response commentsOfArticle(@RequestParam("articleId") long articleId,
@GetMapping("/comments/{pagePath}/{pid}")
public Response commentsOfArticle(@PathVariable("pagePath") String pagePath, @PathVariable(value = "pid") long pid,
@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
return ResponseUtil.success(commentService.retrievePageByArticle(articleId, -1, page, count));
String path = "";
if (pagePath.contains("article+")) {
path = "article/" + pagePath.split("\\+", 2)[1];
} else {
path = pagePath;
}
if ("*".equals(pagePath)) {
path = null;
}
return Response.success(commentService.retrievePageByPageAndPid(path, pid, page, count));
}
/**
* 通过pid获取数据
*
* @param pid
* @param count
* @param page
* @return
* @param pagePath pagePath
* @param count count
* @param page page
* @return Response
*/
@GetMapping("/comment/pid/{pid}")
public Response retrievePage(@PathVariable("pid") long pid,
@GetMapping("/comment/pagePath/{pagePath}")
public Response retrievePage(@PathVariable("pagePath") String pagePath,
@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
return ResponseUtil.success(commentService.retrievePageByPid(pid, page, count));
String path = "";
if (pagePath.contains("article+")) {
path = "article/" + pagePath.split("\\+", 2)[1];
} else {
path = pagePath;
}
if ("*".equals(pagePath)) {
path = null;
}
return Response.success(commentService.retrievePage(path, page, count));
}
/**
* 获取所以的一级留言
*
* @param count
* @param page
* @return
*/
@GetMapping("/leaveMsg")
public Response retrievePageOfLeaveMsg(@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
return ResponseUtil.success(commentService.retrievePageByTypeAndPid(false, -1, page, count));
@GetMapping("/user/comment/pagePath/{pagePath}")
public Response userComment(@PathVariable("pagePath") String pagePath,
@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
String path = "";
if (pagePath.contains("article+")) {
path = "article/" + pagePath.split("\\+", 2)[1];
} else {
path = pagePath;
}
if ("*".equals(pagePath)) {
path = null;
}
return Response.success(commentService.retrievePageByAuthor(path, page, count));
}
@GetMapping("/admin/comment/type/{type}")
public Response retrievePageAdmin(
@PathVariable("type") int isComment,
@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
return ResponseUtil.success(commentService.retrievePageByType(1 == isComment, page, count));
@GetMapping("/admin/comment/pagePath/{pagePath}")
public Response adminComment(@PathVariable("pagePath") String pagePath,
@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
String path = "";
if (pagePath.contains("article+")) {
path = "article/" + pagePath.split("\\+", 2)[1];
} else {
path = pagePath;
}
if ("*".equals(pagePath)) {
path = null;
}
return Response.success(commentService.retrievePageByPage(path, page, count));
}
@GetMapping("/user/comment/type/{type}")
public Response retrievePageByAuthor(
@PathVariable(value = "type") int isComment,
@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
return ResponseUtil.success(commentService.retrievePageByAuthor(1 == isComment, page, count));
}
}

View File

@@ -1,172 +1,222 @@
package cn.celess.blog.controller;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.model.QiniuResponse;
import cn.celess.blog.exception.MyException;
import cn.celess.blog.service.CountService;
import cn.celess.blog.service.QiniuService;
import cn.celess.blog.util.RedisUtil;
import cn.celess.blog.util.ResponseUtil;
import cn.celess.blog.util.VeriCodeUtil;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author : xiaohai
* @date : 2019/04/02 22:03
*/
@RestController
public class Other {
public static final Logger logger = LoggerFactory.getLogger(Object.class);
@Autowired
CountService countService;
@Autowired
QiniuService qiniuService;
@Autowired
RedisUtil redisUtil;
@Autowired
HttpServletRequest request;
@GetMapping("/counts")
public Response allCount() {
Map<String, Long> countMap = new HashMap<>();
countMap.put("articleCount", countService.getArticleCount());
countMap.put("commentCount", countService.getCommentCount());
countMap.put("leaveMsgCount", countService.getLeaveMessageCount());
countMap.put("categoryCount", countService.getCategoriesCount());
countMap.put("tagCount", countService.getTagsCount());
countMap.put("visitorCount", countService.getVisitorCount());
return ResponseUtil.success(countMap);
}
/**
* 获取header的全部参数
*
* @param request HttpServletRequest
* @return Response
*/
@GetMapping("/headerInfo")
public Response headerInfo(HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
String str = null;
while ((str = headerNames.nextElement()) != null) {
map.put(str, request.getHeader(str));
}
map.put("sessionID", request.getSession().getId());
map.put("request.getRemoteAddr()", request.getRemoteAddr());
return ResponseUtil.success(map);
}
/**
* 返回验证码
*
* @param response HttpServletResponse
* @throws IOException IOException
*/
@GetMapping(value = "/imgCode", produces = MediaType.IMAGE_PNG_VALUE)
public void getImg(HttpServletResponse response) throws IOException {
Object[] obj = VeriCodeUtil.createImage();
request.getSession().setAttribute("code", obj[0]);
//将图片输出给浏览器
BufferedImage image = (BufferedImage) obj[1];
response.setContentType("image/png");
OutputStream os = response.getOutputStream();
ImageIO.write(image, "png", os);
os.close();
}
/**
* 验证 验证码的正确性
*
* @param code 传进来的验证码
* @param request HttpServletRequest
* @return Session中写入验证状态
*/
@PostMapping("/verCode")
public Response verCode(@RequestParam("code") String code, HttpServletRequest request) {
request.getSession().setAttribute("verImgCodeStatus", false);
String codeStr = (String) request.getSession().getAttribute("code");
if (code == null) {
throw new MyException(ResponseEnum.PARAMETERS_ERROR);
}
if (codeStr == null) {
throw new MyException(ResponseEnum.IMG_CODE_TIMEOUT);
}
code = code.toLowerCase();
codeStr = codeStr.toLowerCase();
if (code.equals(codeStr)) {
request.getSession().removeAttribute("code");
request.getSession().setAttribute("verImgCodeStatus", true);
return ResponseUtil.success("验证成功");
} else {
request.getSession().removeAttribute("code");
return ResponseUtil.failure("验证失败,请重新获取验证码");
}
}
/**
* FIXME :: 单张图片多次上传的问题
* editor.md图片上传的接口
* FUCK !!!
*
* @param file 文件
* @return
* @throws IOException
*/
@PostMapping("/imgUpload")
public void upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("editormd-image-file") MultipartFile file) throws IOException {
JSONObject jsonObject = new JSONObject();
String uploadTimesStr = redisUtil.get(request.getRemoteAddr() + "-ImgUploadTimes");
int uploadTimes = 0;
if (uploadTimesStr != null) {
uploadTimes = Integer.parseInt(uploadTimesStr);
}
if (uploadTimes == 10) {
throw new MyException(ResponseEnum.FAILURE.getCode(), "上传次数已达10次请2小时后在上传");
}
request.setCharacterEncoding("utf-8");
response.setContentType("text/html");
if (file.isEmpty()) {
jsonObject.put("success", 0);
jsonObject.put("message", "上传失败,请选择文件");
response.getWriter().println(jsonObject.toString());
return;
}
String fileName = file.getOriginalFilename();
String mime = fileName.substring(fileName.lastIndexOf("."));
if (".png".equals(mime.toLowerCase()) || ".jpg".equals(mime.toLowerCase()) ||
".jpeg".equals(mime.toLowerCase()) || ".bmp".equals(mime.toLowerCase())) {
QiniuResponse qiniuResponse = qiniuService.uploadFile(file.getInputStream(), "img_" + System.currentTimeMillis() + mime);
jsonObject.put("success", 0);
jsonObject.put("message", "上传成功");
jsonObject.put("url", "http://cdn.celess.cn/" + qiniuResponse.key);
response.getWriter().println(jsonObject.toString());
redisUtil.setEx(request.getRemoteAddr() + "-ImgUploadTimes", uploadTimes + 1 + "", 2, TimeUnit.HOURS);
return;
}
jsonObject.put("success", 0);
jsonObject.put("message", "上传失败,请上传图片文件");
response.getWriter().println(jsonObject.toString());
}
}
package cn.celess.blog.controller;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.model.FileResponse;
import cn.celess.blog.exception.MyException;
import cn.celess.blog.service.CountService;
import cn.celess.blog.service.FileService;
import cn.celess.blog.util.HttpUtil;
import cn.celess.blog.util.RedisUserUtil;
import cn.celess.blog.util.RedisUtil;
import cn.celess.blog.util.VeriCodeUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author : xiaohai
* @date : 2019/04/02 22:03
*/
@RestController
public class CommonController {
public static final Logger logger = LoggerFactory.getLogger(Object.class);
@Autowired
CountService countService;
@Autowired
FileService fileService;
@Autowired
RedisUtil redisUtil;
@Autowired
RedisUserUtil redisUserUtil;
@GetMapping("/counts")
public Response allCount() {
Map<String, Long> countMap = new HashMap<>();
countMap.put("articleCount", countService.getArticleCount());
countMap.put("commentCount", countService.getCommentCount());
countMap.put("categoryCount", countService.getCategoriesCount());
countMap.put("tagCount", countService.getTagsCount());
countMap.put("visitorCount", countService.getVisitorCount());
return Response.success(countMap);
}
/**
* 获取header的全部参数
*
* @param request HttpServletRequest
* @return Response
*/
@GetMapping("/headerInfo")
public Response headerInfo(HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
String str = null;
while (headerNames.hasMoreElements()) {
str = headerNames.nextElement();
map.put(str, request.getHeader(str));
}
map.put("sessionID", request.getSession().getId());
map.put("request.getRemoteAddr()", request.getRemoteAddr());
return Response.success(map);
}
/**
* 返回验证码
*
* @param response HttpServletResponse
* @throws IOException IOException
*/
@GetMapping(value = "/imgCode", produces = MediaType.IMAGE_PNG_VALUE)
public void getImg(HttpServletRequest request, HttpServletResponse response) throws IOException {
Object[] obj = VeriCodeUtil.createImage();
request.getSession().setAttribute("code", obj[0]);
//将图片输出给浏览器
BufferedImage image = (BufferedImage) obj[1];
response.setContentType("image/png");
OutputStream os = response.getOutputStream();
ImageIO.write(image, "png", os);
os.close();
}
/**
* 验证 验证码的正确性
*
* @param code 传进来的验证码
* @param request HttpServletRequest
* @return Session中写入验证状态
*/
@PostMapping("/verCode")
public Response verCode(@RequestParam("code") String code, HttpServletRequest request) {
request.getSession().setAttribute("verImgCodeStatus", false);
String codeStr = (String) request.getSession().getAttribute("code");
if (code == null) {
throw new MyException(ResponseEnum.PARAMETERS_ERROR);
}
if (codeStr == null) {
throw new MyException(ResponseEnum.IMG_CODE_TIMEOUT);
}
code = code.toLowerCase();
codeStr = codeStr.toLowerCase();
if (code.equals(codeStr)) {
request.getSession().removeAttribute("code");
request.getSession().setAttribute("verImgCodeStatus", true);
return Response.success("验证成功");
} else {
request.getSession().removeAttribute("code");
return Response.failure("验证失败,请重新获取验证码");
}
}
/**
* FIXME :: 单张图片多次上传的问题
* editor.md图片上传的接口
* FUCK !!!
* !! 推荐使用 fileUpload(/fileUpload) 接口
* @param file 文件
*/
@Deprecated
@PostMapping("/imgUpload")
public void upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("editormd-image-file") MultipartFile file) throws IOException {
Map<String, Object> map = new HashMap<>();
ObjectMapper mapper = new ObjectMapper();
String uploadTimesStr = redisUtil.get(request.getRemoteAddr() + "-ImgUploadTimes");
int uploadTimes = 0;
if (uploadTimesStr != null) {
uploadTimes = Integer.parseInt(uploadTimesStr);
}
if (uploadTimes == 10) {
throw new MyException(ResponseEnum.FAILURE.getCode(), "上传次数已达10次请2小时后在上传");
}
request.setCharacterEncoding("utf-8");
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
if (file.isEmpty()) {
map.put("success", 0);
map.put("message", "上传失败,请选择文件");
response.getWriter().println(mapper.writeValueAsString(map));
return;
}
String fileName = file.getOriginalFilename();
assert fileName != null;
String mime = fileName.substring(fileName.lastIndexOf("."));
if (".png".equals(mime.toLowerCase()) || ".jpg".equals(mime.toLowerCase()) ||
".jpeg".equals(mime.toLowerCase()) || ".bmp".equals(mime.toLowerCase())) {
FileResponse fileResponse = fileService.getFileManager().uploadFile(file.getInputStream(), "img_" + System.currentTimeMillis() + mime);
map.put("success", 1);
map.put("message", "上传成功");
map.put("url", "http://cdn.celess.cn/" + fileResponse.key);
response.getWriter().println(mapper.writeValueAsString(map));
redisUtil.setEx(request.getRemoteAddr() + "-ImgUploadTimes", uploadTimes + 1 + "", 2, TimeUnit.HOURS);
return;
}
map.put("success", 0);
map.put("message", "上传失败,请上传图片文件");
response.getWriter().println(mapper.writeValueAsString(map));
}
@GetMapping("/bingPic")
public Response bingPic() {
ObjectMapper mapper = new ObjectMapper();
JsonNode root;
try {
root = mapper.readTree(HttpUtil.get("https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN"));
} catch (IOException e) {
return Response.failure(null);
}
JsonNode images = root.get("images").elements().next();
return Response.success("https://cn.bing.com" + images.get("url").asText());
}
@PostMapping("/fileUpload")
public Response<List<Map<String, Object>>> fileUpload(@RequestParam("file[]") MultipartFile[] files) throws IOException {
List<Map<String, Object>> result = new ArrayList<>();
String uploadTimesStr = redisUtil.get(redisUserUtil.get().getEmail() + "-fileUploadTimes");
int uploadTimes = 0;
if (uploadTimesStr != null) {
uploadTimes = Integer.parseInt(uploadTimesStr);
}
if (uploadTimes == 10) {
throw new MyException(ResponseEnum.FAILURE.getCode(), "上传次数已达10次请2小时后在上传");
}
if (files.length == 0) {
throw new MyException(ResponseEnum.NO_FILE);
}
for (MultipartFile file : files) {
Map<String, Object> resp = new HashMap<>(4);
String fileName = file.getOriginalFilename();
assert fileName != null;
String mime = fileName.substring(fileName.lastIndexOf("."));
String name = fileName.replace(mime, "").replaceAll(" ", "");
FileResponse fileResponse = fileService.getFileManager().uploadFile(file.getInputStream(), "file_" + name + '_' + System.currentTimeMillis() + mime);
resp.put("originalFilename", fileName);
resp.put("success", fileResponse != null);
if (fileResponse != null) {
resp.put("host", "http://cdn.celess.cn/");
resp.put("path", fileResponse.key);
}
result.add(resp);
}
return Response.success(result);
}
}

View File

@@ -0,0 +1,39 @@
package cn.celess.blog.controller;
import cn.celess.blog.entity.Config;
import cn.celess.blog.entity.Response;
import cn.celess.blog.mapper.ConfigMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author : xiaohai
* @date : 2020/10/16 20:56
* @desc : 配置管理接口
*/
@RestController
public class ConfigController {
@Autowired
ConfigMapper configMapper;
@GetMapping("/admin/config")
public Response<List<Config>> getConfiguration() {
return Response.success(configMapper.getConfigurations());
}
@PutMapping("/admin/config")
public Response<List<Config>> updateConfiguration(@RequestBody List<Config> configs) {
configs.forEach(config -> configMapper.updateConfiguration(config));
configs.forEach(config -> System.setProperty(config.getName(), config.getValue()));
return Response.success(configMapper.getConfigurations());
}
@PostMapping("/admin/config")
public Response<List<Config>> addConfiguration(@RequestBody List<Config> configs) {
configs.forEach(config -> configMapper.addConfiguration(config));
configs.forEach(config -> System.setProperty(config.getName(), config.getValue()));
return Response.success(configMapper.getConfigurations());
}
}

View File

@@ -0,0 +1,78 @@
package cn.celess.blog.controller;
import cn.celess.blog.BlogApplication;
import cn.celess.blog.enmu.ConfigKeyEnum;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.Config;
import cn.celess.blog.entity.InstallParam;
import cn.celess.blog.entity.Response;
import cn.celess.blog.exception.MyException;
import cn.celess.blog.mapper.ConfigMapper;
import cn.celess.blog.service.InstallService;
import cn.celess.blog.util.RegexUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
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.ResponseBody;
import javax.validation.Valid;
import java.util.Map;
/**
* @author : xiaohai
* @date : 2020/10/18 15:36
* @desc :
*/
@Slf4j
@Controller
@Validated
public class InstallController {
@Autowired
InstallService installService;
@Autowired
ConfigMapper configMapper;
@GetMapping("/is_install")
@ResponseBody
public Response<Map<String, Object>> isInstall() {
Map<String, Object> install = installService.isInstall();
return Response.success(install);
}
@PostMapping("/install")
@ResponseBody
public Response<Object> install(@Valid @RequestBody InstallParam installParam) {
if (!RegexUtil.emailMatch(installParam.getEmail())) {
throw new MyException(ResponseEnum.PARAMETERS_EMAIL_ERROR);
}
if (!RegexUtil.pwdMatch(installParam.getPassword())) {
throw new MyException(ResponseEnum.PARAMETERS_PWD_ERROR);
}
return Response.success(installService.install(installParam));
}
@GetMapping("/default_config")
@ResponseBody
public Response<String> defaultConfig() {
return null;
}
@GetMapping("/install")
public String install() {
Config configuration = configMapper.getConfiguration(ConfigKeyEnum.BLOG_INSTALLED.getKey());
if (Boolean.parseBoolean(configuration.getValue())) {
return "index.html";
}
log.info("博客第一次运行,还未安装");
return "install.html";
}
}

View File

@@ -1,24 +1,18 @@
package cn.celess.blog.controller;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq;
import cn.celess.blog.exception.MyException;
import cn.celess.blog.service.MailService;
import cn.celess.blog.service.PartnerSiteService;
import cn.celess.blog.util.RedisUtil;
import cn.celess.blog.util.RegexUtil;
import cn.celess.blog.util.ResponseUtil;
import cn.celess.blog.util.DateFormatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author : xiaohai
@@ -37,63 +31,39 @@ public class LinksController {
@PostMapping("/admin/links/create")
public Response create(@RequestBody LinkReq reqBody) {
return ResponseUtil.success(partnerSiteService.create(reqBody));
return Response.success(partnerSiteService.create(reqBody));
}
@DeleteMapping("/admin/links/del/{id}")
public Response del(@PathVariable("id") long id) {
return ResponseUtil.success(partnerSiteService.del(id));
return Response.success(partnerSiteService.del(id));
}
@PutMapping("/admin/links/update")
public Response update(@RequestBody LinkReq reqBody) {
return ResponseUtil.success(partnerSiteService.update(reqBody));
return Response.success(partnerSiteService.update(reqBody));
}
@GetMapping("/links")
public Response allForOpen() {
List<PartnerSite> sites = new ArrayList<>();
for (PartnerSite p : partnerSiteService.findAll()) {
if (p.getOpen()) {
//隐藏open字段
p.setOpen(null);
sites.add(p);
}
}
return ResponseUtil.success(sites);
List<PartnerSite> sites = partnerSiteService.findAll().stream().peek(partnerSite -> partnerSite.setOpen(null)).collect(Collectors.toList());
return Response.success(sites);
}
@GetMapping("/admin/links")
public Response all(@RequestParam("page") int page,
@RequestParam("count") int count) {
return ResponseUtil.success(partnerSiteService.PartnerSitePages(page, count));
@RequestParam("count") int count,
@RequestParam(value = "deleted", required = false) Boolean deleted) {
return Response.success(partnerSiteService.partnerSitePages(page, count, deleted));
}
@PostMapping("/apply")
public Response apply(@RequestParam("name") String name,
@RequestParam("url") String url) {
// TODO :: 弃用发送邮件的方式。
if (name == null || name.replaceAll(" ", "").isEmpty()) {
return ResponseUtil.response(ResponseEnum.PARAMETERS_ERROR, null);
}
if (!RegexUtil.urlMatch(url)) {
return ResponseUtil.response(ResponseEnum.PARAMETERS_URL_ERROR, null);
}
String applyTimeStr = redisUtil.get(request.getRemoteAddr() + "-Apply");
int applyTime = 0;
if (applyTimeStr != null) {
applyTime = Integer.parseInt(applyTimeStr);
}
if (applyTime == 10) {
throw new MyException(ResponseEnum.FAILURE.getCode(), "申请次数已达10次请2小时后重试");
}
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("友链申请:" + name);
message.setTo("a@celess.cn");
message.setText("name:" + name + "\nurl:" + url + "\n" + DateFormatUtil.getNow());
Boolean send = mailService.send(message);
redisUtil.setEx(request.getRemoteAddr() + "-Apply", applyTime + 1 + "", 2, TimeUnit.HOURS);
return send ? ResponseUtil.success("") : ResponseUtil.failure("");
public Response apply(@RequestBody() LinkApplyReq linkApplyReq) {
return Response.success(partnerSiteService.apply(linkApplyReq));
}
@PostMapping("/reapply")
public Response reapply(@RequestParam("key") String key) {
return Response.success(partnerSiteService.reapply(key));
}
}

View File

@@ -1,15 +1,15 @@
package cn.celess.blog.controller;
import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.Tag;
import cn.celess.blog.entity.model.TagModel;
import cn.celess.blog.service.TagService;
import cn.celess.blog.util.ResponseUtil;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author : xiaohai
@@ -23,48 +23,37 @@ public class TagController {
@PostMapping("/admin/tag/create")
public Response addOne(@RequestParam("name") String name) {
return ResponseUtil.success(tagService.create(name));
return Response.success(tagService.create(name));
}
@DeleteMapping("/admin/tag/del")
public Response delOne(@RequestParam("id") long id) {
return ResponseUtil.success(tagService.delete(id));
return Response.success(tagService.delete(id));
}
@PutMapping("/admin/tag/update")
public Response updateOne(@RequestParam("id") Long id, @RequestParam("name") String name) {
return ResponseUtil.success(tagService.update(id, name));
}
@GetMapping("/tag/id/{id}")
public Response retrieveOneById(@PathVariable("id") long id) {
return ResponseUtil.success(tagService.retrieveOneById(id));
}
@GetMapping("/tag/name/{name}")
public Response retrieveOneByName(@PathVariable("name") String name) {
return ResponseUtil.success(tagService.retrieveOneByName(name));
return Response.success(tagService.update(id, name));
}
@GetMapping("/tags")
public Response getPage(@RequestParam(required = false, defaultValue = "10", value = "count") int count,
@RequestParam(required = false, defaultValue = "1", value = "page") int page) {
return ResponseUtil.success(tagService.retrievePage(page, count));
return Response.success(tagService.retrievePage(page, count));
}
@GetMapping("/tags/nac")
public Response getTagNameAndCount() {
List<JSONObject> nameAndCount = new ArrayList<>();
List<Tag> all = tagService.findAll();
for (Tag t : all) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", t.getName());
String articles = t.getArticles();
jsonObject.put("size", articles == null ? 0 : articles.split(",").length);
nameAndCount.add(jsonObject);
List<Map<String, Object>> nameAndCount = new ArrayList<>();
List<TagModel> all = tagService.findAll();
for (TagModel t : all) {
Map<String, Object> map = new HashMap<>(2);
map.put("name", t.getName());
map.put("size", t.getArticles().size());
nameAndCount.add(map);
}
return ResponseUtil.success(nameAndCount);
return Response.success(nameAndCount);
}
}

View File

@@ -4,7 +4,6 @@ import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.request.LoginReq;
import cn.celess.blog.entity.request.UserReq;
import cn.celess.blog.service.UserService;
import cn.celess.blog.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -23,28 +22,28 @@ public class UserController {
@PostMapping("/login")
public Response login(@RequestBody LoginReq loginReq) {
return ResponseUtil.success(userService.login(loginReq));
return Response.success(userService.login(loginReq));
}
@PostMapping("/registration")
public Response registration(@RequestParam("email") String email,
@RequestParam("password") String password) {
return ResponseUtil.success(userService.registration(email, password));
return Response.success(userService.registration(email, password));
}
@GetMapping("/logout")
public Response logout() {
return ResponseUtil.success(userService.logout());
return Response.success(userService.logout());
}
@PutMapping("/user/userInfo/update")
public Response updateInfo(String desc, String displayName) {
return ResponseUtil.success(userService.update(desc, displayName));
return Response.success(userService.update(desc, displayName));
}
@GetMapping("/user/userInfo")
public Response getUserInfo() {
return ResponseUtil.success(userService.getUserInfoBySession());
return Response.success(userService.getUserInfoBySession());
}
/**
@@ -58,7 +57,7 @@ public class UserController {
@ResponseBody
public Response upload(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return ResponseUtil.failure("上传失败,请选择文件");
return Response.failure("上传失败,请选择文件");
}
String fileName = file.getOriginalFilename();
String mime = fileName.substring(fileName.lastIndexOf("."));
@@ -66,56 +65,64 @@ public class UserController {
".jpeg".equals(mime.toLowerCase()) || ".bmp".equals(mime.toLowerCase())) {
return (Response) userService.updateUserAavatarImg(file.getInputStream(), mime);
}
return ResponseUtil.failure("请上传图片文件");
return Response.failure("请上传图片文件");
}
@PostMapping("/sendResetPwdEmail")
public Response sendResetPwdEmail(@RequestParam("email") String email) {
return ResponseUtil.success(userService.sendResetPwdEmail(email));
return Response.success(userService.sendResetPwdEmail(email));
}
@PostMapping("/sendVerifyEmail")
public Response sendVerifyEmail(@RequestParam("email") String email) {
return ResponseUtil.success(userService.sendVerifyEmail(email));
return Response.success(userService.sendVerifyEmail(email));
}
@PostMapping("/emailVerify")
public Response emailVerify(@RequestParam("verifyId") String verifyId,
@RequestParam("email") String mail) {
return ResponseUtil.success(userService.verifyEmail(verifyId, mail));
return Response.success(userService.verifyEmail(verifyId, mail));
}
@PostMapping("/resetPwd")
public Response resetPwd(@RequestParam("verifyId") String verifyId,
@RequestParam("email") String email,
@RequestParam("pwd") String pwd) {
return ResponseUtil.success(userService.reSetPwd(verifyId, email, pwd));
return Response.success(userService.reSetPwd(verifyId, email, pwd));
}
@PostMapping("/user/setPwd")
public Response setPwd(@RequestParam("pwd") String pwd,
@RequestParam("newPwd") String newPwd,
@RequestParam("confirmPwd") String confirmPwd) {
return Response.success(userService.setPwd(pwd, newPwd, confirmPwd));
}
@DeleteMapping("/admin/user/delete")
public Response multipleDelete(@RequestBody Integer[] ids) {
return ResponseUtil.success(userService.deleteUser(ids));
return Response.success(userService.deleteUser(ids));
}
@DeleteMapping("/admin/user/delete/{id}")
public Response delete(@PathVariable("id") Integer id) {
return ResponseUtil.success(userService.deleteUser(new Integer[]{id}));
return Response.success(userService.deleteUser(new Integer[]{id}));
}
@PutMapping("/admin/user")
public Response updateInfoByAdmin(@RequestBody UserReq user) {
return ResponseUtil.success(userService.adminUpdate(user));
return Response.success(userService.adminUpdate(user));
}
@GetMapping("/admin/users")
public Response getAllUser(@RequestParam("page") int pageNum, @RequestParam("count") int count) {
return ResponseUtil.success(userService.getUserList(pageNum, count));
public Response getAllUser(@RequestParam("page") int pageNum, @RequestParam("count") int count, @RequestParam(name = "status", required = false) Integer status) {
return Response.success(userService.getUserList(pageNum, count, status));
}
@GetMapping("/emailStatus/{email}")
public Response getEmailStatus(@PathVariable("email") String email) {
return ResponseUtil.success(userService.getStatusOfEmail(email));
return Response.success(userService.getStatusOfEmail(email));
}

View File

@@ -3,7 +3,6 @@ package cn.celess.blog.controller;
import cn.celess.blog.entity.Response;
import cn.celess.blog.service.CountService;
import cn.celess.blog.service.VisitorService;
import cn.celess.blog.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -22,29 +21,29 @@ public class VisitorController {
@GetMapping("/visitor/count")
public Response getVisitorCount() {
return ResponseUtil.success(countService.getVisitorCount());
return Response.success(countService.getVisitorCount());
}
@GetMapping("/admin/visitor/page")
public Response page(@RequestParam(value = "count", required = false, defaultValue = "10") int count,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "showLocation", required = false, defaultValue = "false") boolean showLocation) {
return ResponseUtil.success(visitorService.visitorPage(page, count, showLocation));
@RequestParam(value = "showLocation", required = false, defaultValue = "true") boolean showLocation) {
return Response.success(visitorService.visitorPage(page, count, showLocation));
}
@PostMapping("/visit")
public Response add(HttpServletRequest request) {
return ResponseUtil.success(visitorService.addVisitor(request));
return Response.success(visitorService.addVisitor(request));
}
@GetMapping("/dayVisitCount")
public Response dayVisitCount() {
return ResponseUtil.success(countService.getDayVisitCount());
return Response.success(countService.getDayVisitCount());
}
@GetMapping("/ip/{ip}")
public Response ipLocation(@PathVariable("ip") String ip) {
return ResponseUtil.success(visitorService.location(ip));
return Response.success(visitorService.location(ip));
}
/**
@@ -55,6 +54,6 @@ public class VisitorController {
*/
@GetMapping("/ip")
public Response getIp(HttpServletRequest request) {
return ResponseUtil.success(request.getRemoteAddr());
return Response.success(request.getRemoteAddr());
}
}

View File

@@ -2,7 +2,6 @@ package cn.celess.blog.controller;
import cn.celess.blog.entity.Response;
import cn.celess.blog.service.WebUpdateInfoService;
import cn.celess.blog.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -17,31 +16,32 @@ public class WebUpdateInfoController {
@PostMapping("/admin/webUpdate/create")
public Response create(@RequestParam("info") String info) {
return ResponseUtil.success(webUpdateInfoService.create(info));
return Response.success(webUpdateInfoService.create(info));
}
@DeleteMapping("/admin/webUpdate/del/{id}")
public Response del(@PathVariable("id") long id) {
return ResponseUtil.success(webUpdateInfoService.del(id));
return Response.success(webUpdateInfoService.del(id));
}
@PutMapping("/admin/webUpdate/update")
public Response update(@RequestParam("id") long id, @RequestParam("info") String info) {
return ResponseUtil.success(webUpdateInfoService.update(id, info));
return Response.success(webUpdateInfoService.update(id, info));
}
@GetMapping("/webUpdate")
public Response findAll() {
return ResponseUtil.success(webUpdateInfoService.findAll());
return Response.success(webUpdateInfoService.findAll());
}
@GetMapping("/webUpdate/pages")
public Response page(@RequestParam("page") int page, @RequestParam("count") int count) {
return ResponseUtil.success(webUpdateInfoService.pages(count, page));
return Response.success(webUpdateInfoService.pages(count, page));
}
@GetMapping("/lastestUpdateTime")
@GetMapping("/lastestUpdate")
public Response lastestUpdateTime() {
return ResponseUtil.success(webUpdateInfoService.getLastestUpdateTime());
return Response.success(webUpdateInfoService.getLastestUpdateTime());
}

View File

@@ -0,0 +1,23 @@
package cn.celess.blog.enmu;
import lombok.Getter;
/**
* @Author: 小海
* @Date: 2020-05-25 08:58
* @Desc:
*/
@Getter
public enum CommentStatusEnum {
// 正常
NORMAL(0, "正常"),
DELETED(3, "已删除");
private final int code;
private final String msg;
CommentStatusEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,37 @@
package cn.celess.blog.enmu;
/**
* @author : xiaohai
* @date : 2020/10/16 16:41
* @desc :
*/
public enum ConfigKeyEnum {
/**
* 枚举
*/
FILE_TYPE("file.type"),
FILE_QINIU_ACCESS_KEY("file.qiniu.accessKey"),
FILE_QINIU_SECRET_KEY("file.qiniu.secretKey"),
FILE_QINIU_BUCKET("file.qiniu.bucket"),
FILE_LOCAL_DIRECTORY_PATH("file.local.directoryPath"),
BLOG_FILE_PATH("blog.file.path"),
BLOG_INSTALLED("blog.installed"),
DB_TYPE("db.type"),
DB_URL("spring.datasource.url"),
DB_USERNAME("spring.datasource.username"),
DB_PASSWORD("spring.datasource.password"),
DB_DRIVER_CLASS_NAME("spring.datasource.driver-class-name"),
BLOG_DB_PATH("blog.db.path");
private final String key;
ConfigKeyEnum(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}

View File

@@ -1,27 +0,0 @@
package cn.celess.blog.enmu;
import lombok.Getter;
/**
* @Author: 小海
* @Date 2019/06/29 00:00
* @Description 文章数据模型转换的级别(响应参数的选择)
*/
@Getter
public enum LevelEnum {
//低级
LOW(0),
//中级
MIDDLE(1),
//另一个级别的转化
BETWEEN_M_AND_H(2),
//高级
HEIGHT(3);
private int levelCode;
LevelEnum(int levelCode) {
this.levelCode = levelCode;
}
}

View File

@@ -11,59 +11,74 @@ public enum ResponseEnum {
FAILURE(-1, "失败"),
ERROR(-2, "错误"),
DATA_IS_DELETED(1000, "数据已被删除"),
//文章类
ARTICLE_NOT_EXIST(201, "文章不存在"),
ARTICLE_HAS_EXIST(202, "文章已存在"),
ARTICLE_NOT_PUBLIC(203, "文章暂未公开"),
ARTICLE_NOT_BELONG_YOU(204, "无权限操作别人的文章"),
ARTICLE_NOT_EXIST(2010, "文章不存在"),
ARTICLE_HAS_EXIST(2020, "文章已存在"),
ARTICLE_NOT_PUBLIC(2030, "文章暂未公开"),
ARTICLE_NOT_BELONG_YOU(2040, "无权限操作别人的文章"),
//用户类
HAVE_NOT_LOG_IN(301, "还未登录"),
PERMISSION_ERROR(302, "没有此权限"),
USER_NOT_EXIST(303, "用户不存在"),
USERNAME_HAS_EXIST(304, "用户名已存在"),
USERNAME_TOO_SHORT(305, "用户名太短"),
PASSWORD_TOO_SHORT_OR_LONG(306, "密码长度过长或者过短"),
LOGIN_FAILURE(310, "登录失败,用户名/密码不正确"),
USEREMAIL_NULL(331, "未设置邮箱"),
USEREMAIL_NOT_VERIFY(332, "邮箱未验证"),
LOGIN_LATER(350, "错误次数已达5次请稍后再试"),
PWD_SAME(360, "新密码与原密码相同"),
LOGIN_EXPIRED(370, "登陆过期"),
HAVE_NOT_LOG_IN(3010, "还未登录"),
PERMISSION_ERROR(3020, "没有此权限"),
USER_NOT_EXIST(3030, "用户不存在"),
USERNAME_HAS_EXIST(3040, "用户名已存在"),
USERNAME_TOO_SHORT(3050, "用户名太短"),
PASSWORD_TOO_SHORT_OR_LONG(3060, "密码长度过长或者过短"),
LOGIN_FAILURE(3100, "登录失败,用户名/密码不正确"),
USEREMAIL_NULL(3310, "未设置邮箱"),
USEREMAIL_NOT_VERIFY(3320, "邮箱未验证"),
LOGIN_LATER(3500, "错误次数已达5次请稍后再试"),
PWD_SAME(3601, "新密码与原密码相同"),
PWD_NOT_SAME(3602, "新密码与原密码不相同"),
LOGIN_EXPIRED(3700, "登陆过期"),
LOGOUT(3710, "账户已注销"),
CAN_NOT_USE(3711, "账户不可用"),
PWD_WRONG(3800, "密码不正确"),
JWT_EXPIRED(3810, "Token过期"),
JWT_MALFORMED(3820, "Token格式不对"),
JWT_SIGNATURE(3830, "Token签名错误"),
JWT_NOT_SUPPORT(3840, "不支持的Token"),
//标签
TAG_NOT_EXIST(401, "标签不存在"),
TAG_HAS_EXIST(402, "标签已存在"),
TAG_NOT_EXIST(4010, "标签不存在"),
TAG_HAS_EXIST(4020, "标签已存在"),
//分类
CATEGORY_NOT_EXIST(501, "分类不存在"),
CATEGORY_HAS_EXIST(502, "分类已存在"),
CATEGORY_NOT_EXIST(5010, "分类不存在"),
CATEGORY_HAS_EXIST(5020, "分类已存在"),
//评论/留言
COMMENT_NOT_EXIST(601, "评论/留言不存在"),
COMMENT_HAS_EXIST(602, "评论/留言已存在,请不要重复提交"),
COMMENT_NOT_EXIST(6010, "评论/留言不存在"),
COMMENT_HAS_EXIST(6020, "评论/留言已存在,请不要重复提交"),
//webUdpateInfo amd PartnerSite
DATA_NOT_EXIST(701, "数据不存在"),
DATA_HAS_EXIST(702, "数据已存在"),
DATA_NOT_EXIST(7010, "数据不存在"),
DATA_HAS_EXIST(7020, "数据已存在"),
//其他
APPLY_LINK_NO_ADD_THIS_SITE(7200, "暂未在您的网站中抓取到本站链接"),
DATA_EXPIRED(7300, "数据过期"),
CANNOT_GET_DATA(7400, "暂无法获取到数据"),
NO_FILE(7500, "未选择文件,请重新选择"),
//提交更新之前,没有获取数据/,
DID_NOT_GET_THE_DATA(802, "非法访问"),
IMG_CODE_TIMEOUT(810, "验证码已失效"),
IMG_CODE_DIDNOTVERIFY(820, "请先验证验证码"),
VERIFY_ERROR(830, "验证失败"),
PARAMETERS_ERROR(850, "参数错误"),
PARAMETERS_URL_ERROR(851, "链接格式错误"),
PARAMETERS_EMAIL_ERROR(852, "邮箱格式错误"),
PARAMETERS_PHONE_ERROR(853, "手机格式错误"),
PARAMETERS_QQ_ERROR(854, "QQ格式错误"),
PARAMETERS_PWD_ERROR(855, "密码格式错误"),
VERIFY_OUT(840, "已经验证过了");
private int code;
private String msg;
DID_NOT_GET_THE_DATA(8020, "非法访问"),
IMG_CODE_TIMEOUT(8100, "验证码已失效"),
IMG_CODE_DIDNOTVERIFY(8200, "请先验证验证码"),
VERIFY_ERROR(8300, "验证失败"),
PARAMETERS_ERROR(8500, "参数错误"),
PARAMETERS_URL_ERROR(8510, "链接格式错误"),
PARAMETERS_EMAIL_ERROR(8520, "邮箱格式错误"),
PARAMETERS_PHONE_ERROR(8530, "手机格式错误"),
PARAMETERS_QQ_ERROR(8540, "QQ格式错误"),
PARAMETERS_PWD_ERROR(8550, "密码格式错误"),
VERIFY_OUT(8400, "已经验证过了");
private final int code;
private final String msg;
ResponseEnum(int code, String msg) {

View File

@@ -0,0 +1,23 @@
package cn.celess.blog.enmu;
import lombok.Getter;
/**
* @Author: 小海
* @Date: 2020-05-24 16:31
* @Desc:
*/
@Getter
public enum RoleEnum {
// admin 权限
ADMIN_ROLE("admin"),
// user 权限
USER_ROLE("user");
private final String roleName;
RoleEnum(String roleName) {
this.roleName = roleName;
}
}

View File

@@ -0,0 +1,72 @@
package cn.celess.blog.enmu;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: 小海
* @Date: 2020-05-22 21:32
* @Desc:
*/
public enum UserAccountStatusEnum {
/**
* 账户正常
*/
NORMAL(0, "正常"),
/**
* 账户被锁定
*/
LOCKED(1, "锁定"),
/**
* 账户被删除
*/
DELETED(2, "已删除");
private final int code;
private final String desc;
UserAccountStatusEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
public static UserAccountStatusEnum get(int code) {
for (UserAccountStatusEnum value : UserAccountStatusEnum.values()) {
if (value.code == code) {
return value;
}
}
return null;
}
@JsonCreator
public static UserAccountStatusEnum get(Map<String, Object> map) {
for (UserAccountStatusEnum value : UserAccountStatusEnum.values()) {
if (value.code == (int) map.get("code") && value.desc.equals(map.get("desc"))) {
return value;
}
}
return null;
}
@JsonValue
public Map<String, Object> toJson() {
Map<String, Object> map = new HashMap<>(2);
map.put("code", code);
map.put("desc", desc);
return map;
}
}

View File

@@ -3,6 +3,7 @@ package cn.celess.blog.entity;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* @author : xiaohai
@@ -41,16 +42,6 @@ public class Article {
private Date updateDate = null;
private Long categoryId;
private String tagsId;
private Long authorId;
private Long preArticleId;
private Long nextArticleId;
private Long readingNumber;
/**
@@ -58,4 +49,15 @@ public class Article {
*/
private Boolean open;
private Category category;
private List<Tag> tags;
private Integer likeCount;
private Integer dislikeCount;
private User user;
private boolean deleted = false;
}

View File

@@ -0,0 +1,26 @@
package cn.celess.blog.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: 小海
* @Date: 2020-05-24 14:52
* @Desc:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleTag {
private Long id;
private Article article;
private TagCategory tag;
public ArticleTag(Article article, TagCategory tag) {
this.article = article;
this.tag = tag;
}
}

View File

@@ -1,20 +1,14 @@
package cn.celess.blog.entity;
import lombok.Data;
/**
* @author : xiaohai
* @date : 2019/03/28 22:18
*/
@Data
public class Category {
private Long id;
private String name;
private String articles;
}
package cn.celess.blog.entity;
import lombok.NoArgsConstructor;
/**
* @author : xiaohai
* @date : 2019/03/28 22:18
*/
@NoArgsConstructor
public class Category extends TagCategory {
public Category(String name) {
super.setName(name);
}
}

View File

@@ -14,27 +14,21 @@ public class Comment {
private Long id;
/**
* 是评论还是留言 0:评论 其他1留言
*/
private Boolean type;
private int status;
private Long authorID;
private String pagePath;
private String content;
private Long articleID;
private Date date;
/**
* 回应着ID 默认为顶级回复
*/
private String responseId = "";
private User fromUser;
private User toUser;
/**
* 评论的父ID
*/
private Long pid;
// private boolean delete;
}

View File

@@ -0,0 +1,26 @@
package cn.celess.blog.entity;
import cn.celess.blog.enmu.ConfigKeyEnum;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author : xiaohai
* @date : 2020/10/16 15:24
* @desc :
*/
@Data
@NoArgsConstructor
public class Config {
private Integer id;
private String name;
private String value;
public Config(String name) {
this.name = name;
}
public Config(ConfigKeyEnum e) {
this.name = e.getKey();
}
}

View File

@@ -0,0 +1,38 @@
package cn.celess.blog.entity;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author : xiaohai
* @date : 2020/10/18 14:52
* @desc :
*/
@Data
public class InstallParam {
@NotBlank(message = "数据库类型不可为空")
private String dbType;
@NotBlank(message = "数据库主机不可为空")
private String dbHost;
@NotBlank(message = "数据库名称不可为空")
private String dbName;
@NotBlank(message = "数据库用户名不可为空")
private String dbUsername;
@NotBlank(message = "数据库密码不可为空")
private String dbPassword;
/**
* user 相关
*/
@NotBlank(message = "用户邮箱地址不可为空")
private String email;
@NotBlank(message = "用户密码不可为空")
private String password;
}

View File

@@ -19,6 +19,16 @@ public class PartnerSite {
private Boolean open;
private String iconPath;
private String desc;
private Boolean delete = false;
private String email;
private Boolean notification = true;
public PartnerSite() {
}

View File

@@ -1,7 +1,9 @@
package cn.celess.blog.entity;
import cn.celess.blog.enmu.ResponseEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import net.sf.json.JSONObject;
import lombok.SneakyThrows;
import java.io.Serializable;
@@ -10,25 +12,54 @@ import java.io.Serializable;
* @date : 2019/03/28 15:24
*/
@Data
public class Response implements Serializable {
public class Response<T> implements Serializable {
private int code;
private String msg;
private Object result;
private long date;
private T result;
public Response() {
}
public Response(int code, String msg, Object result, long date) {
public Response(int code, String msg, T result) {
this.code = code;
this.msg = msg;
this.result = result;
this.date = date;
}
/**
* 成功相应
*
* @param result 结果
* @return Response
*/
public static <T> Response<T> success(T result) {
return new Response<T>(ResponseEnum.SUCCESS.getCode(), ResponseEnum.SUCCESS.getMsg(), result);
}
/**
* 失败的响应
*
* @param result 结果
* @return Response
*/
public static Response<String> failure(String result) {
return new Response<String>(ResponseEnum.FAILURE.getCode(), ResponseEnum.FAILURE.getMsg(), result);
}
/**
* 其他的响应
*
* @param r 枚举常量
* @param result 结果
* @return Response
*/
public static <T> Response<T> response(ResponseEnum r, T result) {
return new Response<T>(r.getCode(), r.getMsg(), result);
}
@SneakyThrows
@Override
public String toString() {
JSONObject jsonObject = JSONObject.fromObject(this);
return jsonObject.toString();
return new ObjectMapper().writeValueAsString(this);
}
}

View File

@@ -1,16 +1,15 @@
package cn.celess.blog.entity;
import lombok.Data;
/**
* @author : xiaohai
* @date : 2019/03/28 22:19
*/
@Data
public class Tag {
private Long id;
private String name;
private String articles;
}
package cn.celess.blog.entity;
import lombok.NoArgsConstructor;
/**
* @author : xiaohai
* @date : 2019/03/28 22:19
*/
@NoArgsConstructor
public class Tag extends TagCategory {
public Tag(String name) {
super.setName(name);
}
}

View File

@@ -0,0 +1,19 @@
package cn.celess.blog.entity;
import lombok.Data;
/**
* @Author: 小海
* @Date: 2020-05-24 14:03
* @Desc:
*/
@Data
public class TagCategory {
private Long id;
private String name;
private Boolean category = true;
private Boolean deleted = false;
}

View File

@@ -2,6 +2,7 @@ package cn.celess.blog.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@@ -10,6 +11,7 @@ import java.util.Date;
* @date : 2019/03/28 14:52
*/
@Data
@NoArgsConstructor
public class User {
private Long id;
@@ -18,12 +20,6 @@ public class User {
*/
private String email;
/**
* 用户唯一标识码
*/
@JsonIgnore
private String uid;
/**
* 密码
*/
@@ -46,15 +42,12 @@ public class User {
private Date recentlyLandedDate;
/**
* 随机码 用户验证邮箱/找回密码
* 暂时废弃这一字段
*/
private String emailVerifyId;
private String role = "user";
public User() {
}
private int status;
public User(String email, String pwd) {
this.email = email;
this.pwd = pwd;
}
}

View File

@@ -15,6 +15,7 @@ public class Visitor {
private String ip;
private Date date;
private String ua;
private boolean delete;
public Visitor(String ip, Date date, String ua) {
this.ip = ip;

View File

@@ -17,11 +17,12 @@ public class WebUpdate {
private Date updateTime;
private boolean delete;
public WebUpdate() {
}
public WebUpdate(String updateInfo, Date updateTime) {
public WebUpdate(String updateInfo) {
this.updateInfo = updateInfo;
this.updateTime = updateTime;
}
}

View File

@@ -1,9 +1,10 @@
package cn.celess.blog.entity.model;
import cn.celess.blog.entity.Tag;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
/**
* @author : xiaohai
@@ -57,40 +58,30 @@ public class ArticleModel {
/**
* 标签
*/
private String[] tags;
private List<Tag> tags;
/**
* 作者
*/
private Long authorId;
private UserModel author;
/**
* 作者名字
*/
private String authorName;
private ArticleModel preArticle;
/**
* 上一篇文章
*/
private Long preArticleId;
/**
* 下一篇文章
*/
private Long nextArticleId;
private String preArticleTitle;
private String nextArticleTitle;
private ArticleModel nextArticle;
/**
* 阅读数
*/
private Long readingNumber;
private Integer likeCount;
private Integer dislikeCount;
/**
* 文章的状态 true公开 false:不公开
*/
private Boolean open;
private boolean deleted;
}

View File

@@ -0,0 +1,24 @@
package cn.celess.blog.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @Author: 小海
* @Date: 2020-03-29 12:18
* @Desc:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CategoryModel {
private Long id;
private String name;
private List<ArticleModel> articles;
private boolean deleted;
}

View File

@@ -3,7 +3,7 @@ package cn.celess.blog.entity.model;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.List;
/**
* @author : xiaohai
@@ -14,44 +14,31 @@ import java.util.Date;
public class CommentModel {
private long id;
/**
* 是评论还是留言 0:评论 其他1留言
*/
private boolean isComment;
private UserModel fromUser;
private String authorName;
private String authorAvatarImgUrl;
private UserModel toUser;
/**
* 内容
*/
private String content;
/**
* 文章ID
*/
private long articleID;
/**
* 文章标题
*/
private String articleTitle;
private String pagePath;
/**
* 发布日期
*/
private String date;
/**
* 回应着ID 默认为顶级回复
*/
private String responseId = "";
/**
* 评论的父ID
*/
private long pid = -1;
private Long pid;
private List<CommentModel> respComment;
private int status;
}

View File

@@ -0,0 +1,25 @@
package cn.celess.blog.entity.model;
/**
* @author : xiaohai
* @date : 2020/10/15 22:16
* @desc :
*/
public class FileInfo {
/**
* 文件名
*/
public String key;
/**
* 文件hash值
*/
public String hash;
/**
* 文件大小,单位:字节
*/
public long size;
/**
* 文件上传时间单位为100纳秒
*/
public long uploadTime;
}

View File

@@ -1,13 +1,13 @@
package cn.celess.blog.entity.model;
/**
* @author : xiaohai
* @date : 2019/04/21 22:43
*/
public class QiniuResponse {
public String key;
public String hash;
public String bucket;
public long fsize;
}
package cn.celess.blog.entity.model;
/**
* @author : xiaohai
* @date : 2019/04/21 22:43
*/
public class FileResponse {
public String key;
public String hash;
public String type;
public long size;
}

View File

@@ -0,0 +1,38 @@
package cn.celess.blog.entity.model;
import com.github.pagehelper.PageInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @Author: 小海
* @Date: 2020-05-25 17:13
* @Desc:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageData<T> {
private List<T> list;
private long total;
private int pageSize;
private int pageNum;
public PageData(PageInfo pageInfo) {
this.pageNum = pageInfo.getPageNum();
this.pageSize = pageInfo.getPageSize();
this.total = pageInfo.getTotal();
}
public PageData(PageInfo pageInfo, List<T> data) {
this(pageInfo);
this.list = data;
}
}

View File

@@ -0,0 +1,25 @@
package cn.celess.blog.entity.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @Author: 小海
* @Date: 2020-03-29 13:56
* @Desc:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TagModel {
private Long id;
private String name;
private List<ArticleModel> articles;
private boolean deleted;
}

View File

@@ -1,5 +1,6 @@
package cn.celess.blog.entity.model;
import cn.celess.blog.enmu.UserAccountStatusEnum;
import lombok.Getter;
import lombok.Setter;
@@ -37,4 +38,6 @@ public class UserModel {
private String role = "user";
private String token;
private UserAccountStatusEnum status;
}

View File

@@ -21,4 +21,6 @@ public class WebUpdateModel {
this.info = info;
this.time = time;
}
private boolean deleted;
}

View File

@@ -11,7 +11,7 @@ public class ArticleReq {
private Long id;
private String title;
private String mdContent;
private String tags;
private String[] tags;
private Boolean type;
private String url;
private String category;

View File

@@ -9,9 +9,8 @@ import lombok.Data;
@Data
public class CommentReq {
private Long id;
private Boolean comment;
private String content;
private Long pid;
private Long articleID;
private String responseId;
private long pid = -1;
private String pagePath;
private long toUserId = -1;
}

View File

@@ -0,0 +1,17 @@
package cn.celess.blog.entity.request;
import lombok.Data;
/**
* @author : xiaohai
* @date : 2020/07/31 20:50
*/
@Data
public class LinkApplyReq {
private String name;
private String email;
private String url;
private String linkUrl;
private String desc;
private String iconPath;
}

View File

@@ -11,5 +11,7 @@ public class LinkReq {
private long id;
private String name;
private String url;
private String iconPath;
private String desc;
private boolean open;
}

View File

@@ -1,12 +1,16 @@
package cn.celess.blog.entity.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author : xiaohai
* @date : 2019/06/01 22:47
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginReq {
private String email;
private String password;

View File

@@ -10,7 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -18,6 +20,10 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Set;
/**
* @author : xiaohai
@@ -26,12 +32,11 @@ import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
public class ExceptionHandle {
public static final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
@Autowired
MailService mailService;
@Autowired
HttpServletRequest request;
public static final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
@Value("${spring.profiles.active}")
private String activeModel;
@@ -40,28 +45,34 @@ public class ExceptionHandle {
public Response handle(Exception e) {
//自定义错误
if (e instanceof MyException) {
logger.debug("返回了自定义的exception,[code={},msg={}]", ((MyException) e).getCode(), e.getMessage());
return new Response(((MyException) e).getCode(), e.getMessage(), null, System.currentTimeMillis());
MyException exception = (MyException) e;
logger.debug("返回了自定义的exception,[code={},msg={},result={}]", exception.getCode(), e.getMessage(), exception.getResult());
return new Response<>(exception.getCode(), e.getMessage(), exception.getResult());
}
//请求路径不支持该方法
if (e instanceof HttpRequestMethodNotSupportedException) {
logger.debug("遇到请求路径与请求方法不匹配的请求,[msg={}path:{},method:{}]", e.getMessage(),request.getRequestURL(),request.getMethod());
return new Response(ResponseEnum.ERROR.getCode(), e.getMessage(), null, System.currentTimeMillis());
logger.debug("遇到请求路径与请求方法不匹配的请求,[msg={}path:{},method:{}]", e.getMessage(), request.getRequestURL(), request.getMethod());
return new Response<>(ResponseEnum.ERROR.getCode(), e.getMessage(), null);
}
//数据输入类型不匹配
if (e instanceof MethodArgumentTypeMismatchException) {
logger.debug("输入类型不匹配,[msg={}]", e.getMessage());
return new Response(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改后再访问", null, System.currentTimeMillis());
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改后再访问", null);
}
//数据验证失败
if (e instanceof BindException) {
logger.debug("数据验证失败,[msg={}]", e.getMessage());
return new Response(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改", null, System.currentTimeMillis());
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改", null);
}
//数据输入不完整
if (e instanceof MissingServletRequestParameterException) {
logger.debug("数据输入不完整,[msg={}]", e.getMessage());
return new Response(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入不完整,请检查", null, System.currentTimeMillis());
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入不完整,请检查", null);
}
if (e instanceof MethodArgumentNotValidException) {
logger.debug("数据验证失败,[msg: {}]", e.getMessage());
BindingResult violations = ((MethodArgumentNotValidException) e).getBindingResult();
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), violations.getAllErrors().get(0).getDefaultMessage(), null);
}
// 发送错误信息到邮箱
@@ -70,7 +81,7 @@ public class ExceptionHandle {
sendMessage(e);
}
e.printStackTrace();
return new Response(ResponseEnum.ERROR.getCode(), "服务器出现错误,已记录", null, System.currentTimeMillis());
return new Response<>(ResponseEnum.ERROR.getCode(), "服务器出现错误,已记录", null);
}
/**
@@ -83,7 +94,12 @@ public class ExceptionHandle {
simpleMailMessage.setTo("a@celess.cn");
simpleMailMessage.setSubject("服务器出现了错误");
StringBuilder msg = new StringBuilder();
msg.append("requirePath:\n").append(request.getRequestURL().toString()).append("?").append(request.getQueryString()).append("\n\n\n");
String queryString = request.getQueryString();
msg.append("requirePath:\n").append(request.getRequestURL().toString());
if (queryString != null) {
msg.append("?").append(queryString);
}
msg.append("\n\n\n");
msg.append("msg:\n").append(e.getMessage()).append("\n\n\n");
msg.append("date:\n").append(DateFormatUtil.getNow()).append("\n\n\n");
msg.append("from:\n").append(request.getHeader("User-Agent")).append("\n\n\n");

View File

@@ -1,13 +1,16 @@
package cn.celess.blog.exception;
import cn.celess.blog.enmu.ResponseEnum;
import lombok.Data;
/**
* @author : xiaohai
* @date : 2019/03/28 16:56
*/
@Data
public class MyException extends RuntimeException {
private int code;
private Object result;
public MyException(int code, String msg) {
super(msg);
@@ -19,16 +22,20 @@ public class MyException extends RuntimeException {
this.code = e.getCode();
}
public MyException(ResponseEnum e, Object result) {
super(e.getMsg());
this.code = e.getCode();
this.result = result;
}
public MyException(ResponseEnum e, String msg) {
super(msg + e.getMsg());
this.code = e.getCode();
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
public MyException(ResponseEnum e, String msg, Object result) {
super(e.getMsg());
this.code = e.getCode();
this.result = result;
}
}

View File

@@ -1,7 +1,7 @@
package cn.celess.blog.mapper;
import cn.celess.blog.entity.Article;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@@ -21,21 +21,15 @@ public interface ArticleMapper {
int update(Article a);
int updateNextArticleId(long targetArticleID, long nextArticleID);
int updatePreArticleId(long targetArticleID, long preArticleID);
long getLastestArticleId();
Article getLastestArticle();
Article findArticleById(long id);
boolean existsByTitle(String title);
boolean existsById(long id);
boolean isDeletedById(long id);
List<Article> findAllByAuthorId(long authorID);
List<Article> findAllByAuthorId(long authorId);
List<Article> findAllByOpen(boolean isOpen);
@@ -43,15 +37,15 @@ public interface ArticleMapper {
List<Article> findAllByCategoryId(long id);
List<Article> findAllByCategoryIdAndOpen(long id);
List<Article> findAll();
Article getSimpleInfo(long id);
Article getPreArticle(Long id);
List<Article> getSimpleInfoByCategory(long categoryId);
Article getNextArticle(Long id);
List<Article> getSimpleInfoByTag(List<String> idList);
int setReadingNumber(long number, long id);
int updateReadingNumber(long id);
long count();

View File

@@ -0,0 +1,35 @@
package cn.celess.blog.mapper;
import cn.celess.blog.entity.ArticleTag;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @Author: 小海
* @Date: 2020-05-24 14:21
* @Desc:
*/
@Mapper
@Repository
public interface ArticleTagMapper {
int insert(ArticleTag articleTag);
int update(ArticleTag articleTag);
ArticleTag findOneById(Long id);
int deleteById(Long id);
int deleteByArticleId(Long articleId);
List<ArticleTag> findAllByArticleId(Long articleId);
int deleteMultiById(List<ArticleTag> articleTags);
List<ArticleTag> findArticleByTag(Long tagId);
List<ArticleTag> findArticleByTagAndOpen(Long tagId);
}

View File

@@ -34,7 +34,7 @@ public interface CategoryMapper {
String getNameById(long id);
Long getIDByName(String name);
Long getIdByName(String name);
Category getLastestCategory();

View File

@@ -8,8 +8,8 @@ import java.util.List;
/**
* @Author: 小海
* @Date 2019/06/30 16:19
* @Description
* @Date: 2019/06/30 16:19
* @Description:
*/
@Mapper
@Repository
@@ -18,11 +18,9 @@ public interface CommentMapper {
int updateContent(String content, long id);
int updateResponder(String responder, long id);
int delete(long id);
int deleteByArticleId(long articleId);
int deleteByPagePath(String pagePath);
boolean existsById(long id);
@@ -30,19 +28,17 @@ public interface CommentMapper {
Comment getLastestComment();
List<Comment> findAllByAuthorIDAndType(long id, boolean isComment);
List<Comment> findAllByFromUser(long id);
List<Comment> findAllByPId(long pid);
List<Comment> findAllByPid(long pid);
List<Comment> findAllByArticleID(long articleId);
List<Comment> findAllByPagePath(String pagePath);
List<Comment> findAllByArticleIDAndPId(long articleID, long pid);
List<Comment> findAllByPagePathAndFromUser(String pagePath, long userId);
List<Comment> findCommentsByTypeAndPId(boolean isComment, long pid);
List<Comment> findAllByPagePathAndPidAndNormal(String pagePath, long pid);
List<Comment> findAllByPId(int pid);
long countByPagePath(String pagePath);
List<Comment> findAllByType(boolean isComment);
long countByType(boolean isComment);
long count();
}

View File

@@ -0,0 +1,55 @@
package cn.celess.blog.mapper;
import cn.celess.blog.entity.Config;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author : xiaohai
* @date : 2020/10/16 15:24
* @desc :
*/
@Mapper
@Repository
public interface ConfigMapper {
/**
* 获取单个配置
*
* @param key 配置名
* @return 配置
*/
Config getConfiguration(String key);
/**
* 更新配置
*
* @param c 配置
* @return 改变数据行数
*/
int updateConfiguration(Config c);
/**
* 获取所有配置
*
* @return 所有配置
*/
List<Config> getConfigurations();
/**
* 新增配置
*
* @param c 配置
* @return 改变行数
*/
int addConfiguration(Config c);
/**
* 删除配置
*
* @param id 主键id
* @return 改变行数
*/
int deleteConfiguration(int id);
}

View File

@@ -36,5 +36,6 @@ public interface PartnerMapper {
List<PartnerSite> findAll();
List<PartnerSite> findAll(Boolean deleted);
}

View File

@@ -26,10 +26,6 @@ public interface TagMapper {
Boolean existsByName(String name);
Long getIDByName(String name);
String getNameById(long id);
Tag getLastestTag();
List<Tag> findAll();

View File

@@ -4,7 +4,6 @@ import cn.celess.blog.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/**
@@ -16,13 +15,13 @@ import java.util.List;
@Repository
public interface UserMapper {
int addUser(String email, String pwd);
int addUser(User user);
int updateInfo(String desc, String displayName, long id);
int updateAvatarImgUrl(String avatarImgUrl, long id);
int updateLoginTime(String email, Date date);
int updateLoginTime(String email);
int updateEmailStatus(String email, boolean status);
@@ -50,7 +49,11 @@ public interface UserMapper {
int delete(long id);
int setUserRole(Long uid, String role);
int lock(long id);
int setUserRole(Long id, String role);
List<User> findAll(Integer status);
List<User> findAll();

View File

@@ -20,5 +20,7 @@ public interface VisitorMapper {
List<Visitor> findAll();
List<Visitor> findAllNotDeleted();
long count();
}

View File

@@ -4,7 +4,6 @@ import cn.celess.blog.entity.WebUpdate;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/**
@@ -27,5 +26,7 @@ public interface WebUpdateInfoMapper {
List<WebUpdate> findAll();
Date getLastestOne();
List<WebUpdate> findAllNotDeleted();
WebUpdate getLastestOne();
}

View File

@@ -1,8 +1,8 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.model.ArticleModel;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.request.ArticleReq;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
@@ -39,11 +39,11 @@ public interface ArticleService {
/**
* 获取一篇文章的数据
*
* @param articleID 文章id
* @param articleId 文章id
* @param is4update 是否是因文章更新而请求数据
* @return 文章数据
*/
ArticleModel retrieveOneByID(long articleID, boolean is4update);
ArticleModel retrieveOneById(long articleId, boolean is4update);
/**
* 管理员 获取分页数据
@@ -52,7 +52,7 @@ public interface ArticleService {
* @param page 数据页
* @return 分页数据
*/
PageInfo adminArticles(int count, int page);
PageData<ArticleModel> adminArticles(int count, int page, Boolean deleted);
/**
* 获取文章状态为开放的文章
@@ -61,7 +61,7 @@ public interface ArticleService {
* @param page 数据页
* @return 分页数据
*/
PageInfo retrievePageForOpen(int count, int page);
PageData<ArticleModel> retrievePageForOpen(int count, int page);
/**
* 根据分类名获取文章数据
@@ -71,7 +71,7 @@ public interface ArticleService {
* @param page 数据页
* @return 分页数据
*/
PageInfo findByCategory(String name, int page, int count);
PageData<ArticleModel> findByCategory(String name, int page, int count);
/**
* 根据标签名获取文章数据
@@ -81,5 +81,5 @@ public interface ArticleService {
* @param page 数据页
* @return 分页数据
*/
PageInfo findByTag(String name, int page, int count);
PageData<ArticleModel> findByTag(String name, int page, int count);
}

View File

@@ -1,10 +1,9 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.Category;
import cn.celess.blog.entity.model.CategoryModel;
import cn.celess.blog.entity.model.PageData;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author : xiaohai
* @date : 2019/03/28 22:42
@@ -17,15 +16,7 @@ public interface CategoryService {
* @param name 分类名
* @return 所增加的分类数据
*/
Category create(String name);
/**
* 增加一个分类
*
* @param category 分类对象
* @return 所增加的分类数据
*/
Category create(Category category);
CategoryModel create(String name);
/**
* 通过id删除分类
@@ -42,13 +33,13 @@ public interface CategoryService {
* @param name 分类名字
* @return 更新后的分类的数据
*/
Category update(Long id, String name);
CategoryModel update(Long id, String name);
/**
* 获取全部的分类数据
*
* @return 全部的分类数据
*/
List<Category> retrievePage();
PageData<CategoryModel> retrievePage(int page, int count);
}

View File

@@ -1,10 +1,12 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.model.CommentModel;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.request.CommentReq;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author : xiaohai
* @date : 2019/03/29 16:58
@@ -38,64 +40,52 @@ public interface CommentService {
/**
* 分页获取数据
*
* @param isComment true评论 false留言
* @param count 单页数据量
* @param page 数据页
* @param pagePath pagePath
* @param count 单页数据量
* @param page 数据页
* @return 分页数据
*/
PageInfo<CommentModel> retrievePage(Boolean isComment, int page, int count);
PageData<CommentModel> retrievePage(String pagePath, int page, int count);
/**
* 通过pid获取数据
*
* @param pid 父id
* @param count 单页数据量
* @param page 数据页
* @param pid 父id
* @return 分页数据
*/
PageInfo<CommentModel> retrievePageByPid(long pid, int page, int count);
List<CommentModel> retrievePageByPid(long pid);
/**
* 根据评论者获取数据
*
* @param isComment true评论 false留言
* @param count 单页数据量
* @param page 数据页
* @param pagePath pagePath
* @param count 单页数据量
* @param page 数据页
* @return 分页数据
*/
PageInfo<CommentModel> retrievePageByAuthor(Boolean isComment, int page, int count);
PageData<CommentModel> retrievePageByAuthor(String pagePath, int page, int count);
/**
* 根据文章获取数据
*
* @param articleID 文章id
* @param pid 父id
* @param count 单页数据量
* @param page 数据页
* @return 分页数据
*/
PageInfo<CommentModel> retrievePageByArticle(long articleID, long pid, int page, int count);
/**
* 根据数据的type和pid获取数据
*
* @param isComment true评论 false留言
* @param pid 父id
* @param count 单页数据量
* @param page 数据页
* @param pagePath pagePath
* @param pid 父id
* @param count 单页数据量
* @param page 数据页
* @return 分页数据
*/
PageInfo<CommentModel> retrievePageByTypeAndPid(Boolean isComment, int pid, int page, int count);
PageData<CommentModel> retrievePageByPageAndPid(String pagePath, long pid, int page, int count);
/**
* 根据type获取数据
*
* @param isComment true评论 false留言
* @param count 单页数据量
* @param page 数据页
* @param pagePath pagePath
* @param count 单页数据量
* @param page 数据页
* @return 分页数据
*/
PageInfo<CommentModel> retrievePageByType(Boolean isComment, int page, int count);
PageData<CommentModel> retrievePageByPage(String pagePath, int page, int count);
}

View File

@@ -36,13 +36,6 @@ public interface CountService {
*/
long getTagsCount();
/**
* 获取留言数量
*
* @return 留言数量
*/
long getLeaveMessageCount();
/**
* 获取用户量
*

View File

@@ -0,0 +1,40 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.model.FileInfo;
import cn.celess.blog.entity.model.FileResponse;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.List;
/**
* @author : xiaohai
* @date : 2020/10/15 18:19
* @desc : 文件管理器 定义操作文件的方法
*/
@Service
public interface FileManager {
/**
* 上传文件到文件存储容器中
*
* @param is 文件流
* @param fileName 文件名
* @return FileResponse
*/
FileResponse uploadFile(InputStream is, String fileName);
/**
* 获取文件列表
*
* @return 文件信息
*/
List<FileInfo> getFileList();
/**
* 删除文件
*
* @param fileName 文件名
* @return 是否删除成功
*/
boolean deleteFile(String fileName);
}

View File

@@ -0,0 +1,18 @@
package cn.celess.blog.service;
import org.springframework.stereotype.Service;
/**
* @author : xiaohai
* @date : 2019/04/25 18:15
*/
@Service("fileService")
@FunctionalInterface
public interface FileService {
/**
* 获取文件管理器
*
* @return 文件管理器 可以操作文件
*/
FileManager getFileManager();
}

View File

@@ -0,0 +1,20 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.InstallParam;
import org.springframework.stereotype.Service;
import javax.validation.constraints.NotNull;
import java.util.Map;
/**
* @author : xiaohai
* @date : 2020/10/23 16:22
* @desc :
*/
@Service
public interface InstallService {
Map<String, Object> isInstall();
Map<String, Object> install(@NotNull InstallParam installParam);
}

View File

@@ -1,8 +1,9 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -44,7 +45,7 @@ public interface PartnerSiteService {
* @param page 数据页
* @return 分页数据
*/
PageInfo<PartnerSite> PartnerSitePages(int page, int count);
PageData<PartnerSite> partnerSitePages(int page, int count, Boolean deleted);
/**
* 获取全部数据
@@ -53,4 +54,19 @@ public interface PartnerSiteService {
*/
List<PartnerSite> findAll();
/**
* 申请友链
*
* @param linkApplyReq linkApplyReq
* @return linkApplyReq
*/
PartnerSite apply(LinkApplyReq linkApplyReq);
/**
* 重写申请友链
*
* @param key key
* @return msg
*/
String reapply(String key);
}

View File

@@ -1,31 +0,0 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.model.QiniuResponse;
import com.qiniu.storage.model.FileInfo;
import org.springframework.stereotype.Service;
import java.io.InputStream;
/**
* @author : xiaohai
* @date : 2019/04/25 18:15
*/
@Service
public interface QiniuService {
/**
* 上传文件
*
* @param is InputStream流
* @param fileName 文件名
* @return 响应数据
*/
QiniuResponse uploadFile(InputStream is, String fileName);
/**
* 获取文件列表
*
* @return 文件列表
*/
FileInfo[] getFileList();
}

View File

@@ -1,7 +1,7 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.Tag;
import com.github.pagehelper.PageInfo;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.model.TagModel;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -18,16 +18,7 @@ public interface TagService {
* @param name 标签名
* @return 新增后的数据
*/
Tag create(String name);
/**
* 新增数据
*
* @param tag tag对象
* @return 新增后的数据
*/
Tag create(Tag tag);
TagModel create(String name);
/**
* 删除数据
@@ -44,24 +35,7 @@ public interface TagService {
* @param name 改名的name值
* @return 更新后的数据
*/
Tag update(Long id, String name);
/**
* 查询单个标签信息
*
* @param tagId id
* @return 标签的数据
*/
Tag retrieveOneById(long tagId);
/**
* 通过name查询标签的信息
*
* @param name tag的名称
* @return 标签数据
*/
Tag retrieveOneByName(String name);
TagModel update(Long id, String name);
/**
* 分页获取标签数据
@@ -70,13 +44,13 @@ public interface TagService {
* @param page 数据页
* @return 分页数据
*/
PageInfo<Tag> retrievePage(int page, int count);
PageData<TagModel> retrievePage(int page, int count);
/**
* 获取全部标签数据
*
* @return 标签数据列表
*/
List<Tag> findAll();
List<TagModel> findAll();
}

View File

@@ -1,16 +1,12 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.User;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.model.UserModel;
import cn.celess.blog.entity.request.LoginReq;
import cn.celess.blog.entity.request.UserReq;
import com.github.pagehelper.PageInfo;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.List;
/**
* @author : xiaohai
@@ -42,14 +38,6 @@ public interface UserService {
*/
Object logout();
/**
* 获取用户头像的链接
*
* @param id 用户id
* @return 头像链接
*/
String getAvatarImg(long id);
/**
* 更新用户数据
*
@@ -83,14 +71,6 @@ public interface UserService {
*/
String getUserRoleByEmail(String email);
/**
* 通过邮箱获取用户的信息
*
* @param email 用户邮箱
* @return 用户信息
*/
User getUserInfoByEmail(String email);
/**
* 获取邮箱是否注册过
*
@@ -99,14 +79,6 @@ public interface UserService {
*/
boolean isExistOfEmail(String email);
/**
* 获取用户的name 优先返回displayName 否则返回email
*
* @param id 用户id
* @return name
*/
String getNameById(long id);
/**
* 发送重置密码邮件
*
@@ -157,7 +129,7 @@ public interface UserService {
* @param page 数据页
* @return 分页数据
*/
PageInfo<UserModel> getUserList(Integer page, Integer count);
PageData<UserModel> getUserList(Integer page, Integer count, Integer status);
/**
* 更改用户信息
@@ -174,4 +146,14 @@ public interface UserService {
* @return true:存在 false不存在
*/
boolean getStatusOfEmail(String email);
/**
* 设置密码
*
* @param pwd pwd
* @param newPwd newPwd
* @param confirmPwd confirmPwd
* @return UserModel
*/
UserModel setPwd(String pwd, String newPwd, String confirmPwd);
}

View File

@@ -1,7 +1,7 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.model.VisitorModel;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
@@ -20,7 +20,7 @@ public interface VisitorService {
* @param showLocation 是否显示位置信息 开启改选项数据响应超慢
* @return 分页数据
*/
PageInfo<VisitorModel> visitorPage(int page, int count, boolean showLocation);
PageData<VisitorModel> visitorPage(int page, int count, boolean showLocation);
/**
* 新增访客

View File

@@ -1,10 +1,11 @@
package cn.celess.blog.service;
import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.model.WebUpdateModel;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @author : xiaohai
@@ -44,7 +45,7 @@ public interface WebUpdateInfoService {
* @param page 数据页
* @return 分页数据
*/
PageInfo<WebUpdateModel> pages(int count, int page);
PageData<WebUpdateModel> pages(int count, int page);
/**
* 获取全部的更新记录
@@ -58,5 +59,5 @@ public interface WebUpdateInfoService {
*
* @return
*/
String getLastestUpdateTime();
Map<String, Object> getLastestUpdateTime();
}

View File

@@ -0,0 +1,36 @@
package cn.celess.blog.service.fileserviceimpl;
import cn.celess.blog.enmu.ConfigKeyEnum;
import cn.celess.blog.service.FileManager;
import cn.celess.blog.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author : xiaohai
* @date : 2020/10/15 18:52
* @desc : 提供文件管理器的服务
*/
@Slf4j
@Service("fileServiceImpl")
public class FileServiceImpl implements FileService {
@Resource(name = "qiniuFileServiceImpl")
FileManager qiniuFileManager;
@Resource(name = "localFileServiceImpl")
FileManager localFileServiceImpl;
@Override
public FileManager getFileManager() {
String property = System.getProperty(ConfigKeyEnum.FILE_TYPE.getKey());
log.info("获取到{}:{}", ConfigKeyEnum.FILE_TYPE.getKey(), property);
if ("qiniu".equals(property)){
return qiniuFileManager;
}else if ("local".equals(property)){
return localFileServiceImpl;
}
return localFileServiceImpl;
}
}

View File

@@ -0,0 +1,104 @@
package cn.celess.blog.service.fileserviceimpl;
import cn.celess.blog.enmu.ConfigKeyEnum;
import cn.celess.blog.entity.model.FileInfo;
import cn.celess.blog.entity.model.FileResponse;
import cn.celess.blog.service.FileManager;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
/**
* @author : xiaohai
* @date : 2020/10/16 14:39
* @desc :
*/
@Slf4j
@Service("localFileServiceImpl")
public class LocalFileServiceImpl implements FileManager {
private static String path = null;
@SneakyThrows
@Override
public FileResponse uploadFile(InputStream is, String fileName) {
if (path == null) {
path = System.getProperty(ConfigKeyEnum.FILE_LOCAL_DIRECTORY_PATH.getKey());
}
// 判断文件夹是否存在
File directory = new File(getPath(path));
if (!directory.exists() && directory.mkdirs()) {
log.info("不存在文件夹,创建文件夹=>{}", directory.getAbsolutePath());
}
log.info("上传文件 {}", fileName);
// 存储文件
File file1 = new File(getPath(path) + File.separator + fileName);
FileOutputStream fos = new FileOutputStream(file1);
byte[] cache = new byte[1024 * 100];
int len = 0;
FileResponse fileResponse = new FileResponse();
while ((len = is.read(cache)) != -1) {
fileResponse.size += len;
fos.write(cache, 0, len);
}
fos.flush();
fos.close();
is.close();
fileResponse.key = URLEncoder.encode(fileName, "UTF-8");
fileResponse.type = "local";
return fileResponse;
}
@SneakyThrows
@Override
public List<FileInfo> getFileList() {
if (path == null) {
path = System.getProperty(ConfigKeyEnum.FILE_LOCAL_DIRECTORY_PATH.getKey());
}
File file = new File(getPath(path));
File[] files = file.listFiles();
List<FileInfo> fileInfoList = new ArrayList<>();
if (files == null) {
return null;
}
for (File file1 : files) {
FileInfo fileInfo = new FileInfo();
fileInfo.key = URLEncoder.encode(file1.getName(), "UTF-8");
fileInfo.size = file1.length();
BasicFileAttributes basicFileAttributes = Files.readAttributes(file1.toPath(), BasicFileAttributes.class);
fileInfo.uploadTime = basicFileAttributes.creationTime().toMillis();
fileInfoList.add(fileInfo);
}
return fileInfoList;
}
@Override
public boolean deleteFile(String fileName) {
if (path == null) {
path = System.getProperty(ConfigKeyEnum.FILE_LOCAL_DIRECTORY_PATH.getKey());
}
File file = new File(getPath(path) + File.separator + fileName);
return file.delete();
}
public static String getPath(String path) {
if (path == null) {
return "";
}
String pathCop = path.replaceAll("//", File.separator);
if (path.startsWith("~")) {
// 家目录
pathCop = path.replaceFirst("~", "");
pathCop = System.getProperty("user.home") + pathCop;
}
return pathCop;
}
}

View File

@@ -0,0 +1,120 @@
package cn.celess.blog.service.fileserviceimpl;
import cn.celess.blog.enmu.ConfigKeyEnum;
import cn.celess.blog.entity.model.FileInfo;
import cn.celess.blog.entity.model.FileResponse;
import cn.celess.blog.service.FileManager;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author : xiaohai
* @date : 2019/04/25 18:15
*/
@Service("qiniuFileServiceImpl")
public class QiniuFileServiceImpl implements FileManager {
private static final Configuration cfg = new Configuration(Zone.zone2());
private static UploadManager uploadManager;
private static BucketManager bucketManager;
private static Auth auth;
private String bucket;
/**
* todo :: 添加reload 方法 配置修改重新创建对象
*/
private void init() {
String accessKey = System.getProperty(ConfigKeyEnum.FILE_QINIU_ACCESS_KEY.getKey());
String secretKey = System.getProperty(ConfigKeyEnum.FILE_QINIU_SECRET_KEY.getKey());
this.bucket = System.getProperty(ConfigKeyEnum.FILE_QINIU_BUCKET.getKey());
if (auth == null || uploadManager == null || bucketManager == null) {
auth = Auth.create(accessKey, secretKey);
uploadManager = new UploadManager(cfg);
bucketManager = new BucketManager(auth, cfg);
}
}
@Override
public FileResponse uploadFile(InputStream is, String fileName) {
init();
//文件存在则删除文件
if (continueFile(fileName)) {
try {
System.out.println(bucketManager.delete(bucket, fileName).toString());
} catch (QiniuException e) {
e.printStackTrace();
}
}
//上传
try {
Response response = uploadManager.put(is, fileName, auth.uploadToken(bucket), null, null);
FileResponse fileResponse = new FileResponse();
StringMap stringMap = response.jsonToMap();
fileResponse.key = (String) stringMap.get("key");
fileResponse.type = "qiniu";
fileResponse.size = 0;
fileResponse.hash = (String) stringMap.get("hash");
return fileResponse;
} catch (QiniuException e) {
Response r = e.response;
System.err.println(r.toString());
return null;
}
}
@Override
public List<FileInfo> getFileList() {
init();
List<FileInfo> infoList = null;
BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, "", 1000, "");
while (fileListIterator.hasNext()) {
//处理获取的file list结果
infoList = new ArrayList<com.qiniu.storage.model.FileInfo>(Arrays.asList(fileListIterator.next()))
.stream()
.map(item -> {
FileInfo fileInfo = new FileInfo();
fileInfo.key = item.key;
fileInfo.hash = item.hash;
fileInfo.size = item.fsize;
fileInfo.uploadTime = item.putTime;
return fileInfo;
})
.collect(Collectors.toList());
}
return infoList;
}
@SneakyThrows
@Override
public boolean deleteFile(String fileName) {
init();
Response response = bucketManager.delete(bucket, fileName);
return "".equals(response.bodyString());
}
private boolean continueFile(String key) {
List<FileInfo> fileList = getFileList();
for (FileInfo fileInfo : fileList) {
if (key.equals(fileInfo.key)) {
return true;
}
}
return false;
}
}

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