目录

  • 简介
  • 1 技术介绍
    • 1.1 个人博客功能
    • 1.2 技术组合
    • 1.3 工具与坏境
  • 2 项目的环境配置
    • 2.1 vue的环境配置
    • 2.2 解决跨域问题
    • 2.3 关于图标的获取
  • 3 前端技术
    • 3.1 element-ui的分页使用介绍
    • 3.2 发布博客
    • 3.3 点赞功能的实现
    • 3.4 评论
    • 3.5 获取B站用户信息
    • 3.6 相册的设计
    • 3.7 图片上传
    • 3.8 时光轴设计详情
  • 4 后端技术
    • 4.1 SpringBoot环境配置
    • 4.2 文件上传
    • 4.3 文件下载
    • 4.4 发送邮箱
    • 4.5 JAVA爬虫
  • 5 Redis
    • 5.1 redis前言
    • 5.2 redis的配置
  • 6 项目打包
    • 6.1 vue打包
    • 6.2 SpringBoot打包
  • 7 项目部署
    • 7.1 docker安装
    • 7.2 vue部署
      • 7.2.1 nginx下载
      • 7.2.2 docker安装nginx
      • 7.2.3 docker挂载nginx
    • 7.3 SpringBoot部署
  • 8 总结

简介

博客介绍: 第一个前后端分离的项目,想做个好的个人博客是很久之前的事,算上这个博客我一共做过三个,第一个是用jsp做的,因为没有设计感页面简直不能直视。第二个是跟着B站上的做的,用thymeleaf模板做的博客,那时候才学SpringBoot没多久,算是为了熟练SpringBoot才做的。这次是想做一个能长期维护的博客(就是一直会用这个,就算要改的话,整体架构也不会怎么变的),所以我打算就用vue来做,做前后端分离的项目。

技术讲解: 这篇博客会详细讲解整个环境配置、开发流程、项目部署这些内容,比如说某些重要的内容,哪里容易出错,哪一方面要注意一下。一些简单的CURD操作就不会详细讲解了。

关于界面: 有些页面是参照别人的做,例如首页我是参照这个做的,并在基础上修改了一下。https://xiaoyou66.com/

个人网站: 附上部署好的网站,可以更好的阅读下面的文章http://liaojiale.com/


1 技术介绍

1.1 个人博客功能


1.2 技术组合

  1. 前端:vue + Semantic-ui框架
  2. 后端:SpringBoot + MyBatis-plus
  3. 数据库: Mysql + Redis
  4. 运维:docker + nginx

1.3 工具与坏境

  1. IDEA
  2. Navicat
  3. Xshell
  4. Xftp
  5. Maven3.6
  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 devnpm 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把安装好的依赖到进去

  1. 配置路由
  2. 然后通过npm run dev进行访问,访问成功则环境配置好了,之后就可以进行前端页面的操作啦~~~

2.2 解决跨域问题

在获取后端数据时都会有一个跨域的问题要解决,所以我们去找到config目录下的index.js的文件进行如下的操作

下面的是以/api/代替了http://localhost:8081/这个ip和端口,这样就能解决跨域的问题。

this.axios({url: "/api/layer/getLayerInfo",method: "get",})

2.3 关于图标的获取

可以通过阿里巴巴矢量图标库获取图标(个人比较推荐,因为这个是真的很简单方便)

步骤

  1. 先进入阿里巴巴矢量图标库
  2. 搜索你需要的图标
  3. 找到喜欢的图标并收藏
  4. 新建项目并添加至项目中
  5. 在Font Class里点击更新代码便会出现链接,然后打开链接并复制里面的内容
  6. 在vue项目里创建一个css文件并复制进去,最后引用这个css文件
  7. 在添加图标的标签里的class里面加入iconfont 图标的class。例如:
 <strong class="iconfont icon-shouye"></strong>

3 前端技术

3.1 element-ui的分页使用介绍

<el-col><el-paginationbackgroundlayout="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].innerHTMLthis.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

步骤

  1. npm install mavon-editor --save
  2. 在main.js上引用
// 全局注册// import with ES6import Vue from 'vue'import mavonEditor from 'mavon-editor'import 'mavon-editor/dist/css/index.css'// useVue.use(mavonEditor)new Vue({'el': '#main',data() {return { value: '' }}})
  1. maven-editor配置


获取md格式和html格式,md的格式内容是在修改博客时用的,html格式的内容是博客展示是用的。这样就能把数据发到后台在存进数据库啦。记得两种格式都要存进数据库

