IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 2.5万字详细讲解个人网站的开发过程和项目的部署 -> 正文阅读

[Java知识库]2.5万字详细讲解个人网站的开发过程和项目的部署

简介

博客介绍: 第一个前后端分离的项目,想做个好的个人博客是很久之前的事,算上这个博客我一共做过三个,第一个是用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 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把安装好的依赖到进去
在这里插入图片描述

  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-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

步骤

  1. npm install mavon-editor --save
  2. 在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: '' }
        }
    })
  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] = $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)
      })
    },
  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-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里面有一个代码自动生成,我们可以通过代码来生成无聊且没有意思的代码。

  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;

    @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邮箱"); //设置发件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 {

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

  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/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下载

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

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-04 11:03:50  更:2021-08-04 11:04:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 8:26:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码