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

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

技术教程gslnedu2025-02-01 13:24:388A+A-

前言

意义

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

封装纯真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);
}

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

/**
 * 登录拦截器
 */
@Slf4j
public class MyLoginInterceptor implements HandlerInterceptor {
    private static final String LOGIN_PATH = "/user/login";
    private static Map 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){}
}

注册自定义的拦截器

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

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

@RestController("user")
public class LoginController {


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

最后

源码、参考文档获取方式:关注小编+转发文章+私信【555】免费获取
重要的事情说三遍,转发+转发+转发,一定要记得点赞转发哦!!!

另外整理成了40多套PDF文档:全套的Java面试宝典手册1000+pdf,

1.编程+开源框架+分布式”等七大面试专栏

2.Java核心知识点1000+Java面试题合集pdf

3.阿里、京东、蚂蚁等大厂面试真题解析

4.Spring全家桶面试题

5.算法笔记文档+刷题手册

6.思维导图(jvm、mysql、并发编程、数据库、kafka等等)。

如果你对这个感兴趣,小编可以免费分享。


重要的事情说三遍,转发+转发+转发,一定要记得点赞转发哦!!!

点击这里复制本文地址 以上内容由朽木教程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

朽木教程网 © All Rights Reserved.  蜀ICP备2024111239号-8