Springboot 使用redis检测浏览量,评论量,点赞量的变化并完成与mysql的交互(有具体实现,有具体需求)

news2025/1/12 1:35:47

  

目录

依赖

准备实体类与业务类

开始正题

实现一览

流程一览

具体实现

1 初始化

2 写浏览量增加的方法

3 在切面处检测浏览器变化

4 新增文章时将新的数据写入redis

5  删除文章时将数据从Redis中删除

6 书写将数据写入mysql数据库的方法

7 销毁的时候将数据写入mySQL数据库

8 评论量增加操作

9 其他操作

大部分工具类如下


开始补文章喽,哈哈

依赖

废话说完先引入依赖

<!--        对象转json-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
<!--        Redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
<!--        AOP-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

准备实体类与业务类

依依赖引完之后一般咱还要有一个实体类可根据自己项目选择哦

实体类

package com.scm.myblog.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Timestamp;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Article {
    @TableField(exist = false,select = false)
    private List<Category> category;
    @TableId(type = IdType.AUTO)
    private Long articleId;
    private long articleUserId;
    private String articleTitle;
    private String articleContent;
    private long articleViewCount;
    private long articleCommentCount;
    private long articleDianzanCount;
    @TableField(fill = FieldFill.UPDATE)
    private Timestamp articleUpdateTime;
    @TableField(fill = FieldFill.INSERT)
    private Timestamp articleCreateTime;
    private String articleSummary;
    private String articleThImg;

}

这个俗称业务类哟里面封装与业务相关的属性

Bo类

package com.scm.myblog.bo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DPLDataBo {
    private Long articleId;
    private Long articleViewCount;
    private Long articleCommentCount;
    private Long articleDianzanCount;
}

开始正题

然后这些准备工作做完之后,我们就开始对redis进行一些封装使其能够实现这么些功能呢

实现一览

1        浏览量增加

2        评论量增加

3        点赞量增加与减少

4        新增文章时将新的数据写入redis

5        删除文章时将数据从Redis中删除

6        还有redis初始化的时候从mysql中读取数据

7        销毁的时候将数据写入mySQL数据库,或者隔一段时间将数据写入数据库

流程一览

 OK我们捋一下大致的流程

首先呢是spring boot容器启动的时候我们需要将数据从数据库中读取到radis中

之后当用户浏览数据的时候我们对redis数据库中的浏览量进行加1的操作

同理我们对点赞量和评论量和评论量也进行相应的处理

 OK咱别急一步一步来首先说初始化.

具体实现

1 初始化

初始化的思路也很简单,首先要设置一个标记量在redis中用于标志redis是否已经被初始化了.

我这边使用的是一个字段名叫isInit,当他的值为一时表示已经初始化了值为零时表示没有初始化。   OK准备工作已做完接下来就从数据库中取出对应的数据就行了,这里我们选用的redis数据结构是list其中以数据库中的 id作为key,其他参数作为值。于是就有了以下的代码


    //初始化redis 点赞收藏评论人数
    public static void init_Redis() {
        String s = rt.opsForValue().get("isInit");
        if (!Objects.equals(s, "1")) {
            //从数据库拿到所有的点赞数据
            List<DPLDataBo> aLlDataBo = UserBlogBo.getALlDataBoFromDb();
            //放入redis,其中id为key,其他数据为值
            for (DPLDataBo d : aLlDataBo) {
                rt.opsForList().leftPushAll(
                        d.getArticleId().toString(),
                        d.getArticleViewCount().toString(),
                        d.getArticleDianzanCount().toString(),
                        d.getArticleCommentCount().toString());
            }
            //标记是否已经初始化
            rt.opsForValue().set("isInit", "1");
        }
    }

2 写浏览量增加的方法

方法接受一个文章的标题或者是文章的ID都可以我这边是用的标题。

这个方法的内容也很简单,我们就是先将中对应文章对应ID的数据中的浏览量取出来,然后对其进行加一,再把它放进去就行了。

所以对应的两个方法就是出站和入站rightpop和rightpush。

    /**
     * 添加浏览量
     *
     * @param title 标题
     */
    public static void addViewCount(String title) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            assert id != null;
            String s = rt.opsForList().rightPop(id.toString());
            assert s != null;
            long oldViewCount = (Long.parseLong(s));
            rt.opsForList().rightPush(String.valueOf(id), String.valueOf((oldViewCount + 1L)));
        }
    }

3 在切面处检测浏览器变化

你你如果嫌麻烦的话可以不使用前面直接在对应的文章详情控制器那里调用 redis中浏览量增加的方法即可。

        使用切面有使用切面的好处,它能够不干涉其他的逻辑代码,从而对数据实现监控,操作我这边使用的切面,然后切面通过截取指定方法接收的参数获取接收参数中的文章的标题,然后将文章的标题传入我们刚刚写好的浏览量增加的方法中,从而实现对文章浏览量增加的操作。

package com.scm.myblog.aop;

import com.scm.myblog.bo.UserBlogBo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * web数据记录AOP
 *
 * @author Lancer
 * @date 2022/12/09
 */
@Aspect
@Component
@Slf4j
public class WebDataRecordAspect {
    @Autowired
    public RedisTemplate<String,String> rs;

    /**
     * web日志切入点
     */
    @Pointcut("execution(public * com.scm.myblog.controller.ArticleController.getArticleDetail(..))")
    public void WebLogPointcut() {}

