Redis高级数据类型-HyperLogLogBitmap以及使用两种数据类型完成网站数据统计

在这里插入图片描述

网站数据统计

在这里插入图片描述

定义相关的Redis Key

    /*** 单日UV*/public static String getUVKey(String date) {return PREFIX_UV+SPLIT+date;}/*** 记录区间UV* @param startData 开始日期* @param endDate 结束日期* @return*/public static String getUVkey(String startData,String endDate){return PREFIX_UV+SPLIT+startData+SPLIT+endDate;}/*** 单日活跃用户* @param date* @return*/public static String getDAUkey(String date){return PREFIX_DAU+SPLIT+date;}/*** 区间活跃用户* @param startDate 开始日期* @param endDate 结束日期* @return*/public static String getDAUKey(String startDate,String endDate){return PREFIX_DAU+SPLIT+startDate+SPLIT+endDate;}

定义DataService

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;@Service
public class DataService {@Autowiredprivate RedisTemplate redisTemplate;//定义日期格式private SimpleDateFormat df=new SimpleDateFormat("yyyyMMdd");//将指定的IP计入UVpublic void recordUV(String ip){//获取redisKeyString redisKey = RedisKeyUtil.getUVKey(df.format(new Date()));//存入ipredisTemplate.opsForHyperLogLog().add(redisKey,ip);}//统计指定日期范围内的UVpublic long calculateUV(Date start,Date end){//参数判空if(start ==null || end == null){throw new IllegalArgumentException("参数不能为空");}/*** 整理改时间范围内的key*/List<String> keyList =new ArrayList<>();//可以进行日期计算Calendar calendar = Calendar.getInstance();calendar.setTime(start);//当前日期小于结束日期while (!calendar.getTime().after(end)){String key=RedisKeyUtil.getUVKey(df.format(calendar.getTime()));keyList.add(key);calendar.add(Calendar.DATE,1);//对日期进行递加}/*** 合并数据*/String redisKey =RedisKeyUtil.getUVkey(df.format(start),df.format(end));redisTemplate.opsForHyperLogLog().union(redisKey,keyList.toArray());//返回统计结果 访问数量return redisTemplate.opsForHyperLogLog().size(redisKey);}//将指定用户计入DAUpublic void recordDAU(int userId){String redisKey =RedisKeyUtil.getDAUkey(df.format(new Date()));redisTemplate.opsForValue().setBit(redisKey,userId,true);}//统计指定日期范围内的DAU//每一天的统计结果做一个或运算public long calculateDAU(Date start,Date end){//参数判空if(start ==null || end == null){throw new IllegalArgumentException("参数不能为空");}/*** 整理改时间范围内的key*/List<byte[]> keyList =new ArrayList<>();//可以进行日期计算Calendar calendar = Calendar.getInstance();calendar.setTime(start);//当前日期小于结束日期while (!calendar.getTime().after(end)){String key=RedisKeyUtil.getDAUkey(df.format(calendar.getTime()));keyList.add(key.getBytes());calendar.add(Calendar.DATE,1);//对日期进行递加}/*** 整合进行or运算* 使用redis底层的链接调用or运算*/return (long) redisTemplate.execute(new RedisCallback() {@Overridepublic Object doInRedis(RedisConnection connection) throws DataAccessException {String redisKey = RedisKeyUtil.getDAUKey(df.format(start),df.format(end));//解释connection.bitOp(RedisStringCommands.BitOperation.OR,redisKey.getBytes(),keyList.toArray(new byte[0][0]));return connection.bitCount(redisKey.getBytes());}});}
}

定义拦截器


@Component
public class DataInterceptor implements HandlerInterceptor {@Autowiredprivate DataService dataService;@Autowiredprivate HostHolder hostHolder;//在请求之初统计数据@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception{//统计UVString ip= request.getRemoteHost();dataService.recordUV(ip);//统计DAUUser user = hostHolder.getUser();if(user!=null){dataService.recordDAU(user.getId());}return true;}
}

定义Controller

