Reader Dev

​ 在之前学习flutter过程中,经常查阅Dart pub中的packages,便想到利用相同的形式做一个分享书籍的Web应用,无须注册,可以进行匿名的发布、修改润色他人分享的推书卡片,当然也可以进行删除。目前只开发了增删改查的工作,打星、评论的功能也会后续增加。


一、开发过程

1.1 开发技术

使用了前后端分离技术,前端采用Vue3框架、后端采用SpringBoot2。

UI框架:TailwindCSS、ElementPlus

==TailwindCss==相比Boostrap更具自定义性,更能理解每一步做了什么,比纯css更方便。

1.2 项目部署

利用腾讯云学生云服务器,学习了linux + docker的部署方式。

整个项目部署在三个docker容器中,分别对应着前端、后端和数据库。

docker图片

1.3 在学习过程中使用的参考资料

Vue3中文文档

SpringBoot2教程

Tailwindcss

ElementPlus

docker部署vue项目


二、项目过程中的问题解决

2.1 前端方面

2.2 后端方面

ElementPlus中在组件中提供了action属性,只要绑定上传后端对应api即可。

  <el-upload
    ref="upload"
    action="http://ip:post/api/covers"
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :on-success="handleSuccess"
    :before-upload="beforImageUpload"
    :file-list="fileList"
    list-type="picture"
  >

给上传的文件重命名以日期时间为前缀放置在/home/ubuntu/readerdev/imgs文件夹下,并返回给前端url地址。此时页面可以响应显示刚才上传的图片成功。

@CrossOrigin
@PostMapping("api/covers")
public String returnUploadCoverUrl(MultipartFile file) {
    String fileName = file.getOriginalFilename();
    String destFolder = "/home/ubuntu/readerdev/imgs";
    assert fileName != null;
    String suffixName = fileName.substring(fileName.lastIndexOf("."));
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmSS");
    Random random = new Random();
    String tempName = sdf.format(new Date()) + random.nextInt(100) + suffixName;
    File tempFile = new File(destFolder, tempName);

    if (!tempFile.getParentFile().exists()) {
        tempFile.mkdirs();
    }

    try {
        file.transferTo(tempFile);
        String url = "http://ip:port/api/file/" + tempFile.getName();
        return url;
    } catch (IOException e) {
        e.printStackTrace();
        return "";
    }
}

2.3 项目部署问题

2.3.1 nginx.conf配置方案

开启了gzip压缩,同时需要在前端项目中配置gzip压缩。

# 开启gzip
gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;

# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;

# 进行压缩的文件类型。javascript有多种形式,后面的图片压缩不需要的可以自行删除
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 设置压缩所需要的缓冲区大小     
gzip_buffers 4 16k;
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;
    error_log  /var/log/nginx/error.log  error;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

2.3.2 docker部署nginx项目

写了一个shell文件来简化前端vue项目修改后的部署。

sudo docker stop reader_front
sudo docker container prune
sudo docker image rm mnginx
sudo docker build -t mnginx .
sudo docker run --name reader_front -p 8080:80 -d mnginx
sudo docker ps -a

2.3.3 docker部署springboot2项目

注释如下:

//将转储的sql文件复制到容器文件中,注意不是复制到文件夹中
sudo docker cp /../book.sql mymysql:/home/tmp/book.sql

//登录容器  mysql -uroot -pyzsby123 为同时登录mysql
docker exec -it mymysql(容器名) mysql -uroot -pyzsby123

//使用数据库名,如未出创建需先创建
use readerdev;

//导入执行sql文件
source /home/tmp/book.sql;

//制作镜像  (该目录包含jar和dockfile)
docker build -t readerdev .

//运行镜像
sudo docker run --link mymysql:mymysql --name=readerdev -p 8443:8443 -di readerdev

//跨容器通信、与宿主机映射
//--link   容器名:别名  mymysql:mymysql	容器间通信
//-v       /home/ubuntu/readerdev/imgs:/home/ubuntu/readerdev/imgs    与宿主机绝对路径映射
//-p       8443:8443	与宿主机端口映射
//-d 	   -detach 在后台运行
sudo docker run --link mymysql:mymysql -v /home/ubuntu/readerdev/imgs:/home/ubuntu/readerdev/imgs --name=readerdev -p 8443:8443 -di readerdev

三、项目总结

暂时没有绑定域名,此时可以通过访问http://ip:port/进行访问。

通过本次的结业作业,大概了解了前后端分离项目开发部署的流程,也是我的第一个Web项目。开发时也踩过很多坑,比如说springboot中的上传路径问题,vue组件通信问题、Dockerfile、nginx配置问题和vue项目打包优化等。但也收获了许多,如在vue项目打包时采用cdn的方式大大减小了项目体积,浏览速度加快。

但同时也存在了很多不足,比如选择了 optional api 而没有采用vue3 推出的 composition api的方式以及代码逻辑混乱、可复用性差等问题,后来在修改一些组件时非常耗时。

希望下一次的web项目能在此基础上有所提高!😆