updateDoc(markdown, render) {this.html = render;this.markdown = markdown;
},
saveDoc(markdown, render) {this.html = render;this.markdown = markdown;
},
  1. 图片上传
 $imgAdd (pos, $file) {// 第一步.将图片上传到服务器.var formdata = new FormData()formdata.append('image', $file)this.img_file[pos] = $filethis.$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)})},
  1. 图片删除
    下面的请求主要是删除图片,删除服务器上的图片
$imgDel (pos) {delete this.img_file[pos]var p = pos[0]this.axios({url:"/api/{{地址}}",method:"get",params:{pos:p}})}
  1. 代码高亮
    通过npm引入以下的三个插件,并在mavon-editor标签上加入这段代码 :ishljs = "true"

highlight.js
github-markdown-css
katex(v2.4.7)

小提示:如果你觉得这些高亮的颜色、字体大小不好看,可以通过f12查看这个高亮的代码的class,然后通过权重(!important)对属性进行自己喜欢的样式修改。

  1. 展示博客的内容
    通过以下代码让博客内容进行展示
    content是从后台请求到的博客内容,也就是html格式的内容
<div id="content" class="markdown-body" v-html="content">
  1. mavon-editor官方文档

3.3 点赞功能的实现

点赞功能通常都是一个人只能点赞一次,不可以重复点赞,因为这个博客主要是个人博客,个人所有的,没有其他用户,所以在数据库上没有建用户表,但要有点赞功能且不能重复点赞,我第一个想到的技术就是本地储存技术也就是cookie,当你点赞时会在你的浏览器上加上一个cookie,例如:我在id为3的博客里点赞了就会在浏览器上储存一个blogId:3这样的一个cookie意思是你在id为3的博客里点赞了,如果识别到你本地上有这个cookie那你就不能继续点赞了。
步骤

  1. 先建一个工具包把这个工具类放进去
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;
  1. 在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站的个人信息作为评论的前提。
步骤

  1. 打开在用户信息那里工具栏抓包,你会发现有一个请求是获取个人信息的,接口如下:

https://api.bilibili.com/x/space/acc/infomid={{B站的UID}}&jsonp=jsonp

  1. 通过键盘输入每一个字母就去请求一次接口
  2. 通过以下代码展示图片,不然展示不了
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-uploadclass="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 bGROUP BY yearsORDER BY years DESC;

然后获取该年份下的博客

SELECT DATE_FORMAT( b.createTime,'%Y') as years FROM blog bGROUP BY yearsORDER 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里面有一个代码自动生成,我们可以通过代码来生成无聊且没有意思的代码。

  1. 我们先导入需要的依赖包
<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>
  1. 我可以通过以下代码生成
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");// 设置要映射的表名

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);//创建一个唯一标识作为评论的主键以及队伍的一个字段,方便用来保存数据将队伍与队伍描述建立起关系//使用FilenameUtils获得文件的后缀(先导依赖Commons-fileUpload)String extension = FilenameUtils.getExtension(file.getOriginalFilename());//生成新的文件名(队伍名+随机数+后缀名)String newFileName = randomNumber + "." + extension;//使用ResourceUtils类路径再获取文件保存的路径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;@Overridepublic 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: truemax-file-size: 10mbmax-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邮箱"); //设置发件qq邮箱message.setTo(email);    //设置收件人message.setSubject(title); //设置标题message.setText(content);     //第二个参数true表示使用HTML语言来编写邮件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 {@Beanpublic 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序列化方式采用jacksontemplate.setValueSerializer(jack);hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jack);template.afterPropertiesSet();return template;}
}

redis的工具包
因为代码太长了我就不放出来了。直接上链接下载 http://liaojiale.com/RedisUtil.java

redis设置值和获取值的用法

redisUtil.set(key, value,time);
redisUtil.get(key);

登录功能如下

 @Autowiredprivate 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打包

  1. 首先要在config/index.js的dev的 / 改为 ./
  2. 在bulid里的 / 也改为 ./
  3. 路由配置那里的mode为 history
  4. 输入 npm run build命令进行打包
    打包后的目录结构如下

6.2 SpringBoot打包

  1. 在pom.xml上配置如下:
  2. 先点击clean在点击package
  3. 打开target就会发现多出的jar包,就能直接把jar包放上服务器部署

7 项目部署

7.1 docker安装

# 1、需要的安装包
yum install -y yum-utils# 2、设置镜像仓库,我们选第二个阿里云镜像
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软件包索引
yum makecache fast# 3、安装docker相关的
yum install docker-ce docker-ce-cli containerd.io# 4、启动docker
systemctl start docker# 5、docker version 是否安装成功# 6、配置阿里云镜像服务
sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://be29yayj.mirror.aliyuncs.com"]
}
EOFsudo systemctl daemon-reloadsudo systemctl restart docker

7.2 vue部署

我们要把项目放进nginx上运行,所以我们先在本地下载nginx。

7.2.1 nginx下载

  1. 我们先从网上下载nginx
  2. 下载完后通过tar -zvvf nginx-1.9.9.tar.gz 命令解压
  3. 进到解压后的目录执行 ./configure && make && make install 命令安装
  4. 进入到 /usr/local/nginx/conf
  5. 通过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部署

  1. 通过Xftp工具把SpringBoot放去你想放入的目录上,并进入该目录。
  2. 使用如下命令进行SpringBoot项目的部署
