Java实现网页浏览次数

大家好,我是孙嵓,大家经常翻看公众号文章左下角是不是有个显示了多少人阅读,那这个是怎么实现的呢,本文带你进行揭秘,当然微信研发可能用的不是我这种方式但是大同小异吗,我也是最近把这个功能放到了自己的线上项目,最近在单位太闲了自己给自己找点事干,总不能一直刷知乎吧,卷起来!!!
在这里插入图片描述

项目需求:

实现例如微信公众号左下角阅读多少次类似功能。


实现思路

结合aop,实现after方法,采用redis存储网页浏览次数,每调用一次接对redis值进行+1操作(注意这个接口只有在浏览此网页的时候有调用才行)。

其实还有另一种思路那就是通过拦截器去实现HandlerInterceptor也可以实现浏览次数,拦截一次就加1,大同小异,后续会出一个详细教程,废话少说看代码!!!
在这里插入图片描述


代码实现:

注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BrowseTimes {
    /**
     * 浏览类型(这里用的是个枚举)
     */
    String type() default BrowseTimesType.COMMON;

}

Aspect

@Aspect
@Component
@Order(2)
public class BrowseTimeAspect {
    @Autowired
    RedisService redisService;
    @Autowired
    TokenService tokenService;
    @Autowired
    IPositionService positionService;

    private static Logger logger = LoggerFactory.getLogger(BrowseTimeAspect.class);

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.fuwai.hr.common.annotation.BrowseTimes)")
    public void checkPoint() {
    }
    /**
     * 环绕获取请求参数
     *
     * @param joinPoint
     * @return
     */
    @After("checkPoint()")
    public void afterMethod(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取被代理的方法
        Method method = signature.getMethod();
        //获取方法上的注解
        BrowseTimes browseTimes = method.getAnnotation(BrowseTimes.class);
        //获取方法的参数
        Object[] args = joinPoint.getArgs()
        //获取注解类型;业务上目前就这一种类型所以就没有分情况讨论
        StringBuilder type = new StringBuilder(browseTimes.type());
        //拼装redis的key,由于方法参数就这一个我就直接这么写了,这个参数是个id后边代码会写到
        type.append(args[0]);
        redisService.judgeBrowseTimes(type.toString());
    }
}

判断浏览次数是否达到最大值方法

public synchronized void judgeBrowseTimes(String key) {
    //获取key值,值为null插入值
    String value = redisCache.getCacheObject(key);
    if (StringUtils.isEmpty(value)) {
        //不存在更新,存在不进行操作
        redisCache.setIfAbsent(key, "1");
        return;
    }
    Integer intValue = Integer.parseInt(value) + 1;
    //存在即更新,不存在不进行操作;
    redisCache.setIfPresent(key, String.valueOf(intValue));
}

最后将其挂载到方法上即可

@GetMapping(value = "/test")
@BrowseTimes(type = BrowseTimesType.TEST)
public AjaxResult test(@RequestParam("testId") String testId)
{
    return testService.test(testId);
}

存在的问题及如何改进:

  1. 我定义了BrowseTimesType这个枚举按道理说应该支持多种类型的浏览次数,因为不同种类的业务逻辑可能不同需要单独处理扩充,用switch
    case显得太臃肿这里可以考虑策略或者简易的模板方法设计模式去设计,增强代码的延展性和可维护性。
  2. 我的redis的key存活时间都设置了永久,那是我业务有些操作会把这个key给删掉的所以我就没加过期时间。其实正确的方法是应该将redis设置过期时间,可以写个定时任务将这些数据存到数据库中,如果redis不存在了就去查库,重新放入redis添加过期时间,写一段伪代码吧,当然如果你的用户访问量很多的话建议防止一下缓存穿透、击穿,雪崩啊等等。
if(ObjectUtil.isEmpty(redisCache.getKey(key))){
  //查库
  String num = sqlService.selectBrowseTime(key);
  //设置了七天
  redisCache.setIfAbsent(key, num , 7, TimeUnit.DAYS);
}
  1. 并发问题 其实判断浏览次数的方法是有并发问题的这里我分两种情况讨论
    单体应用
    直接在方法上加synchronized关键字;或者采用ReentrantLock在方法一开始进行lock操作,最后别忘了unlock
    分布式应用
    这里建议采用分布式锁,可以引入redisson,操作同ReentrantLock类似都是lock和unlock这里不做过多介绍,有兴趣的可以看一下

以上就是本文的全部内容了,能力有限,理性对待

如果感觉还不错的话,欢迎点赞和关注🦋

分享经验,贴近项目,crud永不为奴!!!


欢迎大家关注我的公众号,公众号也会实时发布Java项目相关的文章!!!

在这里插入图片描述


在这里插入图片描述
1.一文搭建本地git服务器

2.Java实现短信验证码


  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙嵓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值