起因

前段时间发现博客右边的FlagCounter计数器突然没了,又看到了博客园封杀了FlagCounter的消息,有点摸不着头脑。于是上FlagCounter的网站上看了一眼,发现最近出现的来自新国家访问居然来自台湾。又经过一轮百度,看到有博主发表声明说由于国家立场拒绝使用FlagCounter了。于是我赶紧把公告栏清空了,又苦于没有替代品,就想着干脆自己写一个。

FlagCounter将台湾显示为国家


显示效果对比(左:FlagCounter 右:自制)

前端显示的是HTML,比FlagCounter的图片格式要清晰很多。

开发环境以及线上环境

  • SpringBoot 2.1.8
  • Redis 5.0.x
  • 域名 + SSL证书 (博客园需要https)

使用到的接口及开源数据

  • www.taobao.com/help/getip.php 用于获取IP地址(可以直接用下面的接口获取,之前疏忽了)
  • http://ip-api.com/json/ 用于解析IP地理位置(只提供HTTP,所以请求需要通过后端发送)
  • https://github.com/mukeshsolanki/country-picker-android 国旗图片来源

开发思路

  用户访问时通过淘宝接口在前端获取访客IP地址,传给后端。后端向ip-api请求ip地址解析后的国家代码,并记录到Redis数据库。同时向后端请求访客数据,并显示在页面上。

  其实在找国家代码标准的数据的时候,发现有两种标准:一种是ISO-3166标准,还有一种是GB/T 2659-2000。区别在于,前者把香港、台湾等地区标为HK、TW,后者直接都标记为CN。可能FlagCounter也只是被这个标准坑了一波,把所有的国家代码标注的地区都当做了国家处理。

关键代码

package com.qf;  

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import java.util.HashMap;
import java.util.Set; @CrossOrigin
@RestController
@Transactional
public class Controller { @Autowired
private StringRedisTemplate redisTemplate; private RestTemplate restTemplate = new RestTemplate(); // 接口隐藏
@RequestMapping("xxxxxx")
public String getVisitor(){
// 取出排名前20的国家以及total(总数),所以是0-20共21个
Set<ZSetOperations.TypedTuple<String>> typedTupleSet = redisTemplate.opsForZSet().reverseRangeWithScores("visitor", 0, 20);
return JSON.toJSON(typedTupleSet).toString();
} // 接口隐藏
@RequestMapping("xxxxxx")
public void addVisitor(@PathVariable String ip){
// 请求ip-api接口,获取ip所属地信息
IPaddr iPaddr = restTemplate.getForObject("http://ip-api.com/json/"+ip, IPaddr.class, new HashMap<>());
String code = iPaddr.getCountryCode();
// 转换为GB/T 2659-2000标准
if (code.equals("HK") || code.equals("TW") || code.equals("MO")) {
code = "CN";
}
// 更新Redis中的记录
redisTemplate.opsForZSet().incrementScore("visitor", code, 1);
redisTemplate.opsForZSet().incrementScore("visitor", "total", 1);
}
}

FlagCounter被封杀?自己实现一个简单的多国访客计数器的更多相关文章

  1. 用mkdocs在gitee码云上建立一个简单的文档博客

    利用mkdocs建立简单的文档博客 一.概述 MkDocs 是一个用于创建项目文档的 快速, 简单 , 完美华丽 的静态站点生成器. 文档源码使用 Markdown 来撰写, 用一个 YAML 文件作 ...

  2. 从开发到部署,使用django创建一个简单可用的个人博客

    本文参考于: 简书-Django搭建简易博客教程:http://www.jianshu.com/p/d15188a74104 自强学堂-Django基础教程:http://www.ziqiangxue ...

  3. 一个简单的hexo搭建博客网站的故事

    首先安装hexo mkdir hexo #创建一个文件夹 cd hexo #切换到hexo目录下面 npm install -g hexo-cli npm install hexo --save 然后 ...

  4. 爬虫浅谈一:一个简单c#爬虫程序

    这篇文章只是简单展示一个基于HTTP请求如何抓取数据的文章,如觉得简单的朋友,后续我们再慢慢深入研究探讨. 图1: 如图1,我们工作过程中,无论平台网站还是企业官网,总少不了新闻展示.如某天产品经理跟 ...

  5. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  6. 在Openfire上弄一个简单的推送系统

    推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...

  7. ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面

    前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...

  8. 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库

    57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...

  9. 如何开发一个简单的HTML5 Canvas 小游戏

    原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...

随机推荐

  1. Linux相关安装文档

    一.JDK环境安装 1.查看linux上是否存在已安装好的JDK (1)java -version openjdk version "1.8.0_181"OpenJDK Runti ...

  2. MySQL数据库安装步骤

    目录 MySQL数据库安装 MySQL数据库安装 MySQL Windows下载地址:https://dev.mysql.com/downloads 我们这里选择5.6.45版本下载,下载zip. 点 ...

  3. VScode 插件推荐与C/C++配置

    以下是我经常用到的VScode插件.由于插件本身具有详细的配置和介绍,不对插件本身的安装配置进行说明,仅仅支出这些插件的主要功能.具体使用强烈推荐看一下安装插件后的说明,大多数的问题和设置都可以找到, ...

  4. 代码解读 | VINS 视觉前端

    本文作者是计算机视觉life公众号成员蔡量力,由于格式问题部分内容显示可能有问题,更好的阅读体验,请查看原文链接:代码解读 | VINS 视觉前端 vins前端概述 在搞清楚VINS前端之前,首先要搞 ...

  5. c# timestamp转换datetime

    一.Codes class Program { static void Main(string[] args) { ); } public static DateTime UnixTimeStampT ...

  6. net core天马行空系列: 泛型仓储和声明式事物实现最优雅的crud操作

    系列目录 1.net core天马行空系列:原生DI+AOP实现spring boot注解式编程 哈哈哈哈,大家好,我就是那个高产似母猪的三合,长久以来,我一直在思考,如何才能实现高效而简洁的仓储模式 ...

  7. Keras 实例 MNIST

    import numpy from keras.datasets import mnist from keras.models import Sequential from keras.layers ...

  8. HDU - 3416-Marriage Match IV (最大流 + 最短路)

    HDU - 3416:http://acm.hdu.edu.cn/showproblem.php?pid=3416 参考:https://www.cnblogs.com/kuangbin/archiv ...

  9. HDU3652:B-number(数位DP)

    Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal for ...

  10. Heron and His Triangle 2017 沈阳区域赛

    A triangle is a Heron’s triangle if it satisfies that the side lengths of it are consecutive integer ...