SpringBoot + Vue实现博文上传+展示+博文列表
Posted Huterox
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot + Vue实现博文上传+展示+博文列表相关的知识,希望对你有一定的参考价值。
文章目录
前言
ok,又到了水文时间了,那么今天带来的是这个WhiteHole的最新的开发进度,也就是实现了我们的博文的基本功能。那么之后比较重大的功能就是我们的消息系统+流量统计(文章,问答之类的数据信息)其他的什么社区,社区管理什么的和我们先前的业务是类似的。所以的话这里就不想复述了,因为意义不大,那部分的话基本上技术没什么难的就是基本的CURD+调用微服务。实话实说,这部分的开发对我来说其实就是繁琐,其实很简单,当然要考虑的东西不少。然后的话还有咱们的后台管理系统,这部分用户端做的差不多了,这个后台的其实也快,无法也是CURD+一些高权限的操作。现阶段的代码还是一个初级阶段,后面把组件上齐了,咱们还会在修改说明的。
那么这次的话也是我们尽可能完整一点。
不过的话也是有部分内容重复的,所以请先阅读这篇文章:
Vue整合Markdown组件+SpringBoot文件上传+代码差异对比
实现效果
博文列表
文章编辑
文章显示
其实这里的实现逻辑和先前的那个很像,区别就是说,但是先前的话也是没有说完整,那么现在的话我们说仔细一点,完整的前端代码+后端的主要业务代码。
博文列表
首先来说的是我们的一个博文的列表。
先说一下我们的这个博文的这个数据表:
我们这边是将内容和我们的blog分开的。因为我们这边要实现很多的操作,比如文章的fork,合并修等等。
前端
我们先来看到前端的完整的代码,这里的话我就直接给出我这个显示的列表的代码。这里的前端的所有的代码都是没有封装的,好处是方便修改,方便理解。坏处是,不方便调用,但是不好维护,所以的话,不去封装了,开发完再说,还有很多的辅助功能没做呢。
那么我们就来看看吧:
<template>
<div style="width: 100%">
<el-empty
image="/static/image/empty.gif" :image-size="600" description="暂时木有找到博文~"
v-if="isEmpty"
>
</el-empty>
<br>
<br>
<div v-if="!isEmpty" style="width: 100%;margin-left: 1%" class="main">
<el-card shadow="hover" v-for="(message,index) in Messages" :key="index">
<div style="height:100px">
<div style="width:14%;height: 100%;border-radius: 100px;display:inline-block;">
<el-image
style="width:100%;height: 100%;border-radius: 100px"
v-bind:src="message.blogimg"
class="image"
/>
</div>
<div style="display:inline-block;margin-left: 5%;width: 60%">
<p class="message" style="font-weight:bold">
<router-link class="alink" :to=" path: '/blogshow',query:'blogid':message.blogid">
message.blogTitle
</router-link>
</p>
<p style="font-weight: lighter" class="message">
message.info
</p>
<p class="message">
阅读:
<i class="el-icon-view"></i>
message.viewNumber
收藏:
<i class="el-icon-star-off"></i>
message.collectNumber
fork:message.forkNumber
</p>
</div>
<div style="width:18%;height: 100%;
display:inline-block;
"
>
<p style="text-align: center;font-size: 8px">message.createTime</p>
<br><br>
</div>
</div>
<br>
</el-card>
</div>
<br>
<div class="footer" style="margin: 0 auto;width: 100%;">
</div>
</div>
</template>
<script>
export default
name: "lastArticle",
data()
return
isEmpty: true,
total: 0,
page: 1,
limit: 10,
Messages:[
userid: null,
info: null,
blogid: null,
contentid: null,
blogTitle: null,
userNickname: null,
userImg: null,
createTime: null,
viewNumber: null,
likeNumber: null,
collectNumber: null,
status: null,
level: null,
forkNumber: null,
blogimg: null
,
]
,
methods:
getDataList()
//这里客户端自己进行一个缓存
let pageSession = sessionStorage.getItem("lastHomeBlogListPageSession");
let total = sessionStorage.getItem("lastHomeBlogListTotal");
if(pageSession && total)
this.Messages = JSON.parse(pageSession);
this.total = parseInt(total);
this.isEmpty = (this.total === 0);
else
this.axios(
url: "/blog/blog/home/last",
method: 'get',
).then((res) =>
res = res.data;
if (res.code === 0)
//这个就是我们的默认展示图片
let image_base_user = "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg";
let image_base_blog = "https://whiteholecloud-dev.oss-cn-shanghai.aliyuncs.com/2022-09-25/8cee84b4-1d03-483f-8376-14d419d84ca5_03.jpg"
//同样的拿到数据后需要临时保存
let page = res.page;
this.total = page.totalCount;
this.Messages = page.list
this.isEmpty = (this.total === 0);
for (let i=0;i<this.Messages.length;i++)
if(!this.Messages[i].userImg)this.Messages[i].userImg=image_base_user;
if(!this.Messages[i].blogimg)this.Messages[i].blogimg=image_base_blog
//存储临时缓存
sessionStorage.setItem("lastHomeBlogListPageSession", JSON.stringify(this.Messages));
sessionStorage.setItem("lastHomeBlogListTotal",page.totalCount);
else
this.$message.error(res.msg);
);
,
created()
this.getDataList();
,
</script>
<style scoped>
.message
width: 25em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
.alink
text-decoration: none;
color: #333333;
</style>
我们这边的话,为了防止客户端的数据丢失以及降低我们的服务端的压力,所以的话做一个缓存,当然我们服务端还是有哨兵的,双重限流嘛。
后端接口
之后的话,就是接口的实现,这个其实相当简单,查表就好了,当然我们这边 还要做一个缓存,这个缓存的话就是直接使用SpringCache来做的。
首先是我们的接口:
@RequestMapping("/last")
@Cacheable(value="homePageBlog:lastHomePageList",key = "#root.methodName")
public R lastHomePageList() throws Exception
return blogHomePageService.lastBlogList();
之后的话是我们的实现类:
@Override
public R lastBlogList() throws Exception
HashMap<String, Object> params = new HashMap<>();
//组装请求博文列表所需要的数据,当访问的为内部接口时,所有的参数均为Map形式
params.put("page","1");
params.put("limit","10");
params.put("accurate","single");
//此时指定HoleNULL,那么这个key不参与查询,但是需要进行占位,不能为空
params.put("table_name","HoleNULL");
params.put("key","1");
params.put("order","desc");
params.put("status","1");
params.put("level","1");
PageUtils page = blogService.queryPage(params);
return R.ok().put("page", page);
这里的话我们重写了这个queryPage的方法来实现分页。
public class BlogServiceImpl extends ServiceImpl<BlogDao, BlogEntity> implements BlogService
/**
*
* 在所有的基础方法当中我们做出如下约定,(因为有大量的请求是需要使用到分页查询的,并且这个方法相当重要)
* key,表示需要模糊查询或者精确查询的值,和 accurate 相互配合。
* accurate表示改查询需要进行精确查询 当accurate=single 表示精确查询,需要指定
* table_name 还有order:desc,asc当为many,表示需要更加复杂的查询,此时需要附带 accurate_query 即查询QueryWrapper
* 所有的附加值都需要具备
* 最后必须参数为
* 'page': 第几页
* 'limit':每页多少,
* 此外对于用户端的查询,需要指明status,和 level否则处理将失败
* */
@Override
public PageUtils queryPage(Map<String, Object> params) throws Exception
String key = (String) params.get("key");
String accurate = (String) params.get("accurate");
IPage<BlogEntity> page_params = new Query<BlogEntity>().getPage(params);
QueryWrapper<BlogEntity> blogEntityQueryWrapper = new QueryWrapper<>();
if(key!=null)
if(accurate==null)
//此时表示只有key,没有accurate,说明是后台管理系统在调用
blogEntityQueryWrapper.like("userid",key).or().
like("blogid",key).or().
like("user_nickname",key).or().
like("blog_title",key);
else
//此时有accurate说明是用户端在调用
if(accurate.equals("single"))
String table_name = (String) params.get("table_name");
String order = (String) params.get("order");
Integer status = Integer.valueOf((String) params.get("status"));
Integer level = Integer.valueOf((String) params.get("level"));
if(table_name.equals("HoleNULL"))
blogEntityQueryWrapper.eq("status",status)
.eq("level",level);
else
blogEntityQueryWrapper.eq(table_name,key)
.eq("status",status)
.eq("level",level);
if(order.equals("desc"))
blogEntityQueryWrapper.orderByDesc("blogid");
else if(accurate.equals("many"))
Object accurate_query = params.get("accurate_query");
QueryWrapper<BlogEntity> deserialize = (QueryWrapper<BlogEntity>) SerializeUtil.deserialize(accurate_query.toString());
blogEntityQueryWrapper = deserialize;
IPage<BlogEntity> page = this.page(
page_params,
blogEntityQueryWrapper
);
return new PageUtils(page);
这些代码后面在做一个映射封装。
这里的话还有我们的R类:
public class R extends HashMap<String, Object>
private static final long serialVersionUID = 1L;
public R()
put("code", 0);
put("msg", "success");
public static R error()
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
以上是关于SpringBoot + Vue实现博文上传+展示+博文列表的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后端篇: 整合阿里云 OSS 服务 -- 上传下载文件图片
SpringBoot+Vue+token实现(表单+图片)上传图片地址保存到数据库。上传图片保存位置自己定义图片可以在前端回显)