Github pages Hexo博客访问量统计功能的实现

之前使用Hexo搭建了自己的github.io博客https://littlefogcat.github.io/。但是没有访问统计功能,让人头大。于是决定着手整一个。

首先需要有一台自己的服务器,如果没有的话就用busuanzi.js吧。(不过我总觉得数据在自己手里比较开心)

由于我对前后端开发几乎都是一窍不通,所以耗费了很多精力,不过最后还是稍有所得,在此记录。

1. 要点

1.1 跨域(同源策略)

由于浏览器的安全策略,js只可以访问相同协议、相同域名、相同端口(同源)下的资源。这就带来一个问题,博客中的js文件无法调用服务器端的接口。

1.2 jsonp

为了解决非同源跨域问题,这里采用了jsonp的解决方案。由于jsonp只支持get方式,所以参数都写在url中。

js端:

var currentPageUrl = window.location.href; // 当前页面地址
    
// 处理服务端返回的数据
function handleCallback(jsonData) {
    // 将获取到的访问量写入html中
}

// 参数
var arrivalServer = "https://myApi?callback=handleCallback&url=" + currentPageUrl;

其中myApi是服务端暴露的获取访问量的接口,而当前页面的url作为唯一标识符做参数传递。这里是有问题的,最好还是不要把url写在参数里,可以考虑base64编码。使用window.btoa()即可将字符串进行base64编码,反之使用window.atob()即可进行解码。

var serverBase64 = window.btoa(arrivalServer);

callback=handleCallback表示当服务端返回数据时,调用js里的handleCallback函数。

服务端

仅就Java而言,使用com.fasterxml.jackson.databind.util.JSONPObject这个类可以快速创建一个jsonp对象。
示例:

    // Code in Controller
    @ResponseBody
    @RequestMapping("/arrival")
    public Object getGithubIoArrival(@RequestParam String callback,
                                     @RequestParam String articleUrl,
                                     @RequestParam(required = false) String ip) {
        GithubIoArrivalResult result = service.getArrival(articleUrl, ip);

        return new JSONPObject(callback, result);
    }

1.3 https

由于Github Pages强制使用https访问,所以服务端也应该支持https。这篇文章有详细的步骤:5分钟内搞定 Tomcat 的 SSL 配置
如果不想整个应用都是用https,只用将url-pattern标签的内容改成所需要的即可。
如:<url-pattern>/githubio/*</url-pattern>

2. 服务端

首先明确需求,很简单:

  • 每个页面单独统计访问量
  • 单个ip每日最多计算一次访问量
  • 所有单次访问都有记录

这样需要两张表,一张保存每个页面的访问量(pv),一张保存详细的访问记录(record)。

逻辑很简单。当一个Get请求到达时,首先将其保存至record表中,然后再查找当天是否已经浏览过本页面。只有当这个ip当日没有浏览过本页面时,才更新pv表,本页面的浏览量+1。最后返回页面浏览数。

3. 前端(Hexo)

找到hexo博客的根目录, 修改themes\landscape\layout\_partial\head.ejs文件。
在其中添加一行

<script src="http://pv.sohu.com/cityjson?ie=utf-8" type="text/javascript"></script>

这个搜狐的链接,用于获取当前用户的IP地址。

然后,修改themes\landscape\layout\_partial\footer.ejs文件。添加以下内容

  <script type="text/javascript">
	var href = window.location.href; // 当前页面地址

	function handleCallback(jsonData) {
		console.log("jsonData = " + jsonData);
		var arrival = jsonData.arrival;
		document.getElementById("page_view").innerHTML = arrival;
	}
	
	var src = "https://106.14.152.93:8443/third/githubio/arrival?callback=handleCallback&articleUrl="
         + href + "&ip=" + returnCitySN["cip"];
	
	document.write("<script type=\"text/javascript\" src=\"" + src + "\"><\/script>");
  </script>

至此,访问统计功能就完成了。
sample

4 查漏

4.1 编码

在url中传递url会出现问题,这是显而易见的。所以,对于每个页面,其url需要经过编码才能传给服务端。常见的方式有base64。但是js中的base64编码只支持ascii字符,并不支持中文,所以不能使用这个方法。最后选择了encodeURIComponent来进行编码。

js端

var href = window.location.href;
href = encodeURIComponent(href)

编码前:https://littlefogcat.top/api/test/testEncodeURIComponent?param=hello你好
编码后:https%3A%2F%2Flittlefogcat.top%2Fapi%2Ftest%2FtestEncodeURIComponent%3Fparam%3Dhello%E4%BD%A0%E5%A5%BD

服务端

java.net.URLEncoder类和java.net.URLDecoder类和js的encodeURIComponentdecodeURIComponent是同样的作用。前端传递过来经过编码的url,只需要通过一句代码就能解码:

String urlDecoded = URLDecoder.decode(urlEncoded, "utf8");

5. 示例

LittleFogCat’s Page - https://littlefogcat.github.io/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值