我在搭建个人技术网站时,遇到需要统计浏览量的需求时,没找到合适的统计平台。因为个人的需求和常规的 PV、UV 统计方式存在一定差异,因此萌生了自己设计开发一款浏览量统计工具。
这里阐述一下我的需求和什么是 PV、UV 统计。
我的期望是:一个用户进入网站时,访问多个页面会记录多次,但是同一 session 下反复打开刷新同一个页面只记为一次。
先明确工具的核心功能就是统计页面的访问次数。除了统计功能外还需要一些辅助功能模块,让工具更加完善也适用更多使用场景。
为了让工具有一定的安全性,所以设计的时候需要一个授权认证模块。因为授权认证的存在可以防止统计接口被恶意调用,让接口和数据被安全有了保障。同时授权需要一个合适的算法去保证安全性的同时,也不至于太过复杂而降低接口性能。
浏览统计有不同的统计方式,例如我们常说的 PV 和 UV。所以针对统计我们需要有一个策略,区分针对该次是否需要新记录一个浏览数量还是已经存在的浏览,不需要重复统计。
随着统计工具的运行,会生成许许多多的统计数据,所以我们还需要一个数据存储模块。因为存在不同服务器环境和业务场景,我们可能有不一样的数据存储需求。我们常见的数据存储有文件存储、内存数据库、Redis 以及关系型数据库。
作为一个工具类或者是一个 SDK,项目需要有足够的扩展点或者说每个功能都需要拓展开发的能力。接触过源码的就会知道,扩展点可以降低项目模块之间的耦合性,让各个模块的维护更容易。参考 Spring 源码可以在流程上的关键点保留一下可以拓展的接口。
授权认证功能,我们常规的做法时做在拦截器中,全局生效。将授权认证和其他的逻辑代码拆分开来,这样一来授权完全是独立的,可以随意控制启用、停用或者修改都不会影响功能逻辑。这就很明显的可以看出解耦的好处,各个模块相互独立,也意味着维护和控制都是独立的。
统计策略功能,同样是针对数据进行过滤,只放行需要做记录的数据。但是统计策略只针对统计浏览量进行过滤,所以可以在浏览量统计的入口,添加一个扩展点。使用 Spring 容器配合接口的方式调用自定义策略,或者通过 SPI 机制进行注入替换默认的实现。
数据存储功能,是对数据的存储。常见的存储就是内存数据库、Redis、关系数据库和文件。拥有同样的能力,但是存在多种实现,使用接口或者继承都是可以的,但是接口更为灵活更加常用。
单单是文字描述比较空洞,这里举一点代码示例,就更加容易理解了。
// 定义了一个存储接口,用于统计浏览量加一
public interface Repostory {
void save(Object data);
}
// Redis 实现
public class RedisRepostory implements Repostory {
public void save(Object data) {
// 执行 Redis 的存储操作
}
}
// H2 内存数据库实现
public class H2Repostory implements Repostory {
public void save(Object data) {
// 执行H2 内存数据库的存储操作
}
}
// 调用处
Repostory repostory = ... // 通过 Spring 容器、SPI 或者 工厂方法的方式获取一个实现类
repostory.save(data); // 因为多态的存在,具体执行的将有实现类决定,在调用处不用关心