0
点赞
收藏
分享

微信扫一扫

Android Jetpack Compose 使用 ViewModel

科牛 2023-09-15 阅读 42

目录

1. 原始文章详情页

2. 为什么要使用并发编程升级文章详情页

3. 如何使用并发编程升级文章详情页

3.1 配置线程池

3.2 合并前端请求

3.3 合并后端接口,使用多线程并发执行

4. 项目相关链接


1. 原始文章详情页

【前端代码】

<script type="text/javascript">
var aid = getURLParam("id"); // 文章ID
var islogin = false; // 是否登录
// 初始化文章详情
var editormd;
function initEdit(md){
editormd = editormd.markdownToHTML("editorDiv", {
markdown : md,
});
}

// 初始化文章的详细信息
function initArtDetail() {
jQuery.ajax({
url:"/art/detail",
type:"GET",
data:{
"aid":aid
},
success:function(body) {
if(body.code==200 && body.data!=null && body.data.id>=0) {
// 查询成功: body 是 articleinfoVo 对象
var art = body.data;
jQuery("#title").html(art.title); // 设置文章标题
jQuery("#createtime").html(art.createtime); // 设置文章发布时间
jQuery("#rcount").html(art.rcount); // 设置文章访问量
initEdit(art.content); // 设置文章详情
if (art.photo != null && art.photo != "") {
jQuery("#photo").attr("src", art.photo); // 设置头像
}
jQuery("#username").html(art.username); // 设置昵称
jQuery("#artcount").html(art.artCount);
} else {
alert("抱歉: 操作失败, 请重试! ");
}
}
});
}

// [是否要显示评论删除按钮] - 判断当前文章是否属于当前登录用户
function isArtByMe(aid) {
jQuery.ajax({
url: "/user/isartbyme",
type: "GET",
data: {
"aid": aid
},
success: function (res) {
if (res.code == 200 && res.data == 1) {
// 当前文章归属于当前登录用户
jQuery(".comment_del_class").each(function (i) {
jQuery(this).show();
});
}
}
});
}

// 加载评论列表
function initComment() {
jQuery.ajax({
url:"/comment/list",
type:"GET",
data:{
"aid":aid
},
success:function(body) {
if(body.code==200 && body.data!=null) {
var commentListHtml = "";
for(let comment of body.data) {
commentListHtml += '<div style="margin-bottom: 26px;">';
commentListHtml += comment.username + ':' + comment.content;
commentListHtml += ' <a class="comment_del_class" style="display: none;text-decoration:none; color:grey;" href="javascript:del(' +
comment.cid + ')">删除</a>';
commentListHtml += '</div>';
}
jQuery("#commentlist").html(commentListHtml);
var commentCount = body.data.length;
jQuery("#commentCount").html('共 ' + commentCount + ' 条评论');
}
}
});
}

// 获取当前登录用户的信息
function getSessionUser() {
jQuery.ajax({
url: "/user/myinfo",
type: "GET",
data: {},
success: function (body) {
if (body.code == 200 && body.data != null && body.data.id >= 0) {
// 当前用户已经登录
islogin = true;
jQuery("#comment_login_name").html(body.data.username); // 评论人

// 判断当前文章是否是当前登录用户发表的, 如果是就显示删除按钮
// 此处如果另起一个ajax生成删除按钮,可能不好处理,因为这几个ajax请求的执行顺序不清除, 很可能
// 先执行了生成删除按钮,再拿用户登录信息,这样就不合理
isArtByMe(aid);
} else {
// 当前用户未登录
}
}
});
}

// 更新访问量
function updateCount() {
jQuery.ajax({
url:"/art/add_rcount",
type:"POST",
data:{
"aid":aid
},
success:function(body) {
}
});
}

// 总的初始化详情页
function initPage() {
// 初始化文章详情页
initArtDetail();
// 加载评论列表
initComment();
// 更新访问量
updateCount();
// 获取当前登录用户的信息
getSessionUser();
}
initPage();
</script>

前端主要做了这四件事:

  1. 初始化文章详情;
  2. 初始化当前文章底下爱的评论列表;
  3. 请求文章详情页时, 阅读量 + 1;
  4. 获取当前用户的登录信息(是否显示登录人,是否显示删除按钮).

后端  controller  分别写 4 个接口处理相应的请求即可.

2. 为什么要使用并发编程升级文章详情页

        🍁根据前面的前端代码,我们可以看出来,每次访问文章详情页,都会调用 4 个方法,而每一个方法的调用就是一次 HTTP 请求,而 HTTP 请求又是基于 TCP 协议的,所以每一次请求都需要进行 3 次握手,4 次挥手,那么 4 次请求,就需要进行 12 次握手,和 16 次挥手;

        🍁这样肯定是不如发送一次 HTTP 请求的性能高的,只不过合并 4 次请求,会使得建立连接和断开连接的时间比原来长那么一点,但是在计算响应的时候,使用了 4 个线程并发执行的,所以整体来说,性能还是可以提升不少的.

3. 如何使用并发编程升级文章详情页

3.1 配置线程池

@Configuration
public class ThreadPoolConfig {

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5); // 核心线程数
taskExecutor.setMaxPoolSize(10); // 最大线程数
taskExecutor.setQueueCapacity(10000); // 任务队列的大小
taskExecutor.setThreadNamePrefix("my-thread-pool-"); // 前缀名
taskExecutor.initialize();
return taskExecutor;
}
}

3.2 合并前端请求

<script type="text/javascript">
var aid = getURLParam("id"); // 文章ID
var islogin = false; // 是否登录
// 初始化文章详情
var editormd;
function initEdit(md){
editormd = editormd.markdownToHTML("editorDiv", {
markdown : md,
});
}

