一.什么是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值
代码如下:
代码语言:javascript复制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);
}
}