基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计
系列文章
- 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?
- 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目
- 基于.NetCore开发博客项目 StarBlog - (3) 模型设计
- 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入
- 基于.NetCore开发博客项目 StarBlog - (5) 开始搭建Web项目
- 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表
- 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面
- 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示
- 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入
- 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流
- 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计
- ...
前言
放完端午假期回来,我的博客还没上线,看着各位大佬的网站都办得风生水起,我隐约感觉到一丝紧迫感,得抓紧时间写代码了~!
前面的文章已经把博客网站的基本功能实现起来了,距离网站上线只有一步之遥,然而还有一些细枝末节之处,对网站的运营或者用户体验有很大影响,必须完善的,比如:
- 网站访问统计
- 图床
按照先后顺序,本文先解决访问统计的问题。
一提到访问统计,众所周知的就是Google Analytics或者百度统计,前者在国内无法使用,后者应该是唯一选择了,但考虑到两者的功能差距以及该公司的口碑,对我这个小破站来说,我宁愿自己实现一个~
实现
实现起来应该是不难的,为了实现统计、分析,我们需要先记录,记录的内容包括用户的IP、设备、访问路径、访问时间,然后再对这些数据进行分析,就可以得出每篇文章、图片、分类的阅读量/访问量。
为了记录这些数据,需要在用户发起每一个请求时都进行处理,在AspNetCore中有多种实现,比如Filter、比如Middleware
这里我选的是中间件的方式
PS:我看到网上有一篇文章介绍Django实现访问统计的,那个作者写了一个方法,在每个接口里调用一次,看得我头皮发麻
在中间件中注入Repo,然后每次请求都把IP、设备、请求路径等数据保存在数据库中。这样看起来应该是会有一些影响性能的,不过考虑到博客网站的并发应该很小,带来的性能损失应该可以忽略不计。(说白了就是懒)
后续有性能瓶颈时再来优化吧~
模型定义
在StarBlog.Data/Models中新建一个VisitRecord.cs
为了节省篇幅,注释啥的就不放了,具体代码可见github
public class VisitRecord {
public int Id { get; set; }
public string Ip { get; set; }
public string RequestPath { get; set; }
public string? RequestQueryString { get; set; }
public string RequestMethod { get; set; }
public string UserAgent { get; set; }
public DateTime Time { get; set; }
}
写个中间件
在StarBlog.Web/Middlewares中新建一个VisitRecordMiddleware.cs
public class VisitRecordMiddleware {
private readonly RequestDelegate _next;
public VisitRecordMiddleware(RequestDelegate requestDelegate) {
_next = requestDelegate;
}
public Task Invoke(HttpContext context, IBaseRepository<VisitRecord> visitRecordRepo) {
var request = context.Request;
var response = context.Response;
visitRecordRepo.InsertAsync(new VisitRecord {
Ip = "",
RequestPath = request.Path,
RequestQueryString = request.QueryString.Value,
RequestMethod = request.Method,
UserAgent = request.Headers.UserAgent,
Time = DateTime.Now
});
return _next(context);
}
}
这里有个地方要注
意的,我的visitRecordRepo是在Invoke方法中注入的,为什么不在构造方法中注入呢?
因为AspNetCore中间件的构造方法是Singleton的,所以只能注入Singleton方式的服务,而FreeSQL的Repository是Scoped的,如果在构造方法中注入就会报错
所以只能在Invoke方法中注入~
使用中间件
编辑StarBlog.Web/Programs.cs,增加中间件配置
app.UseMiddleware<VisitRecordMiddleware>();
PS:本项目基于.Net6,Startup和Program合二为一了;如果是.NetCore3.1及以下版本,则是在Startup.cs中配置中间件。
效果
目前还没有根据访问记录做分析,所以只能截个数据库的图片

OK,接下来可以根据这些数据来做分析了(后面管理后台开发的部分再来写)
基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计的更多相关文章
- 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (18) 实现本地Typora文章打包上传
前言 九月太忙,只更新了三篇文章,本来这个功能是从九月初就开始做的,结果一直拖到现在国庆假期才有时间完善并且写文章~ 之前我更新了几篇关于 Python 的文章,有朋友留言问是不是不更新 .Net 了 ...
- 基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索
前言 笔者认为,一个博客网站,最核心的是阅读体验. 在开发StarBlog的过程中,最耗时的恰恰也是文章的展示部分功能. 最开始还没研究出来如何很好的使用后端渲染,所以只能先用Editor.md组件做 ...
- 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
随机推荐
- 数据库篇:mysql事务原理之MVCC视图+锁
前言 数据库的事务特性 数据并发读写时遇到的一致性问题 mysql事务的隔离级别 MVCC的实现原理 锁和隔离级别 关注公众号,一起交流,微信搜一搜: 潜行前行 1 数据库的事务特性 原子性:同一个事 ...
- Java中的List接口实现类LinkedList
package collection; import java.util.LinkedList; /* * 1.implement List接口 * 2.底层是一个链表结构:查询慢,增删快 * 注意: ...
- kubectl scale sts
使用scale 不单单是扩容还可以:1.动态扩展服务,增加承载能力2.如果出现pod异常,可以利用这种方式,增加pod,再删除原来的pod 比如:pod所在宿主机网络或者宿主机死掉注: 但是一旦有某个 ...
- 查域名对应ip,测试端口是否可访问通
根据命令查询软件包名称 yum provides */nslookup 根据域名解析ip nslookup 域名 示例:nslookup smtp.163.com 测试端口 telnet ip 端口 ...
- iOS全埋点解决方案-UITableView和UICollectionView点击事件
前言 在 $AppClick 事件采集中,还有两个比较特殊的控件: UITableView •UICollectionView 这两个控件的点击事件,一般指的是点击 UITableViewCell 和 ...
- 『现学现忘』Git基础 — 3、Git介绍
目录 1.Git的历史 2.Git的特点 3.Git在项目协作开发中所解决的问题 1.Git的历史 Git是目前世界上最先进的分布式版本控制系统,开源.免费. Git 是 Linus (林纳斯)为了帮 ...
- Dubbo-admin启动问题
在Github上down了Dubbo-admin的最新文件,使用cmd命令打包完成后启动出现了问题,输出找不到2181端口的error. 百度只查询到是Dubbo-admin配置中的Zookeeper ...
- 靶场vulnhub-CH4INRULZ_v1.0.1通关
1.CH4INRULZ_v1.0.1靶场通关 ch4inrulz是vulnhub下的基于Linux的一个靶场,作为练习之用 目的:通过各种手段,获取到靶机内的flag的内容 2.环境搭建: 攻击机 K ...
- golang常用库包:Go依赖注入(DI)工具-wire使用
google 出品的依赖注入库 wire:https://github.com/google/wire 什么是依赖注入 依赖注入 ,英文全名是 dependency injection,简写为 DI. ...
- Promise了解
Promise是一个构造函数,excutor是他的执行函数,同时也是构造函数的参数. new Promise(excutor) excutor有两个参数(resolve,reject) Promise ...