@Controller
public class DataController {@Autowiredprivate DataService dataService;/*** 统计页面的函数* @return*/@RequestMapping(path = "/data",method = {RequestMethod.GET,RequestMethod.POST})public String getDataPage(){return "/site/admin/data";}/*** 统计网站UV* @param start* @param end* @param model* @return*/@RequestMapping(path = "/data/uv",method = RequestMethod.POST)public String getUV(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start , @DateTimeFormat(pattern = "yyyy-MM-dd") Date end, Model model){long uv =dataService.calculateUV(start,end);model.addAttribute("uvResult",uv);model.addAttribute("uvStartDate",start);model.addAttribute("uvEndDate",end);//将处理结果发给/data进行另一半的处理return "forward:/data";
//        return "/site/admin/data";}@RequestMapping(path = "/data/dau",method = RequestMethod.POST)public String getDAU(@DateTimeFormat(pattern = "yyyy-MM-dd") Date start , @DateTimeFormat(pattern = "yyyy-MM-dd") Date end, Model model){long dau =dataService.calculateDAU(start,end);model.addAttribute("dauResult",dau);model.addAttribute("dauStartDate",start);model.addAttribute("dauEndDate",end);//将处理结果发给/data进行另一半的处理return "forward:/data";
//        return "/site/admin/data";}
}

添加权限

.antMatchers("/discuss/delete","/data/**")

页面示例

<div class="main"><!-- 网站UV --><div class="container pl-5 pr-5 pt-3 pb-3 mt-3"><h6 class="mt-3"><b class="square"></b> 网站 UV</h6><form class="form-inline mt-3" method="post" th:action="@{/data/uv}"><input type="date" class="form-control" required name="start" th:value="${#dates.format(uvStartDate,'yyyy-MM-dd')}"/><input type="date" class="form-control ml-3" required name="end" th:value="${#dates.format(uvEndDate,'yyyy-MM-dd')}"/><button type="submit" class="btn btn-primary ml-3">开始统计</button></form><ul class="list-group mt-3 mb-3"><li class="list-group-item d-flex justify-content-between align-items-center">统计结果<span class="badge badge-primary badge-danger font-size-14" th:text="${uvResult}">0</span></li></ul></div><!-- 活跃用户 --><div class="container pl-5 pr-5 pt-3 pb-3 mt-4"><h6 class="mt-3"><b class="square"></b> 活跃用户</h6><form class="form-inline mt-3"method="post" th:action="@{/data/dau}"><input type="date" class="form-control" required name="start" th:value="${#dates.format(dauStartDate,'yyyy-MM-dd')}"/><input type="date" class="form-control ml-3" required name="end" th:value="${#dates.format(dauEndDate,'yyyy-MM-dd')}"/><button type="submit" class="btn btn-primary ml-3">开始统计</button></form><ul class="list-group mt-3 mb-3"><li class="list-group-item d-flex justify-content-between align-items-center">统计结果<span class="badge badge-primary badge-danger font-size-14" th:text="${dauResult}">0</span></li></ul></div>				</div>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/183230.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot+AOP+自定义注解,优雅实现日志记录

文章目录 前言准备阶段1、数据库日志表2、自定义注解编写3、AOP切面类编写4、业务层4.1、Service 层&#xff1a;4.2 Service 实现层&#xff1a; 5、测试 前言 首先我们看下传统记录日志的方式是什么样的&#xff1a; DeleteMapping("/deleteUserById/{userId}") …

ARM64 linux并发与同步之原子操作

卷2&#xff1a;调试与案例分析 第一章 并发与同步 画了两张简图&#xff0c;方便理解&#xff0c;如下&#xff1a; 针对并发源的问题&#xff0c;我接触的项目中都是SMP系统&#xff0c;目前大部分也都是SMP系统&#xff1b; 对于SMP系统&#xff0c;情况会更复杂。 □ 同…

数据可视化:动态柱状图

终于来到最后一个数据可视化的文章拿啦~~~ 在这里学习如何绘制动态柱状图 我先整个活 (๑′ᴗ‵๑)&#xff29; Lᵒᵛᵉᵧₒᵤ❤ 什么是pyecharts&#xff1f; 答&#xff1a; Python的Pyecharts软件包。它是一个用于Python数据可视化和图表绘制的库&#xff0c;可用于制作…

音乐免费下载mp3格式+音频格式转换+剪辑音频+合并音频教程

1.在qq音乐网页版搜索想要的歌曲 qq音乐网站&#xff1a;https://y.qq.com/ 如果你是vip可以直接下载vip的歌曲&#xff0c;如果不是选择不是vip的歌曲进行第一步的操作 2.点击播放进入页面后F12拿到音频地址 然后双击src里面的音频地址复制 网页新标签打开赋值的这个链接&a…

SpringBoot-WebSocket浏览器-服务器双向通信

文章目录 WebSocket 介绍入门案例 WebSocket 介绍 WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并进行双向数据传输。 应用场景&#xff1a; 视…

Markdown语法教程

Markdown&#xff1a;一种轻量级语言&#xff0c;有简洁的编写方式&#xff0c;能够提高大家的工作效率。 一、标题 1.1 标题 标题的编写格式以#号开始&#xff0c;分别表示h1 ~ h6&#xff0c;注意&#xff1a;# 后面有空格&#xff01; # 一级标题 ## 二级标题 ### 三级标题…

vue2.0 打包,nginx部署

1、修改这里为空 否则报错&#xff1a;vue is undefined 2、修改为hash&#xff0c;重点&#xff1a;打包dist文件运行&#xff0c;必须这样 3、安装ngnix&#xff0c;重点&#xff1a;使用node的包&#xff1a;httpserve&#xff0c;失败 4、重点&#xff1a;配置代理转发 前端…

2024天津理工大学中环信息学院专升本机械设计制造自动化专业考纲

2024年天津理工大学中环信息学院高职升本科《机械设计制造及其自动化》专业课考试大纲《机械设计》《机械制图》 《机械设计》考试大纲 教 材&#xff1a;《机械设计》&#xff08;第十版&#xff09;&#xff0c;高等教育出版社&#xff0c;濮良贵、陈国定、吴立言主编&#…

ElementUI-tree拖拽功能与节点自定义

前言 在管理端会遇到多分类时&#xff0c;要求有层次展示出来&#xff0c;并且每个分类有额外的操作。例如&#xff1a;添加分类、编辑分类、删除、拖到分类等。 下面将会记录这样的一个需求实习过程。 了解需求 分类展示按层级展示分类根据特定的参数展示可以操作的按钮&a…

四阶龙格库塔与元胞自动机

龙格库塔法参考&#xff1a; 【精选】四阶龙格库塔算法及matlab代码_四阶龙格库塔法matlab_漫道长歌行的博客-CSDN博客 龙格库塔算法 Runge Kutta Method及其Matlab代码_龙格库塔法matlab_Lzh_023016的博客-CSDN博客 元胞自动机参考&#xff1a; 元胞自动机&#xff1a;森林…

Leetcode Daily Challenge 1845. Seat Reservation Manager

1845. Seat Reservation Manager 题目要求&#xff1a;初始化一个SeatManager类包括默认构造函数和类函数&#xff0c;所有的seat初始化为true。reverse函数返回最小的true&#xff0c;然后把这个编号的椅子赋值为false。unreverse(seatNumber)函数把编号为seatNumber的椅子恢…

阿里云中的云服务器的ubuntu中的vim没有显示行号

没有行号&#xff1a; 在终端输入命令&#xff1a; vim ~/.vimrc set nu

【PC电脑windows环境下-[jetson-orin-NX]Linux环境下-下载工具esptool工具使用-相关细节-简单样例-实际操作】

【PC电脑windows环境下-[jetson-orin-NX]Linux环境下-下载工具esptool工具使用-相关细节-简单样例-实际操作】 1、概述2、实验环境3、 物品说明4-2、自我总结5、本次实验说明1、准备样例2、设置芯片3、编译4、下载5、验证 &#xff08;1&#xff09;windows环境下进行烧写1、下…

java泛型的深入 泛型还可以在很多地方进行定义 泛型类 泛型方法 泛型接口 泛型的继承和通配符 泛型类练习

文章目录 泛型的深入泛型还可以在很多地方进行定义泛型类泛型方法泛型接口 泛型的继承和通配符泛型类练习总结 泛型的深入 public static void main(String[] args) {//在没有泛型的时候怎么存储数据ArrayList listnew ArrayList();list.add(1);list.add("abc");//遍…

上海:竹云董事长董宁受邀在第三届“双区驱动,打造全球经济新引擎”国际合作论坛发言

作为中国最具活力的两大重要经济带&#xff0c;粤港澳和长三角两大湾区2022年GDP总量超过42万亿&#xff0c;占全国GDP总量的35%&#xff0c;对中国经济的重要性举足轻重。中国国际进口博览会是我国主动向世界开放市场的重大举措&#xff0c;是一个推动两地开放合作&#xff0c…

Ubuntu18.04安装pcl-1.12.1,make时报错:/usr/bin/ld: cannot find -lvtkIOMPIImage

解决方案&#xff1a; 在vtk安装包中&#xff0c;重新打开cmake-gui&#xff0c;然后勾选上VTK_Group_MPI和VTK_Group_Imaging。 cd VTK-8.2.0 cd build cmake-gui然后重新编译生成。 make -j8 # 或者j4,量力而行。 sudo make install 就可以解决了。 然后重新回到pcl安装…

V-REP和Python的联合仿真

机器人仿真软件 各类免费的的机器人仿真软件优缺点汇总_robot 仿真 软件收费么_dyannacon的博客-CSDN博客 课程地址 https://class.guyuehome.com/p/t_pc/course_pc_detail/column/p_605af87be4b007b4183a42e7 课程资料 guyueclass: 古月学院课程代码 旋转变换 旋转的左乘与…

论文阅读—— UniDetector(cvpr2023)

arxiv&#xff1a;https://arxiv.org/abs/2303.11749 github&#xff1a;https://github.com/zhenyuw16/UniDetector 一、介绍 通用目标检测旨在检测场景那种的一切目标。现有的检测器依赖于大量数据集 通用的目标检测器应该有两个能力&#xff1a;1、可以利用多种来…

数据库实验:SQL的数据视图

目录 视图概述视图的概念视图的作用 实验目的实验内容实验要求实验过程 视图概述 视图是由数据库中的一个表或多个表导出的虚拟表&#xff0c;其作用是方便用户对数据的操作 视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一…

SQL审计是什么意思?目的是什么?有什么好处?

很多刚入行的运维小伙伴对于SQL审计不是很了解&#xff0c;不知道其是什么意思&#xff1f;使用SQL审计的目的是什么&#xff1f;使用SQL审计的好处有哪些&#xff1f;这里我们大家就来一起聊聊&#xff0c;仅供参考哈&#xff01; SQL审计是什么意思&#xff1f; 【回答】&…