    /**
     * 方法调用前
     *
     * @param j j
     */
    @Before("WebLogPointcut()")
    public void doAfterData(JoinPoint j){
        String sendTitle="";
        Object[] args = j.getArgs();
        if (args != null) {
            sendTitle=(String)args[0];
        }
        UserBlogBo.addViewCount(sendTitle);
        log.info(sendTitle+"浏览加1");
    }
}

4 新增文章时将新的数据写入redis

当增加文章的时候,我们需要将新增的文章数据加入到数据库中,所以这里也比较简单,我们通过一个工具类来实现一下,加入数据的时候,还是以插入数据的ID为key,其他数据为值数据结构还是使用列表将其存入即可。


    /**
     * 新增数据到redis,
     *
     * @param title 标题
     */
    public static void addDataToRedis(String title) {
        DPLDataBo d = UserBlogBo.getSingDataBoFormDb(UserBlogBo.getIdByTitle(title));
        rt.opsForList().leftPushAll(
                d.getArticleId().toString(),
                d.getArticleViewCount().toString(),
                d.getArticleDianzanCount().toString(),
                d.getArticleCommentCount().toString());
    }

5  删除文章时将数据从Redis中删除

删除的思路和增加正好相反,我们首先通过传过来的标题获取到文章的ID,然后在中查找该ID对应的键,然后我们将此键删除即可。

    /**
     * 删除数据在redis,
     *
     * @param id ID
     * @return {@link Boolean}
     */
    public static Boolean deleteDataToRedis(Long id) {
        return rt.delete(id.toString());
    }

6 书写将数据写入mysql数据库的方法

        要实现将数据写入数据库也是十分容易的,首先我们先判断一下当前redis是否被初始化,如果被初始化了,再从redis中读取数据,然后读取数据,我们使用的也是一个range,然后把对应的ID给他,然后后面两个参数分别为零和负一,这样就可以拿到当前key对应的所有VALUE的值了,我们将值写入数据库,也就是更新操作即可。

/*
       获取所有文章id
        */
    public static List<Long> getAllId() {
        LambdaQueryWrapper<Article> article = new LambdaQueryWrapper<>();
        article.select(Article::getArticleId);
        List<Article> articles = articleDao.selectList(article);
        List<Long> ids = new ArrayList<>();
        for (Article article1 : articles) {
            ids.add(article1.getArticleId());
        }
        return ids;
    }
    /**
     * 摧毁Redis时 写入mysql数据库
     */
    public static void destroyRedis() {
        String s = rt.opsForValue().get("isInit");
        if (Objects.equals(s, "1")) {
            //获取所有文章id
            List<Long> allId = UserBlogBo.getAllId();
            //获取所有新的数据
            for (Long id : allId) {
                List<String> data = rt.opsForList().range(id.toString(), 0, -1);
                Article article = new Article();
                article.setArticleId(id);
                assert data != null;
                article.setArticleViewCount(Long.parseLong(data.get(2)));
                article.setArticleDianzanCount(Long.parseLong(data.get(1)));
                article.setArticleCommentCount(Long.parseLong(data.get(0)));
                articleDao.updateById(article);
            }
        }
        else {
            throw new SystemException(Code.InsertMySQLFromRedis_ERR, Tips.InsertMySQLFromRedis_ERR);
        }
    }

7 销毁的时候将数据写入mySQL数据库

        要实现销毁的时候,将数据写入mysql数据库,我们就要用到监听,我们需要监听什么呢?我们需要监听spring boot容器在什么时候销毁?也就是监听servlet的销毁时期,于是我们先新建一个监听类,用于监听一些操作。然后当销毁的时候调用对应的写入方法即可

package com.scm.myblog.listener;

import com.scm.myblog.bo.DPLDataBo;
import com.scm.myblog.bo.UserBlogBo;
import org.springframework.context.annotation.Configuration;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@Configuration
@WebListener()
public class MyServletContextListener implements ServletContextListener {

    /**
     * servlet销毁
     *
     * @param sce 
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce)
    {
        UserBlogBo.destroyRedis();
        System.out.println("Servlet被销毁了,数据写入数据库");
    }
}

8 评论量增加操作

        评论量的增加操作与浏览量的增加操作类似,也就是后台在写入评论时,将用一次使用量增加的方法实现将数据写入redis中,至于怎么实现将数据写入中,相信大家都非常熟悉的这边直接贴代码。

    /**
     * 评论量增加
     *
     * @param title 标题
     */
    public static void addCommentCount(String title) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            String s = rt.opsForList().index(id.toString(), 0);
            assert s != null;
            long oldCommentCount = (Long.parseLong(s));
            rt.opsForList().set(String.valueOf(id), 0, String.valueOf((oldCommentCount + 1L)));
        }
    }

9 其他操作

        至此,大致的思路,大家应该都已经理解了,可以自己完善评论量,减少点赞量,增加点赞量,减少的操作,有需要注意的是点赞量,因为它不仅可以增加,还可以减少,可能会遇到一些坑,这边先贴出来代码,我们直接设置点赞量,而不是使用加一的操作。

        方法接收两个参数,一个是当前最点赞文章的标题,一个是当前的点赞量,比如原来的点赞量是13,通过前台减一之后变成12,所以我们获取了当前点赞量就是12,我们只需要把这个12通过文章的标题对redis中的点赞数据进行一个修改即可,不需要读出来,再加一或读出来再减一。

    /**
     * 设置点赞数
     *
     * @param title    标题
     * @param newCount 
     */
    public static void setDianZanCount(String title, Integer newCount) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            assert id != null;
            String s = rt.opsForList().index(id.toString(), 1);
            assert s != null;
            rt.opsForList().set(String.valueOf(id), 1, String.valueOf(newCount));
        }
    }

