炫酷,SpringBoot+Echarts实现用户访问地图可视化(附源码)

开发 后端
在常见的电商、新闻、社交网站等,合理运用运营成本才能最大化输出自己的产品,其中最常见的功能就有针对不同访问热度的城市制定不同的运营手段,因此我们掌握用户城市分布情况至关重要。

SpringBoot+Echarts用户访问地图可视化

意义

  •  在常见的电商、新闻、社交网站等,合理运用运营成本才能最大化输出自己的产品,其中最常见的功能就有针对不同访问热度的城市制定不同的运营手段,因此我们掌握用户城市分布情况至关重要。
  •  pc端与移动端不同,无法依托手机自带的gps定位到用户所在城市,只能通过ip来进行判断所在地理位置。

根据ip获取城市的方式

  •  淘宝、新浪等常年提供根据ip获取城市的接口,但是隔一段时间会出现接口地址更改的情况,也有一定的限流
  •  开源纯真ip库:不断迭代更新ip库内容,一般场景下足以使用,自主可控。(下载qqwry.dat库)

思路

首先需要获取用户请求的ip地址,我们对该方法进行简单封装: 

public class IPUtil {  
    public static String getIpAddress(HttpServletRequest request) {  
        String ip = request.getHeader("x-forwarded-for");  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_CLIENT_IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

封装纯真ip的解析工具,根据ip获取请求地址所在城市,github有大量实现版本,我们这里不做赘述,具体代码见文末源码 

//篇幅较长,截取的主要方法,详细在源码地址查看      
public IPZone findIP(final String ip) {  
        final long ipNum = toNumericIP(ip);  
        final QIndex idx = searchIndex(ipNum);  
        if (idx == null) {  
            return new IPZone(ip); 
         }  
        return readIP(ip, idx);  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

自定义拦截器,对用户的登录请求进行拦截,在此处判断请求ip所在城市,并进行计数。我们这里只是简单逻辑的说明,在生产上时应该用redis来存放计数,并且专门提供一个rest接口来推送当前各城市访问数量情况,再由前端配合,隔一段时间发起一次请求,例如隔一小时请求一次该rest接口,从而进行前端数据的展示。 

/**  
 * 登录拦截器  
 */  
@Slf4j  
public class MyLoginInterceptor implements HandlerInterceptor {  
    private static final String LOGIN_PATH = "/user/login" 
    private static Map<String, AtomicInteger> visitCount;  
    private static final QQWry qqWry;  
    static {  
        visitCount = new HashMap<>(31);  
        qqWry = new QQWry();  
    } 
    //展示访问数量不是精确指标,如果要做到完全正确需要使用锁,防止计数存在并发问题  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        log.info("【MyLoginInterceptor】调用了:{}", request.getRequestURI());  
        if (request.getRequestURI().equals(LOGIN_PATH)) {  
            String ipAddress = IPUtil.getIpAddress(request);  
            String province = qqWry.findIP(ipAddress).getMainInfo();  
            if (visitCount.containsKey(province)) {  
                visitCount.put(province,new AtomicInteger(visitCount.get(province).incrementAndGet()));  
            } else {  
                visitCount.put(province,new AtomicInteger());  
            }  
        }  
        return true;  
    }  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response,  
                           Object handler, ModelAndView modelAndView) throws Exception {}  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,  
                                Object handler, Exception ex){}  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

注册自定义的拦截器 

@Configuration  
public class WebMvcConfig implements WebMvcConfigurer {  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(new MyLoginInterceptor());  
    }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

登录controller模拟逻辑,注意:如果想看效果图需要自己写线程用不同的虚拟ip进行访问url,从而达到在不同城市访问接口的效果。 

@RestController("user") 
public class LoginController { 
    @GetMapping("login")  
    public String login() {  
        //登录逻辑  
        return "success";  
    }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

最终效果

前后端源码

https://github.com/Motianshi/distribute-tool  
  • 1.

 

责任编辑:庞桂玉 来源: Java知音
相关推荐

2022-09-29 11:16:21

Python数据可视化

2020-03-11 14:39:26

数据可视化地图可视化地理信息

2022-04-13 09:01:53

Echart5绘制地图

2018-03-21 12:13:47

工具数据开发

2013-10-22 10:37:47

谷歌数据可视化

2021-12-30 12:02:52

Python可视化代码

2014-01-17 10:36:39

2020-03-01 14:01:22

Echarts数据可视化图表

2019-07-26 09:19:32

数据可视化架构

2022-08-17 09:01:16

数据可视化大数据

2022-03-01 10:29:44

Kubernetes容器

2019-05-20 08:20:40

数据集数据可视化数据

2017-10-11 18:17:06

大数据数据可视化前后端

2017-10-14 13:54:26

数据可视化数据信息可视化

2021-04-19 09:00:54

Python批量下载视频下载器

2010-08-04 10:48:17

路由器

2021-03-17 08:07:56

Python可视化工具

2017-09-05 08:35:09

Python可视化地图

2017-09-01 19:49:50

Python工具地图

2021-03-18 08:11:18

PythonDash工具
点赞
收藏

51CTO技术栈公众号