zl程序教程

您现在的位置是:首页 >  后端

当前栏目

java记录项目的UV值与PV值

JAVA项目 记录 pv UV
2023-06-13 09:16:12 时间

一.什么是UV什么是PV

PV(访问量):Page View, 即页面浏览量或点击量,用户每次访问即被计算一次。 UV(独立访客):Unique Visitor,访问您网站的一台电脑客户端为一个访客。00:00-24:00内相同的客户端只会被计算一次。

二.为什么需要记录UV与PV

记录uv与pv可以更加直观的看到项目的访问量与用户的分布

三.怎么用java来实现UV与PV的记录

我的方式是通过过滤器的形式来获取到用户当前的真实ip,然后将ip+自己的写的rediskey一起存放进Reids里面,存入redis的有效期为当前时间离当天23:59:59的时间差(秒),这就是一个UV量,下次再请求的时候,通过ip从redis里面取值,如果取到了值,就证明该UV已记录,否则的话就是一个新的UV值

代码如下:

import com.jieyihua.common.core.constant.RedisConstant;
import com.jieyihua.common.core.utils.HttpUtils;
import com.jieyihua.common.core.utils.LocalDateTimeUtils;
import com.jieyihua.common.core.utils.StringUtils;
import com.jieyihua.common.redis.service.RedisService;
import com.jieyihua.system.api.RemoteStatisticsChannelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author LiYu
 * @version 3.0
 * @description: APP端鉴权过滤器
 * @date 2021/7/23 10:50
 */
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "appWebFilter")
@RequiredArgsConstructor
public class AppWebFilter implements Filter {
    private final RemoteStatisticsChannelService remoteStatisticsChannelService;
    private final RedisService redisService;
    /**
     * 开放接口
     */
    private static final String[] OPEN_INTERFACE = {
            "/open/",
    };

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //判断该请求是否拦截
        AtomicBoolean whetherToIntercept = new AtomicBoolean(true);
        //判断是否为开放接口
        Arrays.asList(OPEN_INTERFACE).forEach(val -> {
            if (request.getRequestURI().contains(val)) {
                whetherToIntercept.set(false);
            }
        });
        //不是开放接口 判断用户是否登陆
        if (whetherToIntercept.get()) {
            //获取请求token
            String token = request.getHeader("Authorization");
            //获取客户ID
            String customerId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token) + "";
            //双向绑定获取token
            String originalToken = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
            //获取客户名
            String username = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_USERNAME_KEY + token) + "";
            //获取渠道ID
            Long channelId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token);
            //没有登陆
            if (StringUtils.isEmpty(token)) {
                throwOut("请先登录!", servletRequest, servletResponse);
            } else if (StringUtils.isEmpty(customerId) || StringUtils.isEmpty(originalToken) || !originalToken.equals(token) || !StringUtils.hasText(username)) {
                //在其他设备登陆了或者登陆过期了
                throwOut("登录已过期或者在其他设备登录!", servletRequest, servletResponse);
            } else {
                //刷新缓存时间
                redisService.moreUserCache(username, Long.parseLong(customerId), token,channelId);
                //记录UV PV
                //获取到用户的真实IP
                String ip = HttpUtils.getIpAddress(request);
                if(redisService.getCacheObject(RedisConstant.SYS_CUSTOMER_ONLY_IP+ip) == null){
                    //每天的凌晨00:00清除
                    redisService.setCacheObject(RedisConstant.SYS_CUSTOMER_ONLY_IP+ip,true, LocalDateTimeUtils.getTimeDifference(LocalDateTime.now(),LocalDateTimeUtils.getLocalDateTimeForEnd(LocalDateTime.now())), TimeUnit.SECONDS);
                    //增加一个UV
                    remoteStatisticsChannelService.addUv(channelId);
                }
                //增加一个pv
                remoteStatisticsChannelService.addPv(channelId);
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void throwOut(String errorMessage, ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // 将错误信息封装在request中
        request.setAttribute("errorMessage", errorMessage);
        // 请求转发
        request.getRequestDispatcher("/error/systemError").forward(servletRequest, servletResponse);
    }

}