大部分工具类如下

工具类

package com.scm.myblog.bo;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.scm.myblog.dao.ArticleCategoryRefDao;
import com.scm.myblog.dao.ArticleDao;
import com.scm.myblog.dao.CategoryDao;
import com.scm.myblog.entity.*;
import com.scm.myblog.entity.DTO.PageDto;
import com.scm.myblog.entity.VO.PageData;
import com.scm.myblog.exception.SystemException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class UserBlogBo {
    private static ArticleCategoryRefDao categoryRefDao;
    private static CategoryDao categoryDao;
    private static ArticleDao articleDao;
    private static RedisTemplate<String, String> rt;

    @Autowired
    private ArticleCategoryRefDao categoryRefDaoA;
    @Autowired
    private CategoryDao categoryDaoA;
    @Autowired
    private ArticleDao articleDaoA;

    @Autowired
    public RedisTemplate<String, String> rtA;

    /**
     * 点赞量增加
     *
     * @param title 标题
     */
    public static void addDianZanCount(String title, Boolean isRever) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            String s = rt.opsForList().index(id.toString(), 1);
            assert s != null;
            long oldDianZanCount = (Long.parseLong(s));
            if (isRever) {
                rt.opsForList().set(String.valueOf(id), 1, String.valueOf((oldDianZanCount - 1L)));
            }
            else {
                rt.opsForList().set(String.valueOf(id), 1, String.valueOf((oldDianZanCount + 1L)));
            }
        }
    }

    /**
     * 评论量增加
     *
     * @param title 标题
     */
    public static void addCommentCount(String title) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            String s = rt.opsForList().index(id.toString(), 0);
            assert s != null;
            long oldCommentCount = (Long.parseLong(s));
            rt.opsForList().set(String.valueOf(id), 0, String.valueOf((oldCommentCount + 1L)));
        }
    }

    /**
     * 设置点赞数
     *
     * @param title    标题
     * @param newCount
     */
    public static void setDianZanCount(String title, Integer newCount) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            assert id != null;
            String s = rt.opsForList().index(id.toString(), 1);
            assert s != null;
            rt.opsForList().set(String.valueOf(id), 1, String.valueOf(newCount));
        }
    }

    //在进入此类中时,此方法会被优先调用
    @PostConstruct
    private void init() {
        categoryRefDao = categoryRefDaoA;
        categoryDao = categoryDaoA;
        articleDao = articleDaoA;
        rt = rtA;
    }

    //初始化redis 点赞收藏评论人数
    public static void init_Redis() {
        String s = rt.opsForValue().get("isInit");
        if (!Objects.equals(s, "1")) {
            //从数据库拿到所有的点赞数据
            List<DPLDataBo> aLlDataBo = UserBlogBo.getALlDataBoFromDb();
            //放入redis,其中id为key,其他数据为值
            for (DPLDataBo d : aLlDataBo) {
                rt.opsForList().leftPushAll(
                        d.getArticleId().toString(),
                        d.getArticleViewCount().toString(),
                        d.getArticleDianzanCount().toString(),
                        d.getArticleCommentCount().toString());
            }
            //标记是否已经初始化
            rt.opsForValue().set("isInit", "1");
        }
    }

    /**
     * 新增数据到redis,
     *
     * @param title 标题
     */
    public static void addDataToRedis(String title) {
        DPLDataBo d = UserBlogBo.getSingDataBoFormDb(UserBlogBo.getIdByTitle(title));
        rt.opsForList().leftPushAll(
                d.getArticleId().toString(),
                d.getArticleViewCount().toString(),
                d.getArticleDianzanCount().toString(),
                d.getArticleCommentCount().toString());
    }

    /**
     * 删除数据在redis,
     *
     * @param id ID
     * @return {@link Boolean}
     */
    public static Boolean deleteDataToRedis(Long id) {
        return rt.delete(id.toString());
    }

    /**
     * 从数据库获取单个点赞浏览数据
     *
     * @param id
     * @return {@link DPLDataBo}
     */
    public static DPLDataBo getSingDataBoFormDb(Long id) {
        LambdaQueryWrapper<Article> a = new LambdaQueryWrapper<>();
        a.eq(Article::getArticleId,id).select(Article::getArticleId, Article::getArticleViewCount, Article::getArticleDianzanCount, Article::getArticleCommentCount);
        Article article = articleDao.selectOne(a);
        DPLDataBo d = new DPLDataBo();
        BeanUtils.copyProperties(article, d);
        return d;
    }

    /**
     * 添加浏览量
     *
     * @param title 标题
     */
    public static void addViewCount(String title) {
        if (title != null) {
            Long id = UserBlogBo.getIdByTitle(title);
            assert id != null;
            String s = rt.opsForList().rightPop(id.toString());
            assert s != null;
            long oldViewCount = (Long.parseLong(s));
            rt.opsForList().rightPush(String.valueOf(id), String.valueOf((oldViewCount + 1L)));
        }
    }


    /**
     * 从redis 得到点赞浏览数据
     *
     * @param title 标题
     * @return {@link DPLDataBo}
     */
    public static DPLDataBo getSingleDPLDataFromRedisByTitle(String title) {
        Long id = UserBlogBo.getIdByTitle(title);
        return getSingleDPLDataFromRedisById(id);
    }

    public static DPLDataBo getSingleDPLDataFromRedisById(Long id) {
        List<String> stringList = rt.opsForList().range(id.toString(), 0, -1);
        DPLDataBo da = new DPLDataBo();
        assert stringList != null;
        da.setArticleViewCount(Long.parseLong(stringList.get(2)));
        da.setArticleDianzanCount(Long.parseLong(stringList.get(1)));
        da.setArticleCommentCount(Long.parseLong(stringList.get(0)));
        return da;
    }

    /**
     * 从redis中获取所有的点赞数据
     *
     * @return {@link DPLDataBo}
     */
    public static List<DPLDataBo> getAllDPLDataFromRedis() {
        //匹配4位的id
        Set<String> keys = rt.keys("????");
        List<DPLDataBo> list = new ArrayList<>();
        assert keys != null;
        for (String key : keys) {
            List<String> range = rt.opsForList().range(key, 0, -1);
            DPLDataBo d = new DPLDataBo();
            d.setArticleId(Long.parseLong(key));
            assert range != null;
            d.setArticleViewCount(Long.parseLong(range.get(2)));
            d.setArticleDianzanCount(Long.parseLong(range.get(1)));
            d.setArticleCommentCount(Long.parseLong(range.get(0)));
            list.add(d);
        }
        return list;
    }

    /**
     * 摧毁Redis时 写入mysql数据库
     */
    public static void destroyRedis() {
        String s = rt.opsForValue().get("isInit");
        if (Objects.equals(s, "1")) {
            //获取所有文章id
            List<Long> allId = UserBlogBo.getAllId();
            //获取所有新的数据
            for (Long id : allId) {
                List<String> data = rt.opsForList().range(id.toString(), 0, -1);
                Article article = new Article();
                article.setArticleId(id);
                assert data != null;
                article.setArticleViewCount(Long.parseLong(data.get(2)));
                article.setArticleDianzanCount(Long.parseLong(data.get(1)));
                article.setArticleCommentCount(Long.parseLong(data.get(0)));
                articleDao.updateById(article);
            }
        }
        else {
            throw new SystemException(Code.InsertMySQLFromRedis_ERR, Tips.InsertMySQLFromRedis_ERR);
        }
    }


    /*
    通过标题获取id
     */
    public static Long getIdByTitle(String title) {
        try {

            LambdaQueryWrapper<Article> article = new LambdaQueryWrapper<>();
            article.eq(Article::getArticleTitle, title);
            return articleDao.selectOne(article).getArticleId();
        } catch (Exception e) {
            return null;
        }
    }

    /*
       获取所有文章id
        */
    public static List<Long> getAllId() {
        LambdaQueryWrapper<Article> article = new LambdaQueryWrapper<>();
        article.select(Article::getArticleId);
        List<Article> articles = articleDao.selectList(article);
        List<Long> ids = new ArrayList<>();
        for (Article article1 : articles) {
            ids.add(article1.getArticleId());
        }
        return ids;
    }

    public static void updateAllLDPData(Article article) {
        articleDao.updateById(article);
    }

    /*
    获取多篇文章标签,传入参数为List<>
     */
    public static List<Article> getManyArticleTaggersByIdOrTitle(List<Article> records) {
        for (Article article : records) {
            getSingleArticleTaggersByIdOrTitle(article);
        }
        return records;
    }

    /**
     * 从redis获取,浏览量从大到小排序后的id值
     *
     * @return {@link Long}
     */
    public static List<Long> getMaxViewCountFromRedis() {
        List<DPLDataBo> data = getAllDPLDataFromRedis();
        List<DPLDataBo> boList = data.stream().sorted(Comparator.comparing(DPLDataBo::getArticleViewCount).reversed()).collect(Collectors.toList());
        List<Long> x = new ArrayList<>();
        for (DPLDataBo dp : boList) {
            x.add(dp.getArticleId());
        }
        return x;
    }

    /*
    传入一个article对象,将自动设置对象的标签值
     */
    public static Article getSingleArticleTaggersByIdOrTitle(Article article) {
        //联两个表查询文章标签
        LambdaQueryWrapper<ArticleCategoryRef> articleCategoryRef = new LambdaQueryWrapper<>();
        //根据标题查找id 获取标签id
        Long id = null;
        if (article.getArticleId() != null) {
            id = article.getArticleId();
        }
        else {
            id = UserBlogBo.getIdByTitle(article.getArticleTitle());
        }
        articleCategoryRef = articleCategoryRef.eq(ArticleCategoryRef::getArticleId, id);
        List<ArticleCategoryRef> refs = categoryRefDao.selectList(articleCategoryRef);

        List<Category> tagsData = new ArrayList<>();
        for (ArticleCategoryRef rs : refs) {
            //获取每一个标签
            LambdaQueryWrapper<Category> categoryQueryWrapper = new LambdaQueryWrapper<>();
            categoryQueryWrapper.eq(Category::getCategoryId, rs.getCategoryId());
            Category category = categoryDao.selectOne(categoryQueryWrapper);
            //将每一个标签对象放入List tag中
            tagsData.add(category);
            //再将所有相关的标签对象放入List Arcticle中
            article.setCategory(tagsData);
        }
        return article;
    }


    /**
     * 设置默认分页查询
     *
     * @param pto 美国专利商标局
     */
    public static void setDefaultPage(PageDto pto) {
        if (pto.getCurrPage() == null) {
            pto.setCurrPage(1);
        }
        if (pto.getPageSize() == null) {
            pto.setPageSize(10);
        }
    }

    /**
     * 从数据得到所有数据波
     *
     * @return {@link List}<{@link DPLDataBo}>
     */
    public static List<DPLDataBo> getALlDataBoFromDb() {
        LambdaQueryWrapper<Article> s = new LambdaQueryWrapper<>();
        s.select(Article::getArticleId, Article::getArticleViewCount, Article::getArticleDianzanCount, Article::getArticleCommentCount);
        List<Article> articleList = articleDao.selectList(s);
        List<DPLDataBo> d = new ArrayList<>();
        for (Article article : articleList) {
            DPLDataBo p = new DPLDataBo();
            BeanUtils.copyProperties(article, p);
            d.add(p);
        }
        return d;
    }

    /**
     * 通过标签获取文章列表
     *
     * @param tag1    标签1
     * @param isAdmin 是否是管理
     * @return {@link List}<{@link Article}>
     */
    public static List<Article> getArticleListByTag(String tag1, Boolean isAdmin) {
        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Category::getCategoryName, tag1);
        Long tagId = categoryDao.selectOne(queryWrapper).getCategoryId();
        LambdaQueryWrapper<ArticleCategoryRef> c = new LambdaQueryWrapper<>();
        c.eq(ArticleCategoryRef::getCategoryId, tagId);
        List<ArticleCategoryRef> refs = categoryRefDao.selectList(c);
        List<Long> ids = new ArrayList<>();
        for (ArticleCategoryRef o : refs) {
            ids.add(o.getArticleId());
        }
        List<Article> articles = articleDao.selectBatchIds(ids);
        getManyArticleTaggersByIdOrTitle(articles);
        if (!isAdmin) {
            for (Article o : articles) {
                o.setArticleUserId(null);
                o.setArticleId(null);
                o.setArticleContent(null);
            }
        }
        return articles;
    }
}