// 初始化文章的详细信息
function initArtDetail(art) {
if(art == null || art.aid <= 0) {
alert("参数有误!");
return false;
}
// 查询文章成功
jQuery("#title").html(art.title); // 设置文章标题
jQuery("#createtime").html(art.createtime); // 设置文章发布时间
jQuery("#rcount").html(art.rcount); // 设置文章访问量
initEdit(art.content); // 设置文章详情
if (art.photo != null && art.photo != "") {
jQuery("#photo").attr("src", art.photo); // 设置头像
}
jQuery("#username").html(art.username); // 设置昵称
jQuery("#artcount").html(art.artCount);
}

// [是否要显示评论删除按钮] - 判断当前文章是否属于当前登录用户
function isArtByMe(aid) {
jQuery.ajax({
url: "/user/isartbyme",
type: "GET",
data: {
"aid": aid
},
success: function (res) {
if (res.code == 200 && res.data == 1) {
// 当前文章归属于当前登录用户
jQuery(".comment_del_class").each(function (i) {
jQuery(this).show();
});
}
}
});
}

// 加载评论列表
function initComment(commentList) {
var commentListHtml = "";
for(let comment of commentList) {
commentListHtml += '<div style="margin-bottom: 26px;">';
commentListHtml += comment.username + ':' + comment.content;
commentListHtml += ' <a class="comment_del_class" style="display: none;text-decoration:none; color:grey;" href="javascript:del(' +
comment.cid + ')">删除</a>';
commentListHtml += '</div>';
}
jQuery("#commentlist").html(commentListHtml);
var commentCount = commentList.length;
jQuery("#commentCount").html('共 ' + commentCount + ' 条评论');
}

// 获取当前登录用户的信息
function getSessionUser(userinfo) {
if(userinfo != null && userinfo.uid >= 0) {
// 当前用户已经登录
islogin = true;
jQuery("#comment_login_name").html(userinfo.username); // 评论人

// 1.判断当前文章是否是当前登录用户发表的, 如果是就显示删除按钮;
// 2.此处如果另起一个ajax生成删除按钮,可能不好处理,因为这几个ajax请求的执行顺序不清除,
// 很可能先执行了生成删除按钮,再拿用户登录信息,这样就不合理.
isArtByMe(aid);

}
}

// 总的初始化详情页
function initPage() {
jQuery.ajax({
url:"art/total_init",
type:"POST",
data:{
"aid":aid
},
success:function(body) {
if(body.code == 200 && body.data != null)
// 初始化文章详情页
initArtDetail(res.data.articleinfo);
// 加载评论列表
initComment(body.data.commentList);
// 获取当前登录用户的信息
getSessionUser(body.data.userinfo);
}
});
}
initPage();
</script>

3.3 合并后端接口,使用多线程并发执行

/**
* 详情页接口初始化合并方法
* @param aid
* @return
*/

@RequestMapping("/total_init")
public Object totalInit(Integer aid, HttpServletRequest request) throws ExecutionException, InterruptedException {
// 1.非空效验
if(aid == null & 0) {
return AjaxResult.fail(-1, "非法参数! ");
}
// 2.创建多个任务,放到线程池中进行执行
// 2.1 得到文章详情
FutureTask<ArticleInfoVo> getArticleInfo = new FutureTask<>(() -> {
// 查询数据库中的文章信息
ArticleInfoVo articleInfoVo = articleService.getDetail(aid);
if(articleInfoVo != null) {
// 组装数据: 查询当前用户发表的文章总数
articleInfoVo.setArtCount(articleService.artCount(articleInfoVo.getUid()));
// 查询图片
UserInfo userInfo = userService.getById(articleInfoVo.getUid());
articleInfoVo.setPhoto(userInfo.getPhoto());
}
return articleInfoVo;
});

// 2.2 得到当前文章的评论列表
FutureTask<List<CommentInfoVo>> getCommentList = new FutureTask<>(() -> {
return commentInfoService.getList(aid);
});
// 2.3 给当前文章的阅读量 + 1
FutureTask<Integer> updateRCount = new FutureTask<>(() -> {
return articleService.addRCount(aid);
});
// 2.4 当前登录用户的信息返回给前端
FutureTask<UserInfo> getSession = new FutureTask<>(() -> {
return SessionUtil.getLoginUser(request);
});
// 将任务放到线程池中并发执行
taskExecutor.submit(getArticleInfo);
taskExecutor.submit(getCommentList);
taskExecutor.submit(updateRCount); // 只操作后端,不需要等待执行完
taskExecutor.submit(getSession);
// 等待任务执行完
ArticleInfoVo articleInfoVo = getArticleInfo.get(); // 阻塞至执行完
List<CommentInfoVo> commentList = getCommentList.get();
UserInfo userInfo = getSession.get();
// 3.组装并发执行的结果,返回给前端
HashMap<String, Object> resultMap = new HashMap<>();
resultMap.put("articleinfo",articleInfoVo);
resultMap.put("commentList",commentList);
resultMap.put("userinfo",userInfo);
return AjaxResult.success(resultMap);
}

【注意】后端合并接口后,新的接口需要在拦截器里面设置放行,否则分页列表页查看详情页就会没有权限.

4. 项目相关链接

 项目仓库:https://gitee.com/xiaobite_hl/JAVA/tree/master/Big-work/mycnblog_ssm_2

项目博客:https://blog.csdn.net/xaiobit_hl/article/details/128727219 

项目 web 自动化测试: https://blog.csdn.net/xaiobit_hl/article/details/129903816


举报

相关推荐

0 条评论