目录
依赖
准备实体类与业务类
开始正题
实现一览
流程一览
具体实现
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...