AOP

package com.scm.myblog.aop;

import com.scm.myblog.bo.UserBlogBo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * web数据记录AOP
 *
 * @author 孙超孟
 * @date 2022/12/09
 */
@Aspect
@Component
@Slf4j
public class WebDataRecordAspect {
    @Autowired
    public RedisTemplate<String,String> rs;

    /**
     * web日志切入点
     */
    @Pointcut("execution(public * com.scm.myblog.controller.ArticleController.getArticleDetail(..))")
    public void WebLogPointcut() {}

    /**
     * 方法调用前
     *
     * @param j j
     */
    @Before("WebLogPointcut()")
    public void doAfterData(JoinPoint j){
        ServletRequestAttributes s=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert s != null;
        HttpServletRequest request = s.getRequest();
        String sendTitle="";
        Object[] args = j.getArgs();
        if (args != null) {
            sendTitle=(String)args[0];
        }
        UserBlogBo.addViewCount(sendTitle);
        log.info(sendTitle+"浏览加1");
    }
}

springboot启动类

package com.scm.myblog;

import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory;
import com.scm.myblog.bo.UserBlogBo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
/*
                                MMMMM
                                  MMMMMM
                                    MMMMMMM
                                     MMMMMMMM     .
                                      MMMMMMMMM
                                      HMMMMMMMMMM
                                       MMMMMMMMMMMM  M
                                       MMMMMMMMMMMMM  M
                                        MMMMMMMMMMMMM  M
                                        MMMMMMMMMMMMM:
                                        oMMMMMMMMMMMMMM
              .MMMMMMMMMMMMMMo           MMMMMMMMMMMMMMM M
        MMMMMMMMMMMMMMMMMMMMMMMMMMM      MMMMMMMMMMMMMMMM
          MMMMMMMMMMMMMMMMMMMMMMMMMMMM.  oMMMMMMMMMMMMMMM.M
            MMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMM
              MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                oMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                    MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM:                     H
                     MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM                  .         MMM
                      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM              M       MMMMMM
                       .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM          M   MMMMMMMMMM
                MM.      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM       M MMMMMMMMMMMM
                    MM    MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM    .MMMMMMMMMMMMMM
                      MM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                        MM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
               .MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMM.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                  HMMMMMMMMMMMMMMMMMMMMM.MMMMMMMMM.MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                     MMMMMMMMMMMMMMM MMM.oMMMMMMM..MMMMMMMMM:MMMMMMMMMMMMMMMMMMMMMMM
                       MMMMMMMMMMMMMM MM..MMMMMMM...MMMMMMM. MMMMMMMMMMMMMMMMMMMMM
                         MMMMMMMMMMMMMMM ..MMMMMM...MMMMMM ..MMMMMMMMMMMMMMMMMMM
                          MMMMMMM:M.MMM.M.. MMMMM M..MMMMM...MMMMMMMMMMMMMMMMMM  MMM
                            MMMM. .M..MM.M...MMMMMM..MMMMM.. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM .
                             MMMM..M....M.....:MMM .MMMMMM..MMMMMMM...MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
                              MMM.M.. ...M......MM.MMMMM.......MHM.M  .MMMMMMMMMMMMMMMMMMMMMMMMM
                         MMMMMMMM..MM. . MMM.....MMMMMM.M.....M ..MM..M MMMMMMMMMMMMMMMMMMM
                            .MMMMMHMM. ..MMMM. MMM............o..... . .MMMMMMMMMMMMMMM
                               MMM. M... .........................M..:.MMMMMMMMMMMM
                                 oMMM............ .................M.M.MMMMMMMMM
                                    .....MM........................ . MMMMMM
                                   M.....M.....................o.MM.MMMMMMMM.
                                    M........................M.. ...MMMMMMMMMMMMMo
                                      :....MMM..............MMM..oMMMMMMM
                                       M...MMM.............MMMMMMM
                                          .............:MMMMMMMM
                                          M..... MMM.....M
                                          M M.............
                                          ................M
                                       ooM.................MM  MoMMMMMoooM
                                  MMoooM......................MoooooooH..oMM
                              MHooooMoM.....................MMooooooM........M
                            oooooooMoooM......... o........MoooooooM............
                            Mooooooooooo.......M.........Moooooooo:..............M
                           MooMoooooooooM...M........:Mooooooooooo:..............M
                          M..oooooooooooo .........Mooooooooooooooo..............M
                         M...Mooo:oooooooo.M....ooooooooooooooooooo..M...........M
                          ...oooooMoooooooM..Mooooooooooooo:oooooooM.M...........M.
                         M...ooooooMoo:ooooMoooooooooooooHoooooooooH:M. ...........:
                         M..MoooooooMoooooooooooooooooo:ooooooMooooMoM..............M
                         M..ooooooooooMooooooooooooooHoooooooMooHooooM...............M
                         ...ooooooooooooooooooo:MooooooooooooooMoMoooM................
                        M...oooooooooooooooooooooooooooooooooooooMooMM................M
                        ...MooooooooooooooooooooooooooooooooooooooooMo ................
                        ...MooooooooooooooooooooooooooooooooooooooooM M................M
                       M...ooooooooooooooooooooooooooooooooooooooooM   ................M
                       ...MoooooooooooooooooooooooooooooooooooooooMM   .:...............
                       .....MooooooooooooooooooooooooooooooooooooMoo       .............M
                       M...... ooooooooooooooooooooooooooooooooooooM       M..............M
                       M........MooooMMM MM MM  MMMMMMMMMooooooooM         M...............M
                       .........HM     M:  MM :MMMMMM          M           M...............
                      M..........M     M   MoM M                           M................M
                      M.........:M  MoH  M M M MooooHoooMM.   M             M...............M
                      M..........Moooo MMooM    oooooMooooooooM              M..............H
                      M.........MooooM  Mooo  : ooooooMooooMoooM              M........ . .o.M
                      H..  .....ooooo   oooo  M MooooooooooooooM               M... MMMMMMMMMMM
                      MMMMMMMMMMooooM M oooo  .  ooooooMooooooooM              .MMMMMMMMMMMMMMM
                      MMMMMMMMMMooooH : ooooH    oooooooooooooooo               MMMMMMMMMMMMMMM
                      MMMMMMMMMMoooo    ooooM    Moooooooooooooooo              .MMMMMMMMMMMMMMM
                      MMMMMMMMMMoooo    ooooM    MooooooooooooooooM              MMMMMMMMMMMMMMM
                      MMMMMMMMMMoooM    ooooM     ooooooooooooooooo               MMMMMMMMMMM:M
                      MMMMMMMMMMoooM   MooooM     oooooooooooMoooooo               MH...........
                       . ......Mooo.   MooooM     oooooooooooooooooo              M............M
                      M.M......oooo    MooooM     Moooooooooooooooooo:           .........M.....
                      M.M.....Moooo    MooooM      ooooooooooooooooooM            .M............
                      .......MooooH    MooooM      oooooooooMoooooooooo          M..o...M..o....M
                      .o....HMooooM    MooooH      MooooooooMooooooooooM          .:M...M.......M
                     M..M.....MoooM    :oooo:    .MooooooooHooMoooooooooM         M M... ..oM.M
                      M...M.:.Mooo. MMMMooooo   oooooooooooMoooooooooooooM          ....M. M
                       M:M..o.Moooooooooooooo MooooooooooooooMooooooooooooM          .Mo
                              MooooooooooooooMooooooooooooMoMoooooooooooooo
                              Mooooooooooooooo:ooooooooooooooooooooooooooooo
                              ooooooooooooooooMooooooooooMoooooooooooooooooo
                              ooooooooooooooooMoooooooooooMooooooooooooooooHo
                              ooMooooooooooooooMoooooooooooooooooooooooooooMoM
                             MooMoooooooooooooo.ooooooooooooooooooooooooooo:oM
                             MoooooooooooooooooooooooooooooooooooooooooooooooM
                             MoooMooooooooooooooMooooooooooooooooooooooooooooo.
                             MoooMooooooooooooooMoooooooooooooooooooooooooMooooM
                             MooooooooooooooooooMoooooooooooooooooooooooooMoooooM
                             MooooMoooooooooooooMoooooooooooooooooooooooooMoHooooM
                             ooooooMooooooooooooooooooooooooooooooooooooooooMoMoooM
                            MooooooooooooooooooooMooooooooooooooooooooooooooMoooooH:
                            MoooooooMooooooooooooMoooooooooooooooooooooooooooooHoooM
                            MooooooooMoooooooooooMoooooooooooooooooooooooooMoooMooooM
                            Moooooooooooooooooooooooooooooooooooooooooooooo.oooMooooo
                            MoooooooooooooooooooooooooooooooooooooooooooooMoooooooooM
                             MooooooooooooooooooooMoooooooooooooooooooooooooooooooooM
                              MooooooooooooooooooooMHooooooooooooooooooooMoooo:ooooo
                               MMooooooooooooooooooMoMHoooooooooooooooooooooooMooooo
                                MMoooooooooooooooMMooo MMooooooooooooooooooooooooooM
                                MMMoooooooooooooMooooo  oooooooooooooooooooooMooooo
                                MooMMoooooooooMoooMMoM  ooooHooooooooooooooooMooooM
                                MooooMooooooMooooMoooM  MoooooMoooooooooooooMooooo
                                ooooooMMooooooooMooooM  MoooooooooMooooooooooooooM
                                HooooooMoooooooMooooM    HoooooooHooMooooooooooooo
                                 oooMoooooooooHoooM         MoooooooooMoooooooooM
                                  HooooooooooooHM             MooooooooMMoooooooM
                                   MMMMMMMMMMMMMM                Moooooo:MooooHMM
                                    MMMMMMM: ...                  MMMMMMMMMMMMMM
                                   M............M                  MMMMMMMMM ....
                                   M.MM..........                  M.............M
                                M ..............MM                 M..............
                             MMMMM............MMMM                 ..MMMMMMMM ....M
                           MMMMMMMMMMMMMMMMMMMMMMMM               MMMMMMMMMMMMM...M
                        .MMMMMMMMMMMMMMMMMMMMMMMMMM               MMMMMMMMMMMMMMMMMM
                        MMMMMMMMMMMMMMMMMMMMMMMMM                MMMMMMMMMMMMMMMMMMM
                        :MMMMMMMMMMMMMMMMMMH                     MMMMMMMMMMMMMMMMMMM
                           By EBEN Jérôme                        MMMMMMMMMMMMMMMMMM
                                                                 MMMMMMMMMMMMMMM
                                                                  HMMMMMM

        */
