简介
博客介绍: 第一个前后端分离的项目,想做个好的个人博客是很久之前的事,算上这个博客我一共做过三个,第一个是用jsp做的,因为没有设计感页面简直不能直视。第二个是跟着B站上的做的,用thymeleaf模板做的博客,那时候才学SpringBoot没多久,算是为了熟练SpringBoot才做的。这次是想做一个能长期维护的博客(就是一直会用这个,就算要改的话,整体架构也不会怎么变的),所以我打算就用vue来做,做前后端分离的项目。
技术讲解: 这篇博客会详细讲解整个环境配置、开发流程、项目部署这些内容,比如说某些重要的内容,哪里容易出错,哪一方面要注意一下。一些简单的CURD操作就不会详细讲解了。
关于界面: 有些页面是参照别人的做,例如首页我是参照这个做的,并在基础上修改了一下。https://xiaoyou66.com/
个人网站: 附上部署好的网站,可以更好的阅读下面的文章http://liaojiale.com/
1 技术介绍
1.1 个人博客功能
 

1.2 技术组合
- 前端:vue + Semantic-ui框架
- 后端:SpringBoot + MyBatis-plus
- 数据库: Mysql + Redis
- 运维:docker + nginx
1.3 工具与坏境
- IDEA
- Navicat
- Xshell
- Xftp
- Maven3.6
- JDK 8
2 项目的环境配置
2.1 vue的环境配置
首先进到放vue代码的文件下,在地址栏上输入CMD就会跳到当前的目录下,然后根据以下步骤去创建vue项目
vue init webpack 文件名
cd 创建完的vue项目
cnpm install vue-router --save-dev
cnpm install element-ui --save-dev
cnpm install
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替换到文本原位置 -> 
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">
- mavon-editor官方文档
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();
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");
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
mpg.setGlobalConfig(gc);
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);
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");
4.2 文件上传
关于java文件上传,如果我上传到target的话,服务器每一次重启上传的文件就会没有了,所以我们上传到磁盘那里就能防止文件的丢失了。 JAVA代码如下:
@PostMapping("/uploadPhoto")
public R<Object> uploadPhoto(@RequestParam("image") MultipartFile file){
SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddhhmmss");
Date date = new Date();
String randomNumber = sdf.format(date);
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
String newFileName = randomNumber + "." + extension;
File dateDir = new File(FinalData.UPLOAD_FOLDER);
if (!dateDir.exists()) {
dateDir.mkdirs();
}
try {
file.transferTo(new File(FinalData.UPLOAD_FOLDER, newFileName));
} catch (IOException e) {
e.printStackTrace();
return R.failed("上传失败");
}
String invented_address="/static/uploadImage/" + newFileName;
return R.ok(invented_address);
}
Configuration配置如下
@Configuration
public class UploadFilePathConfig implements WebMvcConfigurer {
@Value("${file.staticAccessPath}")
private String staticAccessPath;
@Value("${file.uploadFolder}")
private String uploadFolder;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(staticAccessPath).addResourceLocations("file:" + uploadFolder);
}
}
yml配置如下
file:
staticAccessPath: /api/file/**
uploadFolder: /usr/local/nginx/html/static/
servlet:
context-path:
multipart:
enabled: true
max-file-size: 10mb
max-request-size: 10mb
uploadFolder: /usr/local/nginx/html/static/ 这个是我的服务器路径,如果放在d盘upload目录的话就配置 D:/upload
4.3 文件下载
特别注意一下如果使用axios是下载不了文件的,前端要通过window.open来下载,这个我就浪费了不少时间
public static void download(String fileName, HttpServletResponse response) throws IOException {
File file = new File(FinalData.PATH,fileName);
if (file.exists()) {
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("cc2da5fe-552b-4e30-acea-180f5c2e9419.jpeg", "UTF-8"));
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.4 发送邮箱
在评论那里我加入了发送邮箱功能来让我知道有人给我评论了,发邮箱的前提是他输入了邮箱才能发送,不然只是单纯的评论。发送邮箱是要获取qq邮箱的stmp,但我只能获取到自己的stmp。所以评论的人是发不了邮箱给我的,所以出现了这样两个模式。
1. 甲评论,我自己给自己发邮箱,这样我就知道别人发邮箱给我了。 2. 甲回复乙,我用我的邮箱替甲发邮箱给乙,乙给甲回复,同理。这样就能完成互相通知的情况了。
邮箱的配置如下
server.max-http-header-size=50000
spring.mail.host=smtp.qq.com
spring.mail.username=自己的QQ邮箱
spring.mail.password=获取到的密码
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
spring.mail.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
java配置如下
@PostMapping("/qqEmail")
public Object qqEmail(String email,String title,String content) throws MessagingException {
MimeMessage mimeMessage = this.mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setFrom("qq邮箱");
message.setTo(email);
message.setSubject(title);
message.setText(content);
this.mailSender.send(mimeMessage);
return "发送成功";
}
4.5 JAVA爬虫
我本来是想增加一个追番的功能,在B站那里爬取每一部番的信息,这样就不用自己去添加,可爬取时发现除了图片的数据其他的数据都能爬取,因为这一点我才没有发布追番这个功能,这个爬取的代码如下:
// 依赖包
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
Java代码
@GetMapping("/getSearchSource")
public ArrayList<Animation>getSearchSource(String keyWork) throws Exception {
ArrayList<Animation> animations = new ArrayList<>();
String encode = URLEncoder.encode(keyWork, "UTF-8");
String url = "https://search.bilibili.com/all?keyword="+encode+"&from_source=web_search";
Document document = Jsoup.parse(new URL(url), 30000);
Elements elements = document.getElementsByClass("bangumi-item");
for (Element element : elements) {
Animation animation = new Animation();
Elements link = element.getElementsByClass("left-img");
animation.setName(element.getElementsByClass("title").attr("title"));
animation.setRemarks(element.getElementsByClass("desc").text());
animation.setLink(link.attr("href").split("//")[1]);
animations.add(animation);
}
return animations;
}
请求的时候要加上url的加密。到后台那里要进行解密,不然会爬取不了的 爬取出来是这么一个效果  图片不知道为什么没有,所以这个功能暂时没做,有爬虫的大佬知道的话,就告诉我一下哈!!!
5 Redis
5.1 redis前言
前言: 在讲redis前,我先说一下在服务器上部署的redis,一开始时我就打算用上redis去做,也好补一下这方面的知识。因为要部署网站时redis要用服务器上的而不是本地,为了测试我就把服务器上的redis弄成所有ip都可以连接,不然我的本地电脑就连接不上。问题就出在于我没设置密码,然后就被别人攻击了,造成服务的cpu和负载状态100%,服务直接卡炸了。并且一些基本的liunx命令都使用不了,我就直接重装系统。那时我还不知道这个原因,然后又开始把redis设置成所有ip都可以连接,过了没多久又开始受到攻击,无奈下又重装系统。这我才知道是redis的原因。
总结: 服务器上的redis不用设置成所有ip都能连接直接把项目部署上去就能直接连接了,如果真要弄成所有ip都可以连接的话,切记一定要设置密码,这个可是血的教训。
5.2 redis的配置
在这里我用redis只做了自动登录功能,主要存储登录后的cookie并存储七天的时间,时间一过这个数据就会消失,本地存储的cookie和redis存储的数据不相等,则不会自动登录。
依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Configuration配置
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
//序列化配置
Jackson2JsonRedisSerializer<Object> jack = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jack.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用string类型的序列化
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value序列化方式采用jackson
template.setValueSerializer(jack);
hash的value序列化方式采用jackson
template.setHashValueSerializer(jack);
template.afterPropertiesSet();
return template;
}
}
redis的工具包 因为代码太长了我就不放出来了。直接上链接下载 http://liaojiale.com/RedisUtil.java
redis设置值和获取值的用法
redisUtil.set(key, value,time);
redisUtil.get(key);
登录功能如下
@Autowired
private RedisUtil redisUtil;
@PostMapping("/adminLogin")
public String adminLogin(Admin admin){
QueryWrapper<Admin> wrapper = new QueryWrapper<>();
wrapper.eq("username",admin.getUsername());
wrapper.eq("password",admin.getPassword());
if (adminService.getOne(wrapper)!=null){
String uid = UUID.randomUUID().toString();
redisUtil.set("login", uid,60*60*24*7);
return uid;
}
return null;
}
自动登录功能
@Autowired
private RedisUtil redisUtil;
@GetMapping("/autoLogin")
public boolean autoLogin(String value){
if (redisUtil.get("login")==null)return false;
if (redisUtil.get("login").equals(value))return true;
return false;
}
6 项目打包
6.1 vue打包
- 首先要在config/index.js的dev的 / 改为 ./
 - 在bulid里的 / 也改为 ./
 - 路由配置那里的mode为 history
 - 输入 npm run build命令进行打包
打包后的目录结构如下 
6.2 SpringBoot打包
- 在pom.xml上配置如下:
 - 先点击clean在点击package
 - 打开target就会发现多出的jar包,就能直接把jar包放上服务器部署
7 项目部署
7.1 docker安装
yum install -y yum-utils
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum makecache fast
yum install docker-ce docker-ce-cli containerd.io
systemctl start docker
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://be29yayj.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
7.2 vue部署
我们要把项目放进nginx上运行,所以我们先在本地下载nginx。
7.2.1 nginx下载
- 我们先从网上下载nginx
- 下载完后通过tar -zvvf nginx-1.9.9.tar.gz 命令解压
- 进到解压后的目录执行 ./configure && make && make install 命令安装
- 进入到 /usr/local/nginx/conf
- 通过vim对nginx.conf进行如下配置:
如果配置到本地要注释第二个 root /usr/share/nginx/html;把第一个root的注释取消掉,因为我们要配置到docker上就要如下配置 
7.2.2 docker安装nginx
docker pull nginx
7.2.3 docker挂载nginx
docker run --name 容器名 -d -p 80:80 -v /usr/local/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /usr/local/nginx/html/:/usr/share/nginx/html nginx
-d 后台运行 –name 给容器命名 -p 宿主端口,容器内部端口 -v 挂载的目录或文件
1.挂载完之后就能通过ip地址直接访问啦~ 2. 我们先通过Xftp工具把vue项目放到/usr/local/nginx/html里面 3. 因为我们挂载了相应的目录和文件,所以vue项目也在docker容器里上传好了,vue项目也就部署完了
7.3 SpringBoot部署
- 通过Xftp工具把SpringBoot放去你想放入的目录上,并进入该目录。
- 使用如下命令进行SpringBoot项目的部署
nohup java -jar 文件名.jar >/home/admin/文件名.jar.out 2>&1 &java -jar 文件名.jar &
8 总结
整个项目我用了20天的时间完成,主要前端花费了很多时间,因为我前端的技术一般般,加上审美这方面真的是硬伤。通过这个项目我对所使用的到的技术更加了解,如果想要学好编程真的要做项目,做项目是成长最快的一个方法。如果要大佬看见这篇博客觉得哪些地方可以改进一下,希望指教一下哈哈哈!!! 最后附上我的博客的页面!      
|