<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          炫酷,Spring Boot + ECharts 實(shí)現(xiàn)用戶訪問地圖可視化(附源碼)

          共 3827字,需瀏覽 8分鐘

           ·

          2020-09-27 09:11

          原文: 

          https://www.toutiao.com/i6845433908494860804/


          意義


          • 在常見的電商、新聞、社交網(wǎng)站等,合理運(yùn)用運(yùn)營成本才能最大化輸出自己的產(chǎn)品,其中最常見的功能就有針對(duì)不同訪問熱度的城市制定不同的運(yùn)營手段,因此我們掌握用戶城市分布情況至關(guān)重要。


          • pc端與移動(dòng)端不同,無法依托手機(jī)自帶的gps定位到用戶所在城市,只能通過ip來進(jìn)行判斷所在地理位置。


          根據(jù)ip獲取城市的方式


          • 淘寶、新浪等常年提供根據(jù)ip獲取城市的接口,但是隔一段時(shí)間會(huì)出現(xiàn)接口地址更改的情況,也有一定的限流


          • 開源純真ip庫:不斷迭代更新ip庫內(nèi)容,一般場景下足以使用,自主可控。(下載qqwry.dat庫)


          思路


          首先需要獲取用戶請(qǐng)求的ip地址,我們對(duì)該方法進(jìn)行簡單封裝:

          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的解析工具,根據(jù)ip獲取請(qǐng)求地址所在城市,github有大量實(shí)現(xiàn)版本,我們這里不做贅述,具體代碼見文末源碼

          //篇幅較長,截取的主要方法,詳細(xì)在源碼地址查看    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);}

          自定義攔截器,對(duì)用戶的登錄請(qǐng)求進(jìn)行攔截,在此處判斷請(qǐng)求ip所在城市,并進(jìn)行計(jì)數(shù)。我們這里只是簡單邏輯的說明,在生產(chǎn)上時(shí)應(yīng)該用redis來存放計(jì)數(shù),并且專門提供一個(gè)rest接口來推送當(dāng)前各城市訪問數(shù)量情況,再由前端配合,隔一段時(shí)間發(fā)起一次請(qǐng)求,例如隔一小時(shí)請(qǐng)求一次該rest接口,從而進(jìn)行前端數(shù)據(jù)的展示。

          /** * 登錄攔截器 */@Slf4jpublic 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();    }
          //展示訪問數(shù)量不是精確指標(biāo),如果要做到完全正確需要使用鎖,防止計(jì)數(shù)存在并發(fā)問題 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("【MyLoginInterceptor】調(diào)用了:{}", 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){}}

          注冊(cè)自定義的攔截器

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

          登錄controller模擬邏輯,注意:如果想看效果圖需要自己寫線程用不同的虛擬ip進(jìn)行訪問url,從而達(dá)到在不同城市訪問接口的效果。

          @RestController("user")public class LoginController {
          @GetMapping("login") public String login() { //登錄邏輯 return "success"; }}

          案例源碼


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


          
           

          最后免費(fèi)給大家分享50個(gè)Java項(xiàng)目實(shí)戰(zhàn)資料,涵蓋入門、進(jìn)階各個(gè)階段學(xué)習(xí)內(nèi)容,可以說非常全面了。大部分視頻還附帶源碼,學(xué)起來還不費(fèi)勁!


          附上截圖。(下面有下載方式)。

          3d39b7fadda3a24cca5b318140bcda47.webp

          d84f9576bf348df6a448ff32ff514406.webp

          49c507efbb422dae898c28d9716b9c39.webp

          4b8f357848f7c0f593d0df6ecadb6069.webp

          551b51333f43c5ee8434479a250a3c17.webp


          項(xiàng)目領(lǐng)取方式:

          掃描下方公眾號(hào)回復(fù):50,

          可獲取下載鏈接

          ???

          ?長按上方二維碼 2 秒回復(fù)「50」即可獲取資料

          點(diǎn)贊是最大的支持 a896924fb4037777db6da3b2a316b5b6.webp

          瀏覽 60
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91豆花官网 | 靠逼在线观看 | 男人天堂99 | 性高潮视频网站 | 亚洲日本色情视频在线 |