@SpringBootApplication
@MapperScan("com.scm.myblog.*")
@ServletComponentScan("com.scm.myblog.filter")
public class MyBlogscmApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBlogscmApplication.class, args);
        //初始化点赞浏览数据
        UserBlogBo.init_Redis();
    }

}

监听器

package com.scm.myblog.listener;

import com.scm.myblog.bo.DPLDataBo;
import com.scm.myblog.bo.UserBlogBo;
import org.springframework.context.annotation.Configuration;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@Configuration
@WebListener()
public class MyServletContextListener implements ServletContextListener {

    /**
     * servlet销毁
     *
     * @param sce 南加州爱迪生公司
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce)
    {
        UserBlogBo.destroyRedis();
        System.out.println("Servlet被销毁了,数据写入数据库");
    }
}

END...

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文搞懂百万富翁问题

百万富翁问题1. 解决方案2. 协议描述3. 协议说明4. 协议举例两个百万富翁Alice和Bob想知道他们两个谁更富有&#xff0c;但他们都不想让对方及其他第三方知道自己财富的任何信息&#xff0c;这是由中国计算机科学家、2000年图灵奖获得者姚启智教授于1982年在论文《Protocols fo…

新手小白做跨境电商有哪些注意的地方?

近两年&#xff0c;受疫情刺激&#xff0c;线上电商出现前所未有的高速增长&#xff0c;中国品牌纷纷出海&#xff0c;跨境电商腾飞。此外&#xff0c;国内电商市场发展趋于平淡&#xff0c;市场需求不断萎缩&#xff0c;也让越来越多的大卖家和平台盯上了这块大蛋糕。不仅中小…

300左右半入耳蓝牙耳机推荐:南卡、漫步者、JBL蓝牙耳机谁值得入手?

现在的年轻人&#xff0c;出门都会随身携带的一副蓝牙耳机&#xff0c;所以很多品牌商加入其中&#xff0c;导致大多数人选购难度变大&#xff0c;很多人总是不知道哪个不知道品牌蓝牙耳机最好&#xff0c;半入耳式蓝牙耳机相比入耳式蓝牙耳机有着天然的舒适性&#xff0c;因而…

如何利用MOS管设计一个LED亮度可调电路

首先大家可以看下下面的MOS管亮度可调的演示视频 如何利用MOS管设计一个LED亮度可调电路这个电路大致电路图如下 MOS管的栅极放了一个电容&#xff0c;当按按键1的时候&#xff0c;电源通过R1给电容充电&#xff0c;&#xff0c;MOS管栅极的电压慢慢增大&#xff0c;流过MOS管的…

计算机毕业设计HTML+CSS+JavaScript——基于HTML花店购物网站项目的设计与实现

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

Essential singularity

In complex analysis, an essential singularity of a function is a “severe” singularity near which the function exhibits odd behavior. The category essential singularity is a “left-over” or default group of isolated singularities that are especially unm…

跳转指令 —— B、BL

跳转指令可以跳转到标号的下一条指令&#xff0c;本质就是修改了PC寄存器的值。&#xff08;标号并非指令&#xff0c;只是用来定位&#xff0c;相当于记录了当前位置的下一条指令的地址&#xff09; 这里的MAIN就是一个标号 MAIN: MOV R1, #1 这里的FUNC就是一个标…

实验3 路由器基本配置及路由配置

实验3 路由器基本配置及路由配置一、实验目的二、实验要求三、实验步骤&#xff0c;数据记录及处理四&#xff0e;实验总结一、实验目的 1、路由器几种模式。 2、基本的配置命令。 3、路由器各接口的配置方法。 4、会查看检测接口状态。 二、实验要求 写出自己学习使用了哪些…

Redis框架(十五):大众点评项目 共同关注方案实现?双指针筛选DB数据:Redis取交集

大众点评项目 好友关注 共同关注需求&#xff1a;好友关注 共同关注业务逻辑展示点击关注功能实现判断当前用户是否关注了此博主共同好友列表查询业务逻辑实现双指针筛选DB数据Redis取交集总结SpringCloud章节复习已经过去&#xff0c;新的章节Redis开始了&#xff0c;这个章节…

字节一面:select......for update会锁表还是锁行?

select查询语句是不会加锁的&#xff0c;但是select .......for update除了有查询的作用外&#xff0c;还会加锁呢&#xff0c;而且它是悲观锁。 那么它加的是行锁还是表锁&#xff0c;这就要看是不是用了索引/主键。 没用索引/主键的话就是表锁&#xff0c;否则就是是行锁。…

sklearn基础篇(十)-- 非负矩阵分解与t-SNE

1 非负矩阵分解(NFM) NMF(Non-negative matrix factorization)&#xff0c;即对于任意给定的一个非负矩阵V\pmb{V}VVV&#xff0c;其能够寻找到一个非负矩阵W\pmb{W}WWW和一个非负矩阵H\pmb{H}HHH&#xff0c;满足条件VW∗H\pmb{VW*H}VW∗HVW∗HVW∗H,从而将一个非负的矩阵分解…

物联网架构实例—解决Linux(Ubuntu)服务器最大TCP连接数限制

1.前言&#xff1a; 在对物联网网关进行压测的时候&#xff0c;发现在腾讯云部署网关程序&#xff0c;设备接入数量只能达到4000多个长连接&#xff0c;之后就再也无法接入终端了。 之前在阿里云部署的时候明明可以到达2万左右&#xff0c;而且腾讯云的这个服务器比阿里云的硬…

蓝桥杯嵌入式综合实验真题-联网电压测量系统设计与实现

目录 实验要求&#xff1a; 实验思路&#xff1a; 核心代码&#xff1a; &#xff08;1&#xff09;变量声明 &#xff08;2&#xff09;函数声明 &#xff08;3&#xff09;main主函数 &#xff08;4&#xff09;按键&#xff08;长按/短按&#xff09; &#xff08;5&…

K8s——Service、代理模式演示(二)

Service 演示 SVC 创建svc-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:name: myapp-deploynamespace: default spec:replicas: 3selector:matchLabels:app: myapprelease: stabeltemplate:metadata:labels:app: myapprelease: stabelenv: testspec: c…

学习UI设计有哪些figma插件

自2016年推出以来&#xff0c;Figma已发展成为市场领先者UI设计工具之一。 因为它不仅简单易用&#xff0c;功能优秀&#xff0c;而且基于云服务&#xff0c;可以实时编辑&#xff0c;节省大量手动下载或复制文件的时间。不仅如此&#xff0c;Figma还提供合作功能&#xff0c;…

一文读懂PFMEA(过程失效模式及后果分析)

PFMEA是过程失效模式及后果分析(Process Failure Mode andEffects Analysis)的英文简称&#xff0c;是由负责制造/装配的工程师/小组主要采用的一种分析技术&#xff0c;用以最大限度地保证各种潜在的失效模式及其相关的起因/机理已得到充分的考虑和论述。 名词解释&#xff1a…

springboot介绍

笔记来源于 动力节点springboot Javaconfig xml方式 在创建模块时&#xff0c;idea2022新版选择internal即可&#xff1a; pom.xml文件 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xs…

圆顶光源特点及应用——塑料包装袋、PCB板检测

照明系统是机器视觉系统较为关键的部分之一&#xff0c;机器视觉光源直接影响到图像的质量&#xff0c;进而影响到系统的性能。其重要性无论如何强调都是不过分的。好的打光设计能够使我们得到一幅好的图象&#xff0c;从而改善整个整个系统的分辨率&#xff0c;简化软件的运算…

Java JNA 调用DLL(动态连接库) 回调函数

首先准备好动态链接库dll 参考连接 visual studio 2017 创建dll文件并使用https://blog.csdn.net/miss_na/article/details/113524280 Visual Studio 2017 动态链接库(.dll)生成与使用的简明教程https://blog.csdn.net/Hide_on_Stream/article/details/109172054 jni之jni与…

【记录】U盘安装Ubuntu20.04系统

之前电脑安装的Centos7系统&#xff0c;但是在启动过程中遇到了文件异常&#xff0c;就开不了机了&#xff0c;另外貌似Centos7已经停止维护了&#xff0c;想了下&#xff0c;果断不要数据了&#xff0c;直接重装系统吧&#xff0c;这次选用的是Ubuntu 20.04【ps: 没有选择最新…