nohup java -jar 文件名.jar >/home/admin/文件名.jar.out 2>&1 &java -jar 文件名.jar &

8 总结

整个项目我用了20天的时间完成,主要前端花费了很多时间,因为我前端的技术一般般,加上审美这方面真的是硬伤。通过这个项目我对所使用的到的技术更加了解,如果想要学好编程真的要做项目,做项目是成长最快的一个方法。如果要大佬看见这篇博客觉得哪些地方可以改进一下,希望指教一下哈哈哈!!!
最后附上我的博客的页面!





2.5万字详细讲解个人网站的开发过程和项目的部署相关推荐

  1. [python]14、五万字详细讲解pandas的所有功能和用法以及安装jupyter

    目录 1.安装jupyter 1.1.启用jupyter 2. pandas介绍 2.1.pip3和pip的区别 2.2.pip或者pip3换源 2.2.1.临时修改 2.2.2.永久修改 2.2.3 ...

  2. pytest自动化测试框架,真正做到从0到1由浅入深详细讲解【万字级】

    目录 嗨咯铁汁们,很久不见,我还是你们的老朋友凡叔,这里也感谢各位小伙伴的点赞和关注,你们的三连是我最大的动力哈,我也不会辜负各位的期盼,这里呢给大家出了一个pytest自动化测试框架由浅入深详细讲解 ...

  3. 【数据库】以sqlserver数据库为例,讲解sql语句的修改列(万字长文详细讲解)

    本文针对数据库的初学者,进行详细讲解,通过更改.添加.除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义. 一 语法 ALTER TABLE table  { [ ALTER COLUMN c ...

  4. 适合新手练手,用Python爬取OPGG里英雄联盟英雄胜率及选取率,详细讲解加注释(建议收藏练手)

    今天来个简单的小项目,适合新手拿来练手,在OPGG上爬取英雄联盟里的法师,ADC,打野,辅助所有英雄的胜率及选取率,是不是感觉很高大上,但是却很简单,只要用三十多行代码就能实现,详细讲解每一行代码加注 ...

  5. python爬虫原理-python爬虫原理详细讲解

    原标题:python爬虫原理详细讲解 一 .爬虫是什么 1.什么是互联网? 互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样. 2.互联网建立的目的?互联网的 ...

  6. oracle怎么将一列挪到另一列,详细讲解Oracle数据库的数据迁移方法

    <详细讲解Oracle数据库的数据迁移方法>由会员分享,可在线阅读,更多相关<详细讲解Oracle数据库的数据迁移方法(4页珍藏版)>请在人人文库网上搜索. 1.详细讲解 Or ...

  7. [Python图像处理] 三十二.傅里叶变换(图像去噪)与霍夫变换(特征识别)万字详细总结

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  8. [Python图像处理] 三十一.图像点运算处理两万字详细总结(灰度化处理、阈值化处理)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  9. [Python图像处理] 三十.图像量化及采样处理万字详细总结(推荐)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

最新文章

  1. 使用pytorch构建2D和3D人脸比对库(使用face-alignment)
  2. [Python从零到壹] 三.语法基础之文件操作、CSV文件读写及面向对象
  3. undefined reference to 'pthread_create'问题解决 -- 转
  4. 53pagecontext对象
  5. IDEA 使用generator逆向工程生成pojo,mapper
  6. Python中替换元素
  7. JSP — request 内置对象
  8. 隐藏IP地址的三种方法
  9. python 循环十次_python循环10次怎么写
  10. python爬虫beautifulsoup爬取小说_Python3网络爬虫(七):使用Beautiful Soup爬取小说
  11. ceph存储 pg归置组处于stuck以及degraded状态解决方案
  12. STM32 MPU 阅读笔记
  13. 学生管理系统--【Java+MySQL】--数据库系统概论综合性实验
  14. Kotlin 开发Android app(十九):文件读写和SharedPreferences内容存储
  15. Chromedriver 安装
  16. 防止电脑辐射的有效方法
  17. Ranklib部分源码分析
  18. 福虎迎新,到央视新闻APP瞰博冠8K春节风光慢直播
  19. 基础不扎实,工作中很迷茫。
  20. KVM学习(四)windows server半虚拟化驱动virtio

热门文章

  1. HDD深圳站:全生命周期赋能开发者,华为引领应用生态升级
  2. vw 前端_【前端适配】vw+rem自适应适配方案
  3. 定义计划协议凭证类型
  4. IBM造海水电池,“搅局”锂电池产业?
  5. Latex文本两端对齐
  6. kali wmap使用教程
  7. matlab怎么对语音信号取样,语音信号采样和频谱分析
  8. win7“找不到该项目”的错误原因及解决方法
  9. glm() and lm()
  10. 为什么要使用第三方物联网平台