2.5万字详细讲解个人网站的开发过程和项目的部署
Posted Talisman丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.5万字详细讲解个人网站的开发过程和项目的部署相关的知识,希望对你有一定的参考价值。
简介
博客介绍: 第一个前后端分离的项目,想做个好的个人博客是很久之前的事,算上这个博客我一共做过三个,第一个是用jsp做的,因为没有设计感页面简直不能直视。第二个是跟着B站上的做的,用thymeleaf模板做的博客,那时候才学SpringBoot没多久,算是为了熟练SpringBoot才做的。这次是想做一个能长期维护的博客(就是一直会用这个,就算要改的话,整体架构也不会怎么变的),所以我打算就用vue来做,做前后端分离的项目。
技术讲解: 这篇博客会详细讲解整个环境配置、开发流程、项目部署这些内容,比如说某些重要的内容,哪里容易出错,哪一方面要注意一下。一些简单的CURD操作就不会详细讲解了。
关于界面: 有些页面是参照别人的做,例如首页我是参照这个做的,并在基础上修改了一下。https://xiaoyou66.com/
个人网站: 附上部署好的网站,可以更好的阅读下面的文章http://liaojiale.com/
1 技术介绍
1.1 个人博客功能
1.2 技术组合
1.3 工具与坏境
- IDEA
- Navicat
- Xshell
- Xftp
- Maven3.6
- JDK 8
2 项目的环境配置
2.1 vue的环境配置
首先进到放vue代码的文件下,在地址栏上输入CMD就会跳到当前的目录下,然后根据以下步骤去创建vue项目
vue init webpack 文件名
# 进入工程目录
cd 创建完的vue项目
# 安装 vue-router
cnpm install vue-router --save-dev
# 安装 element-ui
cnpm install element-ui --save-dev
# 安装依赖
cnpm install
# 安装 SASS 加载器
cnpm install sass-loader node-sass --save-dev
# 启动测试
npm run dev
npm isntall vue-router --save
npm install storage --save-dev
npm install semantic-ui --save-dev
npm install vue-jsonp --save
cnpm install axios --save-dev
cnpm install vue-axios --save-dev
1.环境配置好后首先进到main.js把安装好的依赖到进去
- 配置路由
- 然后通过npm run dev进行访问,访问成功则环境配置好了,之后就可以进行前端页面的操作啦~~~
2.2 解决跨域问题
在获取后端数据时都会有一个跨域的问题要解决,所以我们去找到config目录下的index.js的文件进行如下的操作
下面的是以/api/代替了http://localhost:8081/这个ip和端口,这样就能解决跨域的问题。
this.axios({
url: "/api/layer/getLayerInfo",
method: "get",
})
2.3 关于图标的获取
可以通过阿里巴巴矢量图标库获取图标(个人比较推荐,因为这个是真的很简单方便)
步骤
- 先进入阿里巴巴矢量图标库
- 搜索你需要的图标
- 找到喜欢的图标并收藏
- 新建项目并添加至项目中
- 在Font Class里点击更新代码便会出现链接,然后打开链接并复制里面的内容
- 在vue项目里创建一个css文件并复制进去,最后引用这个css文件
- 在添加图标的标签里的class里面加入iconfont 图标的class。例如:
<strong class="iconfont icon-shouye"></strong>
3 前端技术
3.1 element-ui的分页使用介绍
<el-col>
<el-pagination
background
layout="prev, pager, next"
@current-change="selectPage()"
:total="blogsCount * 10 / size">
</el-pagination>
</el-col>
current-change当前页面发生改变时会触发
blogsCount是博客的数量,通过blogsCount * 10 / size就可以获取到页数
通过获取active这个class获取页面发生改变时的值,再把这个值传给后台便可以获取下一页的数据
selectPage(){
let current = document.getElementsByClassName('active')[0].innerhtml
this.axios({
url:"/api/{{请求地址}}",
method:"get",
params:{
current:current - 1,
size:this.size
}
}).then(res => {
this.blogs = res.data.blog
})
},
3.2 发布博客
个人博客最核心的是什么,那当然是写博客啊,要说写博客首选的编辑器当然是markdown,功能多样却操作容易方便。有一个基于vue的markdow编辑插件mavon-edtior
步骤
- npm install mavon-editor --save
- 在main.js上引用
// 全局注册
// import with ES6
import Vue from 'vue'
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
// use
Vue.use(mavonEditor)
new Vue({
'el': '#main',
data() {
return { value: '' }
}
})
- maven-editor配置
获取md格式和html格式,md的格式内容是在修改博客时用的,html格式的内容是博客展示是用的。这样就能把数据发到后台在存进数据库啦。记得两种格式都要存进数据库
updateDoc(markdown, render) {
this.html = render;
this.markdown = markdown;
},
saveDoc(markdown, render) {
this.html = render;
this.markdown = markdown;
},
- 图片上传
$imgAdd (pos, $file) {
// 第一步.将图片上传到服务器.
var formdata = new FormData()
formdata.append('image', $file)
this.img_file[pos] = $file
this.$http({
url: '/api/{{地址}}',
method: 'post',
data: formdata,
headers: { 'Content-Type': 'multipart/form-data' }
}).then((res) => {
let _res = res.data
// 第二步.将返回的url替换到文本原位置![...](0) -> ![...](url)
this.$refs.md.$img2Url(pos, _res.data)
})
},
- 图片删除
下面的请求主要是删除图片,删除服务器上的图片
$imgDel (pos) {
delete this.img_file[pos]
var p = pos[0]
this.axios({
url:"/api/{{地址}}",
method:"get",
params:{
pos:p
}
})
}
- 代码高亮
通过npm引入以下的三个插件,并在mavon-editor标签上加入这段代码 :ishljs = "true"
highlight.js
github-markdown-css
katex(v2.4.7)
小提示:如果你觉得这些高亮的颜色、字体大小不好看,可以通过f12查看这个高亮的代码的class,然后通过权重(!important)对属性进行自己喜欢的样式修改。
- 展示博客的内容
通过以下代码让博客内容进行展示
content是从后台请求到的博客内容,也就是html格式的内容
<div id="content" class="markdown-body" v-html="content">
3.3 点赞功能的实现
点赞功能通常都是一个人只能点赞一次,不可以重复点赞,因为这个博客主要是个人博客,个人所有的,没有其他用户,所以在数据库上没有建用户表,但要有点赞功能且不能重复点赞,我第一个想到的技术就是本地储存技术也就是cookie,当你点赞时会在你的浏览器上加上一个cookie,例如:我在id为3的博客里点赞了就会在浏览器上储存一个blogId:3这样的一个cookie意思是你在id为3的博客里点赞了,如果识别到你本地上有这个cookie那你就不能继续点赞了。
步骤
- 先建一个工具包把这个工具类放进去
var storage = {
/**
对本地数据进行操作的相关方法,如localStorage,sessionStorage的封装
*/
setStorage: function(key, value, duration) {
var data = {
value: value,
expiryTime: !duration || isNaN(duration) ? 0 : this.getCurrentTimeStamp() + parseInt(duration)
};
localStorage[key] = JSON.stringify(data);
},
getStorage: function(key) {
var data = localStorage[key];
if (!data || data === "null") {
return null;
}
var now = this.getCurrentTimeStamp();
var obj;
try {
obj = JSON.parse(data);
} catch (e) {
return null;
}
if (obj.expiryTime === 0 || obj.expiryTime > now) {
return obj.value;
}
return null;
},
removeStorage: function(key){
localStorage.removeItem(key);
},
getSession: function(key) {
var data = sessionStorage[key];
if (!data || data === "null") {
return null;
}
return JSON.parse(data).value;
},
setSession: function(key, value) {
var data = {
value: value
}
sessionStorage[key] = JSON.stringify(data);
},
getCurrentTimeStamp: function() {
return Date.parse(new Date());
}
};
export default storage;
- 在main.js如下配置
import mavonEditor from "mavon-editor";
Vue.prototype.$storage=storage;
使用方法
this.$storage.setStorage(key,value) //设置cookie
this.$storage.getStorage(key) //获取cookie
代码如下
if (this.$storage.getStorage("good"+this.blogId)==this.blogId){
this.$message.warning("你已经点过赞了")
return
}
this.axios({
url:"/api/{{地址}}",
method:"get",
params:{blogId:this.blogId}
}).then(res=>{
if (res.data){
this.$message.success("点赞成功")
this.$storage.setStorage("good"+this.blogId,this.blogId)
}
})
3.4 评论
说到评论。几乎每个博客都会加上这一点,毕竟这个能增加和别人的互动性。这个评论的难点是数据库的设计,如果数据库设计的不好,做出来是比较困难的。
评论的结构设计
思路: 根据这个设计,我们如何去设计呢?如果是建一张表如何设计才能做出楼和层的结构,他们的关系是怎样表现的出来的?我想过用一张表设计,但这样设计会很麻烦。所以我建了两张表,一张是floor(楼)表和layer(层)表。如下:
floor表是专门放楼的评论的数据,而层表是专门放层评论的数据,层的数据是绑定楼的id来获取你是在哪一楼发言,这样就能确定楼层之间的关系啦~~~
要展示哪一些层对应哪一楼这个最简单不过了只要用v-if将绑定在层的楼id等于楼的id就可。如下:
<div v-for="layer in allLayer" v-if="layer.floorId == floor.id">
3.5 获取B站用户信息
既然做评论,当然要知道是谁评论,可这是个人博客诶,又没有建用户表,所以我想到获取B站的个人信息作为评论的前提。
步骤
- 打开在用户信息那里工具栏抓包,你会发现有一个请求是获取个人信息的,接口如下:
https://api.bilibili.com/x/space/acc/infomid={{B站的UID}}&jsonp=jsonp
- 通过键盘输入每一个字母就去请求一次接口
- 通过以下代码展示图片,不然展示不了
if( res.data.data.face !== undefined ){
let _u = res.data.data.face.substring( 7 );
this.BPhoto = res.data.data.face = 'https://images.weserv.nl/?url=' + _u;
}
这是完成后的样子~
3.6 相册的设计
相册是用了不少的时间去做的,但仔细想想其实很多都是CURD操作和一下逻辑上的操作,其实没有什么可以说的,我相信多人都是会做的,所以就不说了,但花费了这么多时间还是要讲一下不说的原因的哈哈哈哈哈。
这个是相册的链接可以点进去看一下哈------相册链接
3.7 图片上传
vue提供的图片上传真的太容易了,只要贴上如下代码就可了,详细的介绍就看vue官方。
<el-upload
class="upload-demo"
drag
:action="'/api/{{请求地址}}"
list-type="picture"
:on-preview="handlePreview"
:on-remove="handleRemove"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
3.8 时光轴设计详情
时光轴的设计结构
这个时光轴的设计难点就是sql语句和怎么展示出来。首先我们先写获取年份的sql语句,如下
SELECT DATE_FORMAT( b.createTime,'%Y') as years FROM blog b
GROUP BY years
ORDER BY years DESC;
然后获取该年份下的博客
SELECT DATE_FORMAT( b.createTime,'%Y') as years FROM blog b
GROUP BY years
ORDER BY years DESC;
通过在两条sql语句就能查询出来啦~
那我们该怎么去展示在页面呢?首先我们先把年份给遍历出来,然后遍历查询出来博客,也就是第二条sql语句的数据,最后我们遍历出该博客的信息,并等于当前年份的博客才能展示出来。所以我们用到了v-if语句,这样就完成了,如果有什么不明白可以在评论区问问我哈哈哈
<div v-for="year in allYears">
<div v-for="info in blogYearInfo">
<div v-for="i in info" v-if="i.createTime.split('-')[0]==year"></div>
</div>
</div>
关于前端的知识现在到这里已经结束了,接下来讲一下关于后端方面的知识!!!
4 后端技术
4.1 SpringBoot环境配置
mybatis-plus里面有一个代码自动生成,我们可以通过代码来生成无聊且没有意思的代码。
- 我们先导入需要的依赖包
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.0.5</version>
<scope>test</scope>
</dependency>
- 我可以通过以下代码生成
public static void main(String[] args) {
// 需要构建一个 代码自动生成器 对象
AutoGenerator mpg = new AutoGenerator();
// 配置策略
// 1、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath+"/src/main/java");
gc.setAuthor("Talisman");
gc.setOpen(false);
gc.setFileOverride(false); // 是否覆盖
gc.setServiceName("%sService"); // 去Service的I前缀
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
// gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
// 2、 配置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/yingmublog?useSSL=true&characterEncoding=utf8&useUnicode=true&autoReconnect=true&failOverReadOnly=false");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("账号");
dsc.setPassword("密码");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("yingmublog");
pc.setParent("com.jiale");
pc.setEntity("entity");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
// 配置策略
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("admin","blog","blog_tag","comment","tag","type","topic","animation",
"friend","other","album_photo","album","floor","layer");// 设置要映射的表名
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setLogicDeleteFieldName("deleted");
// 自动填充配置
TableFill createTime = new TableFill("createTime", FieldFill.INSERT);
TableFill updateTime = new TableFill("updateTime", FieldFill.UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(createTime);
tableFills.add(updateTime);
strategy.setTableFillList(tableFills);
// 乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true);
mpg.setStrategy(strategy);
mpg.execute();
}
通过这些代码我们就能生成这样的目录结构
这段代码是映射你表里的字段,如果你每增加一个表可以写进去再运行代码,他就会生成对应的,这个真的很方便,大力推荐一下,它可以减少我们不必要浪费的时间。
strategy.setInclude("admin","blog","blog_tag","comment","tag","type","topic","animation",
"friend","other","album_photo","album","floor","layer"2.5 万字详解:23 种设计模式
❤️爆肝万字整理的综合架构web服务之nginx详解❤️,附建议收藏
UG NX二次开发(C#)--详细讲述编程模板NXOpen_CS_Wizard的代码意义,帮你轻松进入NXOpen(C#)二次开发