feat:将官方文档迁移到新库

This commit is contained in:
anjoy8 2023-11-20 16:38:36 +08:00
parent c93c3eb44b
commit 1b3ab297f3
15 changed files with 3 additions and 1815 deletions

2
.docs/README.md Normal file
View File

@ -0,0 +1,2 @@
BlogCore官方文档仓库地址已经迁移到
https://gitee.com/laozhangIsPhi/Blog.Core.E-Book

View File

@ -1,46 +0,0 @@
module.exports = {
title: 'Blog.Core',
description: 'Hello, 欢迎使用前后端分离之 ASP.NET Core 后端全家桶框架!',
base : '/.doc/',
head: [
['link', {
rel: 'icon',
href: `/favicon.ico`
}]
],
dest: './contents/.vuepress/dist',
ga: '',
evergreen: true,
themeConfig: {
nav: [
{ text: '首页', link: '/' },
{ text: '指南', link: '/guide/' },
{ text: '更新日志', link: '/Update/' },
{ text: '压测', link: '/PressureTest/' },
{ text: '参与贡献', link: '/Contribution/' },
{ text: 'BCVP社区', link: '/QQ/' },
{ text: '接口API', link: 'http://apk.neters.club' },
{ text: '管理后台', link: 'http://vueadmin.neters.club' },
{ text: 'Github', link: 'https://github.com/anjoy8/Blog.Core' },
],
sidebarDepth: 2,
sidebar: {
'/guide/': getGuideSidebar('Guide'),
}
}
}
function getGuideSidebar (groupA) {
return [
{
title: groupA,
collapsable: false,
children: [
'',
'getting-started',
'function-sheet',
'cheat-sheet'
]
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,143 +0,0 @@
# 贡献
欢迎一起完善文档,
参与打赏的小可爱名单如下(单位:元),你们的贡献是我继续的动力:
(2021年9月9日 13点53分)
|序号|微信昵称|助力值|备注|
|-|-|-|-|
|01|排 * * 瓜|100||
|02|船 * * 长|100||
|03|二 * * 生|1||
|04||1|未留微信号|
|05|旭 * * 光|10||
|06||12.66|未留微信号|
|07|Ro * * st|10||
|08|陈 * * 朝|10||
|09|勇 * * 勇|10||
|10|袁 * * 嘉|10||
|11|En * * us|20||
|12|风 * * 在|18||
|13|林 * * 杰|10||
|14|枫 * * 叶|10||
|15|火 * * 鸟 |50||
|16|阿 * * 福|10||
|17||20|未留微信号|
|18|Er * * or|100|未留微信号|
|19|陶 * * ve|20||
|20|熊 * * 育|50||
|21|点 * * 痕|20||
|22|夏 * * 目|20||
|23|CL * * L|50||
|24|rm * * rf|100||
|25|Je * * ca|30|搜不到微信号|
|26|W * * 生|50||
|27|鹏 * * 郎|20||
|28|ws * * ai|10||
|29|逐 * * 梦|20||
|30|Jo * * aH|10||
|31|Do * * n|10||
|32|灰 * * 白|50||
|33|Ne * * er|100||
|34|Ar * * as|10||
|35|吉 * * 祥|36||
|36|ma * * y|10||
|37|Yu * * ic|30||
|38|亡 * * 死|30||
|39|板 * * 根|20||
|40|-- * * -|100|未留微信号|
|41|t * * |20||
|42|王 * * 聪 |10|未留微信号|
|43|哈 * * 方|50||
|44|le * * on|30||
|45|李 * * |10||
|46|不 * * 染|10|未留微信号|
|47|林 * * LIN|10||
|48|阿 * * 奇|30||
|49|哒 * * 哒|10||
|50|王 * * 龙|100||
|51|Ja * * Tu|100||
|52|it * * hi|100||
|53|沙 * * 锋|50|未留微信号|
|54|Ba * * ai|10||
|55|古 * * 桐|10||
|56|小 * * 柜|20||
|57|rm * * rf|100||
|58|高 * * 源|10||
|59|Qq * * 80|10|未留微信号|
|60|如 * * 寄|20||
|61|大 * * 灰|10|未留微信号|
|62|包 * * 华|10|微信号错误|
|63|西 * * 5°|30||
|64|王 * * 粮|20||
|65|Q1 * * ..|30||
|66|Le * * ry|100||
|67|bo * * t|30||
|68|早 * * 蛋|10||
|69|罗 * * 啊|10||
|70|40 * * er|30||
|71|胡 * * 运|30||
|72|昌 * * 进|5||
|73|甲 * * 学|15||
|74|小 * * 走|100||
|75|啊 * * 辉|50||
|76|D * * W|100||
|77|简 * * 简|99||
|78|空 * * 空|101||
|79|朱 * * 傻|20||
|80|Mr * * hi|50||
|81|王 * * 飞|110||
|82|Mr * * nn|20|微信号未搜到|
|83|蓝 * * 兴|30||
|84|Et * * ng|100||
|85|Ke * * on|10||
|86|几 * * 己|20||
|87|张 * * 群|20||
|88|睡 * * 鱼|30||
|89|Mr * * 宋|50||
|90|布 * * 布|10||
|91|s * * s|6.6||
|92|V * * V|50||
|93|o**o|50||
|94|书**6|6.6||
|95|精**E|50||
|96|有**幸|10||
|97|r**y|10||
|98|v**c|5||
|99|j**n|20||
|100|贾**琪|100||
|101|a**s|20||
|102|狂**牛|10||
|103|风**宜|10||
|104|鸠**夜|5||
|105|大**灰|15||
|106|不**懂|100||
|107|圣**旨|50||
|108|A**n|50||
|109|薛**猫|100||
|110|岁**叁|10||
|111|K**g|100||
|112|琛**田|30||
|113|L**s|20||
|114|小**哥|10||
|115|G**e|10||
|116|s**o|30||
|117|大**白|50||
|118|星**星|20||
|119|沙**锋|200||
|120|词**意|11||
|121|A**N|20||
|122|像**恋|10||
|123|M**o|10||
|124|风**虹|50||
|125|健**诚|10||
|126|**|5||
|127|何**玖|6.66||
|128|A**g|10||
|129|高**广|20||
|130|吴**杰|0.01||
|131|刘**标|0.01||

View File

@ -1,80 +0,0 @@
# 框架压测报告
## 1、测试工具
使用 `JMeter` 进行压力测试。
测试时间2021年1月21日 09点38分。
服务器报告:
<img src="https://img.neters.club/doc/report.png" />
## 2、测试准备
因为 `JMeter` 是使用 `JAVA` 写的,所以使用 `JMeter` 之前,先安装 `JAVA` 环境。
安装好后,在 `bin` 文件夹下,点击 `jmeter.bat` 启动程序。
启动之后会有两个窗口,一个`cmd`窗口,一个`JMeter`的 `GUI`。前面不要忽略`CMD`窗口的提示信息,不要关闭它。
注意:使用`API`模式,不要使用`GUI`模式。
## 3、测试配置
本地发布后的 `windows` 环境,直接用 `kestrel` 启动。
线程数100
循环数1000
HTTP默认值协议`http`服务器或IP`localhost`;端口号:`9291`
HTTP请求方法GET路径`/api/blog/ApacheTestUpdate`
HTTP信息请求管理器
响应断言:无
<img src="https://img.neters.club/doc/config.png" />
## 4、项目初始化
目前采用 `Blog.Core` 默认的配置,
只开启了内存 `AOP`
其他的都是默认的,然后也把任务调度也关闭了,
最后注意要把 `IP限流`给关闭,不然压测没效果,因为限流了:
<img src="https://img.neters.club/doc/init.png" />
## 5、压测过程
##### 第一阶段
<img src="https://img.neters.club/doc/test01.png" />
##### 第二阶段
<img src="https://img.neters.club/doc/test02.png" />
##### 第三阶段
<img src="https://img.neters.club/doc/test03.png" />
##### 第四阶段压测后检测内存是否降低20m后
<img src="https://img.neters.club/doc/test04.png" />
##### 第五阶段停止压测1h后
<img src="https://img.neters.club/doc/test_05.png" />
## 6、测试结果
内存方面,`100*1000` 的 **压测过程中** (写操作),项目保证所占内存在 `350m~500m` 之间
然后停止一个小时后,内存将为`150m~200m`
<img src="https://img.neters.club/doc/test04.png" />
<img src="https://img.neters.club/doc/test_05.png" />
## 7、压测配置文件下载
[配置文件](https://img.neters.club/doc/blogcore_blog_ApacheTestUpdate.jmx)
下载后,导入到工具里,可以直接测试,察看结果树。
## 8、Docker 镜像
已经提交到 `docker hub` 自行拉取操作即可:
```
docker pull laozhangisphi/apkimg:latest
```

View File

@ -1,18 +0,0 @@
## 开源社区
<img src="http://apk.neters.club/.doc/bcvphomelogo.png" alt="bcvp" width="200" >
[https://github.com/BaseCoreVueProject/Home](https://github.com/BaseCoreVueProject/Home)
Base netCore (Vue) Project Team
基于Net/Core 和Vuereact/ng快速搭建 MVC & SPA 及微服务应用
如果你有关于dotNet/core 的,不错的,可以正常运行,且一年内维护的,均可以加入。
唯一宗旨:我们来自社区,服务社区,反哺社区。
## 微信公众号
<img src="https://img.neters.club/doc/WeChat%20Screenshot_20200624194936.png" alt="公众号" width="600" >

View File

@ -1,14 +0,0 @@
---
home: true
heroImage: /bcvphomelogo.png
actionText: 快速上手 →
actionLink: /guide/
features:
- title: 详尽的文档
details: 通过详细的文章和视频讲解将知识点各个击破入门ASP.Net Core不再难
- title: 强大的社区
details: 通过 QQ 群,和数千位同业大佬一起切磋交流。
- title: 丰富的内容
details: 框架涵盖ASP.Net Core开发中常见的基本知识点不仅适合初学者入门同时也适用于企业级别的开发。
footer: MIT Licensed | Copyright © 2018-2020-老张的哲学 Powered by VUEPRESS on CentOS 7.6
---

View File

@ -1,198 +0,0 @@

## 更新日志
### 2021-08-21
重要功能增加:项目增加 `Apollo` 配置中心;
### 2021-08-03
重要功能增加:项目增加 `ES` 搜索,增加 `Serilog` 使用 `tcp` 的方式自定义格式化,写入 `elk` 的实现;
### 2021-06-28
功能增加:项目增加 `nacos` 配置,支持将项目注册到 `nacos` 服务中心,搭建微服务之子服务;
### 2021-06-04
小功能更新:执行的时候,将 `Sql` 日志输出到控制台,方便查看,支持配置文件关闭;
### 2021-05-01
组件更新:多项日志中间件,由自写组件,转为使用`serilog`组件记录日志;
### 2021-03-03
项目目录调整:新增测试文件夹和模板文件夹;
### 2021-02-09
重大项目更新:新增建行聚合支付;
### 2021-01-11
更新:优化任务调度功能,新增暂停和停止;
### 2020-12-02
更新:新增调用`MongoDB`功能,功能可用待完善中;
### 2020-11-19
> 重大内容更新:更新项目模板 `Update Blog.Core.Webapi.Template.2.5.2.nupkg`
> 主要内容1、泛型主键2、通过测试中间件3、`RabbitMQ`消息队列
### 2020-11-18
项目更新:新增`RabbitMQ`消息队列和`EventBus`事件总线,功能可用待完善。
### 2020-11-11
项目重大更新:更新至`.NET 5.0`。
### 2020-11-05
项目更新:增加`测试用户`中间件,通过一键操作可以跳过权限限制,方便调试,文章[使用测试用户中间件](http://apk.neters.club/api/Blog/GoUrl?id=156)。
### 2020-10-11
项目更新:设计泛型主键功能,可以在项目初始化的时候设计主键类型。
### 2020-09-18
项目更新:更新项目模板 `Update Blog.Core.Webapi.Template.2.2.3.nupkg`
> 1、增加 `Redis` 消息队列功能;
### 2020-09-04
项目更新:增加 `Redis` 消息队列功能;
### 2020-08-06
项目更新:更新项目模板 `Update Blog.Core.Webapi.Template.2.2.0.nupkg`
> 1、根据解决方案名来自动导入model
> 2、单独封装服务扩展层 `Blog.Core.Extensions`
> 3、代码生成器支持控制器文件的生成
> 4、弱化仓储层用泛型仓储基类注入服务
### 2020-08-01
> 重大结构更新:弱化仓储层,通过泛型仓储基类,来实现仓储服务注入,并去掉`Blog.Core.IRepository` 接口层;
### 2020-07-03
> 更新:`DbFirstController` 生成四层文件,目前新增支持 `控制器Controller` 文件的输出;
### 2020-06-22
> 项目更新:将服务扩展和自定义中间件,单独封装一层 `Blog.Core.Extensions` ,更解耦。
### 2020-06-08
> 简单项目更新:生成数据库表结构的时候,利用反射机制,自动生成固定命名空间 `Blog.Core.Model.Models` 下的全部实体.
> 同时判断表是否存在,如果存在下次不再重复生成。
### 2020-06-06
项目更新:更新项目模板 `Update Blog.Core.Webapi.Template.2.1.0.nupkg` [1a726f8](https://github.com/anjoy8/Blog.Core/commit/1a726f890e527c978982071462e82db4478632f0),更新项目即可 。
> 1、配置内容展示到控制台
> 2、简化封装 `Startup.cs` 类文件;
> 3、`DbFirst` 模式支持多库模式;
> 4、`Log4net` 讲异常和 `Info` 分开;
> 5、修复 `BlogLogAop` 偶尔卡顿问题;
> 6、将生成种子数据和任务调度功能封装到中间件
> 7、获取当前项目在服务器中的运行信息
> 8、删除所有的不需要的 `using` 指令;
### 2020-05-29
项目启动开启 `QuzrtzNet` 调度任务,并且在 `Admin` 后台管理中配置操作界面;
> 内容更新:封装生成种子数据的入口方法;
### 2020-05-12
修复:支持多库模式下,生成项目模板代码 `DbFirstController` [102c6d6](https://github.com/anjoy8/Blog.Core/commit/102c6d6bfcafd06bf5241844759dea5e7a6815da)
> 注意:`T4` 模板不能此功能,一次只能一个数据库,且只能 `SqlServer`
### 2020-05-07
> 重大内容更新:更新项目模板 `Update Blog.Core.Webapi.Template.2.1.0.nupkg` [7f64fde](https://github.com/anjoy8/Blog.Core/commit/7f64fde5507f7a8572372dcadb6af5110bd37d68)
### 2020-05-06
> 重大内容更新优化Log4Net使用方案,完美配合 `NetCore` 官方的 `ILogger<T>` [ecaffb6](https://github.com/anjoy8/Blog.Core/commit/ecaffb66bdf10a90c087d01e6e817e54f23a97d4)
### 2020-05-01
> 重要内容更新配合Admin全部完成按钮级别权限更新初始化种子数据
### 2020-04-27
增加功能配合前端Admin增加页面 `KeepAlive` 功能;
增加功能:增加 `Sql` 语句查询Demo支持返回 `DataTable`
### 2020-04-25
增加功能:`Http api` 接口调用,满足微服务需求
> 重要内容更新:优化 `Appsettings.app()` 方法,通过官方 `IConfiguration` 接口来获取DBS连接字符串
> 优化 `BlogLogAOP.cs`
### 2020-04-15
> 重大内容更新:更新项目模板 `Update Blog.Core.Webapi.Template.1.11.30.nupkg`
### 2020-04-14
> 重大内容更新主分支可以通过配置一键切换JWT和Ids4认证授权模式
### 2020-03-30
> 重大内容更新:统一所有接口返回格式
### 2020-03-25
增加功能:支持读写分离(目前是三种模式:单库、多库、读写分离)
> 重大BUG更新系统登录接口未对用户软删除进行判断现已修复
> API: /api/login/GetJwtToken3
> Code: await _sysUserInfoServices.Query(d => d.uLoginName == name && d.uLoginPWD == pass && d.tdIsDelete == false);
### 2020-03-18
增加功能:创建 Quartz.net 任务调度服务
### 2020-01-09
增加功能项目迁移到IdentityServer4统一授权认证中心
### 2020-01-05
增加功能:设计一个简单的中间件,可以查看所有已经注入的服务
### 2020-01-04
增加功能Ip限流防止过多刷数据

View File

@ -1,121 +0,0 @@
# W 文档指南
## 亮点与优势
Blog.Core 是一个开箱即用的企业级权限管理应用框架。
采用最新的前后端完全分离技术【 ASP.NET Core Api 5.0 + Vue 2.x 】。
并结合 `IdentityServer4` ,可快速解决多客户端和多资源服务的统一认证与鉴权的问题。
## 其他资料
博客园,早期架构搭建:[博客园](https://www.cnblogs.com/laozhang-is-phi/p/9495618.html)
公众号,后期调整:[文章](https://mvp.neters.club/MVP_aspnetcore_2020/2020)
视频:[B站](https://www.bilibili.com/video/BV1vC4y1p7Za)
## 配套站点
本资源服务器,配合多个项目,构建前后端权限一体化平台,前端用 `VUE` 框架。
前端-客户端:[预览](https://vueadmin.neters.club/)、[源码](https://github.com/anjoy8/Blog.Admin)
前端-管理后台:[预览](http://vueblog.neters.club/)、[源码](https://github.com/anjoy8/Blog.Vue)
认证平台:[预览](https://ids.neters.club/)、[源码](https://github.com/anjoy8/Blog.IdentityServer)
### 为什么选择 ASPNET.Core
1、【开源】`ASPNET.NET Core` 是由 `Microsoft``.NET` 社区在 `GitHub` 上开源并维护的一个跨平台(支持 Windows、macOS 和 Linux的新一代高性能框架
拥有十分广泛的社区与支持者可用于构建web应用、物联网IOT应用和移动端应用。
2、【高效】Asp.net core(.net core)来源于.net很容易迁移而且也很容易上手
但是又是不同的一个框架,除了上述对.net开发者十分友好以外相对于之前的.net项目速度上有巨大的改进
相比与原来的`Web.net framework 4.6`程序性能提升了`2300%`。跟`python`、`java`等相同环境比较,性能都要优越,
参考[www.techempower.com](https://www.techempower.com/benchmarks/)。
3、【跨平台】可以在`Windows`、`Mac`和`Linux`构建和运行跨平台的`Asp.Net Core`应用。
4、【云原生】在云原生领域拥有天然的优势搭配Azure云服务配合K8s更好的实现分布式应用以及微服务应用。
5、【微服务】`ASP.NET Core`尤其适用于微服务架构也就是说ASP.NET Core不仅适合于中小型项目而且还特别适合于大型超大型项目。
6、【大公司】目前国内采用`ASP.NET Core`的大公司比如腾讯、网易国际的有BingGoDaddyStackoverflowAdobeMicrosoft
7、【总结来说】`java`支持的,`ASPNET.Core`都支持,而且更轻量级、更高效跨,并且对.net开发者十分友好微服务案例成熟。
### 框架功能点
1、丰富完整的接口文档在查看的基础上可以模拟前端调用更方便。
2、采用多层开发隔离性更好封装更完善。
3、基于项目模板可以一键创建自己的项目。
4、搭配代码生成器实现快速开发节省成本。
5、项目集成多库模式以及读写分离模式可以同时处理多个数据库的不同模块更快更安全。
6、集成统一认证平台 `IdentityServer4` ,实现多个项目的统一认证管理,解决了之前一个项目,
一套用户的弊端,更适用微服务的开发。
7、丰富的审计日志处理方便线上项目快速定位异常点。
8、支持自由切换多种数据库Sqlite/SqlServer/MySql/PostgreSQL/Oracle
9、支持 `Docker` 容器化开发,可以搭配 k8s 更好的实现微服务。
### 应用领域
1、【对接第三方api】项目通过`webapi`,可以快速对接第三方`api`服务,实现业务逻辑。
2、【前后端分离】 采用的是`API`+前端的完全分离的开发模式,满足平时开发的所有需求,
你可以对接任何的自定义前端项目无论是微信小程序还是授权APP无论是PC网页
还是手机H5。
3、【多项目】同时框架还集成了一套鉴权平台采用IdentityServer4可以快速的实现多个客户端的认证与授权服务
从而大大的减少了平时的工作量,可以快速的进行产品迭代。
4、【微服务】当然因为采用的是API模式所以同样适用于微服务项目实现高并发的产品需求。
### 市场前景
1、前后端分离模式已经是目前的主流开发模式框架已经是一套可行的方案开箱即用。
2、拥有几十篇技术文档和3000人的技术社区方便快捷的解决问题。
3、目前已经有超过20多家公司在生产环境中使用当然实际中更多具体查看 [点击查看使用的情况](https://github.com/anjoy8/Blog.Core/issues/75)。
4、同时可以搭配自己的业务实现微服务的开发在大数据高并发中占有更好的优势。
5、本项目直接作者由微软MVP“老张的哲学”出品并长久维护不会断更有保障。
## 功能与进度
框架模块:
- [√] 采用`仓储+服务+接口`的形式封装框架;
- [√] 异步 async/await 开发;
- [√] 接入国产数据库ORM组件 —— SqlSugar封装数据库操作
- [√] 支持自由切换多种数据库MySql/SqlServer/Sqlite/Oracle/Postgresql/达梦/人大金仓;
- [√] 实现项目启动,自动生成种子数据 ✨;
- [√] 五种日志记录,审计/异常/请求响应/服务操作/Sql记录等
- [√] 支持项目事务处理若要分布式用cap即可
- [√] 设计4种 AOP 切面编程,功能涵盖:日志、缓存、审计、事务 ✨;
- [√] 支持 T4 代码模板,自动生成每层代码;
- [√] 或使用 DbFirst 一键创建自己项目的四层文件(支持多库);
- [√] 封装`Blog.Core.Webapi.Template`项目模板,一键重建自己的项目 ✨;
- [√] 搭配多个前端案例供参考和借鉴Blog.Vue、Blog.Admin、Nuxt.tbug、Blog.Mvp.Blazor ✨;
- [√] 统一集成 IdentityServer4 认证 ✨;
组件模块:
- [√] 提供 Redis 做缓存处理;
- [√] 使用 Swagger 做api文档
- [√] 使用 MiniProfiler 做接口性能分析 ✨;
- [√] 使用 Automapper 处理对象映射;
- [√] 使用 AutoFac 做依赖注入容器,并提供批量服务注入 ✨;
- [√] 支持 CORS 跨域;
- [√] 封装 JWT 自定义策略授权;
- [√] 使用 Log4Net 日志框架,集成原生 ILogger 接口做日志记录;
- [√] 使用 SignalR 双工通讯 ✨;
- [√] 添加 IpRateLimiting 做 API 限流处理;
- [√] 使用 Quartz.net 做任务调度(目前单机多任务,集群调度暂不支持);
- [√] 支持 数据库`读写分离`和多库操作 ✨;
- [√] 新增 Redis 消息队列 ✨;
- [√] 新增 RabbitMQ 消息队列 ✨;
- [√] 新增 EventBus 事件总线 ✨;
- [√] 新增 实现聚合支付;
- [ ] 计划 - 数据部门权限;
- [ ] 计划 - ES 搜索;
微服务模块:
- [√] 可配合 Docker 实现容器化;
- [√] 可配合 Jenkins 实现CI / CD
- [√] 可配合 Consul 实现服务发现;
- [√] 可配合 Ocelot 实现网关处理;
- [√] 可配合 Nginx 实现负载均衡;
- [√] 可配合 Ids4 实现认证中心;
&nbsp;

View File

@ -1,580 +0,0 @@
# Z 主要知识点
## AOP
本项目多处采用面向切面编程思想——AOP除了广义上的过滤器和中间件以外主要通过动态代理的形式来实现AOP编程思想主要的案例共有四个分别是
1、服务日志AOP
2、服务InMemory缓存AOP
3、服务Redis缓存AOP
4、服务事务AOP
具体的代码可以在 `Blog.Core\Blog.Core\AOP` 文件夹下查看。
与此同时多个AOP也设置了阀门来控制是否开启具体的可以查看 `appsettings.json` 中的:
```
"AppSettings": {
"RedisCachingAOP": {
"Enabled": false,
"ConnectionString": "127.0.0.1:6319"
},
"MemoryCachingAOP": {
"Enabled": true
},
"LogAOP": {
"Enabled": false
},
"TranAOP": {
"Enabled": false
},
"SqlAOP": {
"Enabled": false
}
},
```
## Appsettings
整个系统通过一个封装的操作类 `Appsettings.cs` 来控制配置文件 `appsettings.json` 文件,
操作类地址在:`\Blog.Core.Common\Helper` 文件夹下。
具体的使用方法是:
```
Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "Enabled" })
// 里边的参数,按照 appsettings.json 中设置的层级顺序来写,可以获取到指定的任意内容。
```
## AspNetCoreRateLimit
系统使用 `AspNetCoreRateLimit` 组件来实现ip限流
1、添加 `nuget` 包:
```
<PackageReference Include="AspNetCoreRateLimit" Version="3.0.5" />
```
2、注入服务 `IpPolicyRateLimitSetup.cs`
```
services.AddIpPolicyRateLimitSetup(Configuration);
```
3、配置中间件
```
// Ip限流,尽量放管道外层
app.UseIpRateLimiting();
```
4、配置数据
具体的内容,自行百度即可
```
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,//返回状态码
"GeneralRules": [//规则,结尾一定要带*
{
"Endpoint": "*",
"Period": "1m",
"Limit": 120
},
{
"Endpoint": "*:/api/blog*",
"Period": "1m",
"Limit": 30
}
]
}
```
## Async-Await
整个系统采用 async/await 异步编程,符合主流的开发模式,
特别是对多线程开发很友好。
## Authorization-Ids4
本系统 v2.0 版本(目前的系统已经集成 `ids4``jwt`,并且可以自由切换),已经支持了统一授权认证,和 `blog` 项目、`Admin` 项目、`DDD` 项目等一起,使用一个统一的认证中心。
具体的代码参考:`.\Blog.Core\Extensions` 文件夹下的 `Authorization_Ids4Setup.cs` ,注意需要引用指定的 `nuget` 包,核心代码如下:
```
//【认证】
services.AddAuthentication(o =>
{
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = nameof(ApiResponseHandler);
o.DefaultForbidScheme = nameof(ApiResponseHandler);
})
// 2.添加Identityserver4认证
.AddIdentityServerAuthentication(options =>
{
options.Authority = Appsettings.app(new string[] { "Startup", "IdentityServer4", "AuthorizationUrl" });
options.RequireHttpsMetadata = false;
options.ApiName = Appsettings.app(new string[] { "Startup", "IdentityServer4", "ApiName" });
options.SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Jwt;
options.ApiSecret = "api_secret";
})
```
### 如何在Swagger中配置Ids4
很简单,直接在 `SwaggerSetup.cs` 中直接接入 `oauth、Implicit` 即可:
```
//接入identityserver4
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri($"{Appsettings.app(new string[] { "Startup", "IdentityServer4", "AuthorizationUrl" })}/connect/authorize"),
Scopes = new Dictionary<string, string> {
{
"blog.core.api","ApiResource id"
}
}
}
}
});
```
然后在 `IdentityServer4` 项目中,做指定的修改,配置 `9291` 的回调地址:
```
new Client {
ClientId = "blogadminjs",
ClientName = "Blog.Admin JavaScript Client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris =
{
"http://vueadmin.neters.club/callback",
// 这里要配置回调地址
"http://localhost:9291/oauth2-redirect.html"
},
PostLogoutRedirectUris = { "http://vueadmin.neters.club" },
AllowedCorsOrigins = { "http://vueadmin.neters.club" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles",
"blog.core.api"
}
},
```
然后再 `Swagger` 中,配置登录授权:
<img src="http://apk.neters.club/images/20200507213830.png" alt="swagger" width="600" >
## Authorization-JWT
如果你不想使用 `IdentityServer4` 的话,也可以使用 `JWT` 认证,同样是是`Blog.Core\Blog.Core\Extensions` 文件夹下的 `AuthorizationSetup.cs` 中有关认证的部分:
```
1.添加JwtBearer认证服务
.AddJwtBearer(o =>
{
o.TokenValidationParameters = tokenValidationParameters;
o.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
// 如果过期,则把<是否过期>添加到,返回头信息中
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
})
```
## AutoMapper
使用 `AutoMapper` 组件来实现 `Dto` 模型的传输转换,具体的用法,可以查看:
`Blog.Core\Blog.Core\Extensions` 文件夹下的 `AutoMapperSetup.cs` 扩展类,
通过引用 `AutoMapper``AutoMapper.Extensions.Microsoft.DependencyInjection` 两个 `nuget` 包,并设置指定的 `profile` 文件,来实现模型转换控制。
```
// 比如如何定义:
public class CustomProfile : Profile
{
/// <summary>
/// 配置构造函数,用来创建关系映射
/// </summary>
public CustomProfile()
{
CreateMap<BlogArticle, BlogViewModels>();
CreateMap<BlogViewModels, BlogArticle>();
}
}
// 比如如何使用
models = _mapper.Map<BlogViewModels>(blogArticle);
```
具体的查看项目中代码即可。
## CORS
在线项目使用的是 `nginx` 跨域代理,但是同时也是支持 `CORS` 代理:
1、注入服务 `services.AddCorsSetup();` 具体代码 `Blog.Core\Blog.Core\Extensions` 文件夹下的 `CorsSetup.cs` 扩展类;
2、配置中间件 `app.UseCors("LimitRequests");` ,要注意中间件顺序;
3、配置自己项目的前端端口通过在 `appsettings.json` 文件中配置自己的前端项目 `ip:端口` ,来实现跨域:
```
"Startup": {
"Cors": {
"IPs": "http://127.0.0.1:2364,http://localhost:2364,http://localhost:8080,http://localhost:8021,http://localhost:1818"
}
},
```
## DI-AutoFac
项目使用了依赖注入,除了原生的依赖注入以外,更多的使用的是第三方组件 `Autofac`
1、引用依赖包
```
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="4.5.0" />
```
主要是第一个 `nuget` 包,下边的是为了实现动态代理 `AOP` 操作;
2、项目之间采用引用解耦的方式通过反射来注入服务层和仓储层的程序集 `dll` 来实现批量注入,更方便,以后每次新增和修改 `Service` 层和 `Repository` 层,只需要 `F6` 编译一下即可,具体代码查看 `Startup.cs`
```
// 注意在CreateDefaultBuilder中添加Autofac服务工厂
public void ConfigureContainer(ContainerBuilder builder)
{
var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
//builder.RegisterType<AdvertisementServices>().As<IAdvertisementServices>();
#region 带有接口层的服务注入
var servicesDllFile = Path.Combine(basePath, "Blog.Core.Services.dll");
var repositoryDllFile = Path.Combine(basePath, "Blog.Core.Repository.dll");
if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
throw new Exception("Repository.dll和service.dll 丢失因为项目解耦了所以需要先F6编译再F5运行请检查 bin 文件夹,并拷贝。");
}
// AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。
var cacheType = new List<Type>();
if (Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogRedisCacheAOP>();
cacheType.Add(typeof(BlogRedisCacheAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "MemoryCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogCacheAOP>();
cacheType.Add(typeof(BlogCacheAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogTranAOP>();
cacheType.Add(typeof(BlogTranAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "LogAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogLogAOP>();
cacheType.Add(typeof(BlogLogAOP));
}
// 获取 Service.dll 程序集服务,并注册
var assemblysServices = Assembly.LoadFrom(servicesDllFile);
builder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerDependency()
.EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
.InterceptedBy(cacheType.ToArray());//允许将拦截器服务的列表分配给注册。
// 获取 Repository.dll 程序集服务,并注册
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
builder.RegisterAssemblyTypes(assemblysRepository)
.AsImplementedInterfaces()
.InstancePerDependency();
#endregion
#region 没有接口层的服务层注入
//因为没有接口层,所以不能实现解耦,只能用 Load 方法。
//注意如果使用没有接口的服务,并想对其使用 AOP 拦截,就必须设置为虚方法
//var assemblysServicesNoInterfaces = Assembly.Load("Blog.Core.Services");
//builder.RegisterAssemblyTypes(assemblysServicesNoInterfaces);
#endregion
#region 没有接口的单独类 class 注入
//只能注入该类中的虚方法
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Love)))
.EnableClassInterceptors()
.InterceptedBy(cacheType.ToArray());
#endregion
// 这里和注入没关系,只是获取注册列表,请忽略
tsDIAutofac.AddRange(assemblysServices.GetTypes().ToList());
tsDIAutofac.AddRange(assemblysRepository.GetTypes().ToList());
}
```
3、然后 `Program.cs` 中也要加一句话:` .UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<--NOTE THIS `
## DI-NetCore
除了主要的 `Autofac` 依赖注入以外,也减少的使用了原生的依赖注入方式,很简单,比如这样的:
```
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// 注入权限处理器
services.AddScoped<IAuthorizationHandler, PermissionHandler>();
services.AddSingleton(permissionRequirement);
```
## Filter
项目中一共有四个过滤器
```
1、GlobalAuthorizeFilter.cs —— 全局授权配置,添加后,就可以不用在每一个控制器上添加 [Authorize] 特性但是3.1版本好像有些问题,【暂时放弃使用】;
2、GlobalExceptionFilter.cs —— 全局异常处理,实现 actionContext 级别的异常日志收集;
3、GlobalRoutePrefixFilter.cs —— 全局路由前缀公约,统计在路由上加上前缀;
4、UseServiceDIAttribute.cs —— 测试注入,【暂时无用】;
```
文件地址在 `.\Blog.Core\Filter` 文件夹下,其中核心的是 `2` 个,重点使用的是 `1` 个 —— 全局异常错误日志 `GlobalExceptionsFilter`:
通过注册在 `MVC` 服务 `services.AddControllers()` 中,实现全局异常过滤:
```
services.AddControllers(o =>
{
// 全局异常过滤
o.Filters.Add(typeof(GlobalExceptionsFilter));
// 全局路由权限公约
//o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
// 全局路由前缀,统一修改路由
o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
})
```
## Framework
项目采用 `服务+仓储+接口` 的多层结构,使用依赖注入,并且通过解耦项目,较完整的实现了 `DIP` 原则:
高层模块不应该依赖于底层模块,二者都应该依赖于抽象。
抽象不应该依赖于细节,细节应该依赖于抽象。
同时项目也封装了:
`CodeFirst` 初始化数据库以及数据;
`DbFirst` 根据数据库(支持多库),生成多层代码,算是简单代码生成器;
其他功能,[核心功能与进度](http://apk.neters.club/.doc/guide/#%E5%8A%9F%E8%83%BD%E4%B8%8E%E8%BF%9B%E5%BA%A6)
## Log
通过集成 `Log4Net` 组件,完美配合 `NetCore` 官方的 `ILogger<T>` 接口,实现对日志的管控,引用 `nuget``Microsoft.Extensions.Logging.Log4Net.AspNetCore`:
Program.cs
```
webBuilder
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, builder) =>
{
//该方法需要引入Microsoft.Extensions.Logging名称空间
builder.AddFilter("System", LogLevel.Error); //过滤掉系统默认的一些日志
builder.AddFilter("Microsoft", LogLevel.Error);//过滤掉系统默认的一些日志
//添加Log4Net
//var path = Directory.GetCurrentDirectory() + "\\log4net.config";
//不带参数表示log4net.config的配置文件就在应用程序根目录下也可以指定配置文件的路径
//需要添加nuget包Microsoft.Extensions.Logging.Log4Net.AspNetCore
builder.AddLog4Net();
});
```
然后直接在需要的地方注入使用,比如在控制器中
` public UserController(ILogger<UserController> logger)`
然后就可以使用了。
> 注意:日志 其实是分为两部分的:
> netcore输出(控制台、输出窗口等) 和 `ILogger` 持久化
> 两者对应配置也不一样,就比如上边的过滤,是针对日志持久化的,如果想要对控制台进行控制,需要配置 `appsettings.json` 中的 `Logging` 节点
## MemoryCache
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## Middleware
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## MiniProfiler
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## publish
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## Redis
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## Repository
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## SeedData
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## SignalR
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## SqlSugar
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## SqlSugar-Codefirst&DataSeed
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## SqlSugar-SqlAOP
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## Swagger
精力有限,还是更新中...
如果你愿意帮忙可以直接在GitHub中提交pull request
我会在后边的贡献者页面里,列出你的名字和项目地址做推广
## T4
项目集成 `T4` 模板 `.\Blog.Core.FrameWork` 层,目的是可以一键生成项目模板代码。
1、需要在 `DbHelper.ttinclude` 中配置连接数据库连接字符串;
2、针对每一层的代码就去指定的 `.tt` 模板,直接 `CTRL+S` 保存即可;
> 注意,目前的代码是 `SqlServer` 版本的,其他数据库版本的,可以去群文件查看。
## Test-xUnit
项目简单使用了单元测试,通过 `xUnit` 组件,具体的可以查看 `Blog.Core.Tests` 层相关代码。
目前单元测试用例还比较少,大家可以自行添加。
## Temple-Nuget
本项目封装了 `Nuget` 自定义模板,你可以根据这个模板,一键创建自己的项目名,具体的操作,可以双击项目根目录下的 `CreateYourProject.bat` ,可以参考 [#如何项目重命名](http://apk.neters.club/.doc/guide/getting-started.html#%E5%A6%82%E4%BD%95%E9%A1%B9%E7%9B%AE%E9%87%8D%E5%91%BD%E5%90%8D)
同时,你也可以再 `Nuget` 管理器中,搜索到:
<img src="http://apk.neters.club/images/20200507223058.png" alt="nuget" width="600" >
## UserInfo
项目中封装了获取用户信息的代码:
`.\Blog.Core.Common\HttpContextUser` 文件夹下 `AspNetUser.cs` 实现类和 `IUser.cs` 接口。
如果使用,首先需要注册相应的服务,参见:`.\Blog.Core\Extensions` 文件夹下的 `HttpContextSetup.cs`
然后,就直接在控制器构造函数中,注入接口 `IUser` 即可;
> `注意`
> 1、如果要想获取指定的服务必须登录也就是必须要在 `Header` 中传递有效 `Token` ,这是肯定的。
> 2、如果要获取用户信息一定要在中间件 `app.UseAuthentication()` 之后(不要问为什么),控制器肯定在它之后,所以能获取到;
> 3、`【并不是】`一定需要添加 `[Authorize]` 特性,如果你加了这个特性,可以直接获取,但是如果不加,可以从我的 `AspNetUser.cs` 方法中,有一个直接从 `Header` 中解析的方法 `List<string> GetUserInfoFromToken(string ClaimType);`
```
public string GetToken()
{
return _accessor.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "");
}
public List<string> GetUserInfoFromToken(string ClaimType)
{
var jwtHandler = new JwtSecurityTokenHandler();
if (!string.IsNullOrEmpty(GetToken()))
{
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(GetToken());
return (from item in jwtToken.Claims
where item.Type == ClaimType
select item.Value).ToList();
}
else
{
return new List<string>() { };
}
}
```

View File

@ -1,471 +0,0 @@
# H 核心功能一览表
## 一、表结构解析
`Blog.Core` 项目共包含四部分的数据库表结构,分别是:用户角色管理部分、接口菜单权限管理部分、博客文章管理部分、以及其他不重要部分。
> 注意:目前不提供与维护数据库数据,直接通过 `SeedData` 生成种子数据;
### 1、用户角色管理部分[必须]
主要是三个表:分别对应用户表(sysUserInfo)、角色表(Role)、用户角色关系表(UserRole)。
<img src="http://img.neters.club/doc/usermanager.png" alt="usermanager" >
### 2、接口菜单权限管理部分[必须]
主要是四个表:分别对应接口表(Module)、菜单表(Permission)、接口菜单关系表(ModulePermission)暂时没用到、角色接口菜单关系表(RoleModulePermission)。
<img src="http://img.neters.club/doc/permissionmanager.png" alt="permissionmanager" >
### 3、博客文章管理部分[可选]
主要是三个表:分别对应博客表(BlogArticle)、Bug专题表(Topic)、Bug内容表(TopicDetail)。
<img src="http://img.neters.club/doc/blogmanager.png" alt="blogmanager" >
### 4、其他不重要部分
主要是三个表分别对应Job调度表(TasksQz)、密码库表(PasswordLib)、操作日志表(OperateLog)、广告表(Advertisement)、公告表(Guestbook)。
<img src="http://img.neters.club/doc/othersmanager.png" alt="othersmanager" >
## 二、日志记录
本框架涵盖了不同领域的日志记录,共五个,分别是:
1、全局异常日志
开启方式:无需操作。
文件路径web目录下Log/GlobalExcepLogs_{日期}.log。
功能描述:记录项目启动后出现的所有异常日志,不包括中间件中异常。
2、IP 请求日志
开启方式:无需操作。
文件路径web目录下Log/RequestIpInfoLog.log。
功能描述记录项目启动后客户端请求的ip和接口信息。
举例来说:
{"Ip":"xxx.xx.xx.x","Url":"/api/values","Datetime":"2020-01-06 18:02:19","Date":"2020-01-06","Week":"周一"}
3、用户API访问日志
开启方式appsettings.json -> Middlewar -> RecordAccessLogs 节点为true。
文件路径web目录下Log/RecordAccessLogs_{日期}.log。
功能描述记录项目启动后客户端所有的API访问日志包括参数、body以及用户信息。
4、服务层请求响应AOP日志
开启方式appsettings.json -> AppSettings -> LogAOP 节点为true。
文件路径web目录下Log/AOPLog.log。
功能描述记录项目启动请求api后所有的service层日志包括方法名、参数、响应结果或用户非必须
5、数据库操作日志
开启方式appsettings.json -> AppSettings -> SqlAOP 节点为true。
文件路径web目录下Log/SqlLog.log。
功能描述记录项目启动请求api并访问service后所有的db操作日志包括Sql参数与Sql语句。
举例来说:
--------------------------------
1/6/2020 6:13:04 PM|
【SQL参数】@bID0:1
【SQL语句】SELECT `bID`,`bsubmitter`,`btitle`,`bcategory`,`bcontent`,`btraffic`,`bcommentNum`,`bUpdateTime`,`bCreateTime`,`bRemark`,`IsDeleted` FROM `BlogArticle` WHERE ( `bID` = @bID0 )
## 三、控制台信息展示
<img src="https://img.neters.club/doc/2020-05-09_182758.png" alt="配置" width="800" >
## 四、Nginx一览表
```
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 64;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 128k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
#gzip on;
######################################################################
server {
listen 80;
server_name www.neters.club;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root C:\code\Code\Neters\home;
index index.html index.htm;
}
}
server {
listen 80;
server_name neters.club;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root C:\code\Code\Neters\home;
index index.html index.htm;
}
}
server {
listen 80;
server_name ids.neters.club;
rewrite ^(.*)$ https://$host$1 permanent;#把http的域名请求转成https第二种写法在此节的末端
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#proxy_pass http://localhost:5004;
root html;
index index.html index.htm;
}
}
server {
listen 443 ssl;
server_name ids.neters.club; #网站域名和80端口保持一致
ssl on;
ssl_certificate 1_ids.neters.club_bundle.crt; #证书公钥
ssl_certificate_key 2_ids.neters.club.key; #证书私钥
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH:AESGCM:HIGH:!RC4:!DH:!MD5:!3DES:!aNULL:!eNULL;
ssl_prefer_server_ciphers on;
error_page 497 https://$host$uri?$args;
location / {
proxy_pass http://localhost:5004;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
#proxy_cookie_path
chunked_transfer_encoding off;
}
}
server {
listen 80;
server_name apk.neters.club;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
location /.doc/ {
proxy_pass http://docs.neters.club/;
}
}
server {
listen 80;
server_name docs.neters.club;
location / {
root C:\code\Code\Blog.Core\.docs\contents\.vuepress\dist;
index index.html index.htm;
}
}
server {
listen 80;
server_name vueadmin.neters.club;
location / {
try_files $uri $uri/ /index.html;
root C:\code\Code\Blog.Admin\distis;
#proxy_pass http://localhost:2364;
index index.html index.htm;
}
location /api/ {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
#proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /api2/ {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /images/ {
include uwsgi_params;
proxy_pass http://localhost:9291;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
#proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /.doc/ {
proxy_pass http://docsadmin.neters.club/;
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name docsadmin.neters.club;
location / {
root C:\code\Code\Blog.Admin\.doc\contents\.vuepress\dist;
index index.html index.htm;
}
}
server {
listen 80;
server_name ddd.neters.club;
location / {
proxy_pass http://localhost:4773;
index index.php index.html index.htm;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name ask.neters.club;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
proxy_pass http://localhost:5020;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
#proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
index index.html index.htm;
}
}
server {
listen 80;
server_name vueblog.neters.club;
location / {
try_files $uri $uri/ /index.html;
root C:\code\Code\Blog.Vue\dist;
index index.html index.htm;
}
location /api {
rewrite ^.+apb/?(.*)$ /$1 break;
include uwsgi_params;
proxy_pass http://localhost:9291;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /images {
include uwsgi_params;
proxy_pass http://localhost:9291;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
upstream nodenuxt {
server 127.0.0.1:3089; # nuxt 项目监听PC端端口
keepalive 64;
}
server {
listen 80;
server_name tibug.neters.club;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Nginx-Proxy true;
proxy_cache_bypass $http_upgrade;
proxy_pass http://nodenuxt;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name jwt.neters.club;
location / {
root C:\code\Code\jwttoken;
index index.html index.htm;
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
```
> 这里说明下,我的 `Nginx` 文件中,`Ids4` 项目强制使用 `Https` ,采用的是直接跳转,这也是一个办法,当然还有第二种办法(感谢 `tibos`)
```
server {
listen 80;
server_name admin.wmowm.com;
location / {
proxy_pass http://localhost:9002;
index index.php index.html index.htm;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl;#监听443端口https默认端口
server_name admin.wmowm.com; #填写绑定证书的域名
ssl_certificate /etc/nginx/conf.d/key/admin.wm.crt;#填写你的证书所在的位置
ssl_certificate_key /etc/nginx/conf.d/key/admin.wm.key;#填写你的key所在的位置
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照这个协议配置
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:9002;
index index.php index.html index.htm;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```

View File

@ -1,132 +0,0 @@
# K 快速上手
注意
请确保你的 `Visual Studio 2019` 版本 >= `16.8.2`
并安装 `.NET 5.0 SDK`
## 下载
Github国际 下载 [https://github.com/anjoy8/Blog.Core](https://github.com/anjoy8/Blog.Core)
Gitee国内 下载 [https://gitee.com/laozhangIsPhi/Blog.Core](https://gitee.com/laozhangIsPhi/Blog.Core)
## 编译与运行
1、拿到项目后双击 `Blog.Core.sln` 解决方案;
2、首先 `F6` 编译,看是否有错误;
3、然后 `F5` 运行,调起 `9291` 端口,浏览器查看效果;
4、因为系统默认的是 `sqlite` 数据库,如果你想换其他数据库,请看下边;
5、注意本系统是直接自动生成数据库和数据的不用手动创建数据库
## CodeFirst 与 DbFirst
1、项目同时支持两个常见开发模式`CodeFirst` 和 `DbFirst`
2、首先 如果你是第一次下载我的项目,肯定是想要浏览效果和直接使用对应的权限相关的内容,这个时候肯定需要用到数据库表结构,那就肯定需要 `CodeFirst` ,只需要在`appsettings.json` 里配置好数据库连接字符串(下文会说到如何配置),就能正确运行;
3、浏览器查看效果或者配合 `Admin` 项目查看效果后,如果感觉项目可行,并打算在此基础上二次开发,那肯定会在你刚刚创建的数据库种去创建新的表结构,这个时候就需要使用 `DbFirst` 模式来生成四层项目问题Model+Service+Repository等
4、你可以使用T4模板但是我更建议使用 `/api/DbFirst/GetFrameFiles` 接口来生成,不仅支持多种类型的数据库,还支持同时多库模式的输出;
5、如果你不想用我的表结构和实体类在项目启动的时候把配置文件的 `SeedDBEnabled`节点设置成False即可然后配置对应的你自己的数据库连接字符串比如是商城的然后使用 `/api/DbFirst/GetFrameFiles` 接口来生成你的数据库四层类文件;
## 如何配置数据库连接字符串
1、打开 `Blog.Core` 项目下的 `appsettings.json` 文件;
2、修改 `DBS` 字节内容,配置对应的连接字符串,注意`DBType`对应不同的数据库类型;
3、把你想要运行的数据库 `Enabled``true` 即可,其他都要设置 `false`
4、然后 `MainDB` 设置为下边你使用的指定 `ConnId`:
```
"MainDB": "WMBLOG_MSSQL", //当前项目的主库所对应的连接字符串的Enabled必须为true
"MutiDBEnabled": false, //是否开启多库
"DBS": [
{
"ConnId": "WMBLOG_SQLITE",
"DBType": 2,// sqlite数据库
"Enabled": true,// 设置为true启用1
"Connection": "WMBlog.db" //只写数据库名就行
},
{
"ConnId": "WMBLOG_MSSQL",
"DBType": 1,// sqlserver数据库
"Enabled": true,// 设置为true启用2
"Connection": "Server=.;Database=WMBlogDB;User ID=sa;Password=123;",
"ProviderName": "System.Data.SqlClient"
},
{
"ConnId": "WMBLOG_MYSQL",
"DBType": 0,// mysql
"Enabled": false,// false 不启用
"Connection": "Server=localhost; Port=3306;Stmt=; Database=wmblogdb; Uid=root; Pwd=456;"
},
{
"ConnId": "WMBLOG_ORACLE",
"DBType": 3,// Oracle
"Enabled": false,// 不启用
"Connection": "Provider=OraOLEDB.Oracle; Data Source=WMBlogDB; User Id=sss; Password=789;"
}
],
```
5、如果你想多库操作需要配置
```
aMainDB 设置为主库的 ConnId
bMutiDBEnabled设置为true
c把下边想要连接的多个连接字符串都设置为true
```
## 如何配置项目端口号
1、在 `Blog.Core` 层下的 `program.cs` 文件中,将 `9291`端口,修改为自己想要的端口号;
2、或者在 `launchSettings.json` 中设置(`注意如果仅仅修改这里publish后端口访问无效`)
## 如何项目重命名
1、双击项目根目录下的 `CreateYourProject.bat` 批处理文件;
2、根据提示`在Dos窗口内`输入自己想要的项目名称即可;
3、在根目录会有一个 `.1YourProject` 文件夹,里边即你的项目;
## 新增实体模块后如何迁移到数据库
1、在 `Blog.Core.Model` 项目目录下的 `Seed` 文件夹下,找到 `DBSeed` 类;
2、根据提示找到生成table的地方 `myContext.CreateTableByEntity`
3、添加进去你新增的实体类当然也可以用下边的单独写法
4、编译项目没错后运行,则数据库更新完毕;
## 新增实体如何进行增删改查CURD操作
1、随便找一个含有业务逻辑的 `controller` 参考一下即可;
2、主要 `api` 是通过 `Service` 服务层提供业务逻辑;
3、然后服务层通过 `Repository` 仓储层封装持久化操作;
4、每一个表基本上对应一个仓储类基本的操作都封装到了 `BaseRepository.cs` 基类仓储中;
5、添加完业务逻辑记得要 `F6` 重新编译一下,因为项目间引用解耦了;
6、项目已经自动注入了直接在控制器使用对应的服务层接口就行 `IxxxxService` ;
## 新增数据库表,如何反向生成四层文件
1、可以通过 `T4` 模板来生成,在 `Blog.Core.FrameWork` 层,使用方法: [9757999.html](https://www.cnblogs.com/laozhang-is-phi/p/9757999.html#autoid-4-3-0)
> 注意:这种方案,目前默认的只能是 `SqlServer` ,其他类型的数据库,可以看上边文章中的代码,或者群文件里对应的代码。
> 1、修改`DbHelper.ttinclude`文件中的连接字符串,注意是`SqlServer`的: public static readonly string ConnectionString;
> 2、然后去各个层模板文件点击`Ctrl+S`;
> 3、就会在对应的层内看到新文件比如Blog.Core.Model/Model_NEW
2、也可以通过 `Sqlsugar` 所带的方法来实现 `DbFirst`,具体查看 `Controller` 层下的 `DbFirstController.cs`
3、总体操作过程可以参考我的视频[av77612407](https://www.bilibili.com/video/av77612407?p=2)
## 发布与部署
1、双击项目根目录下的 `Blog.Core.Publish.bat`批处理文件;
2、执行完成后根目录会有一个`.PublishFiles` 文件夹,就是发布后的项目;
## 如何更新项目模板
1、着急的话自己打包不着急就提 `issue`,等我更新;
2、我的开源项目中有个模板项目 `BlogCoreTempl` [地址](https://github.com/anjoy8/BlogCoreTempl),下载下来;
3、下载最新的 `Blog.Core` 源代码;
4、将源代码拷贝到模板项目的 `content` 文件夹下;
5、双击 `Package.bat` 文件,就生成了最新的模板了;

View File

@ -1,12 +0,0 @@
{
"name": "BCVP",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

1
.gitignore vendored
View File

@ -358,3 +358,4 @@ Blog.Core.Api/wwwroot/ui/
Blog.Core.Api/Logs
*.db
/Blog.Core.Api/WMBlog.db-journal
.docs/.vuepress/dist/