• Flask自学分享


    写在前面

    最近两个月,学会了微信小程序,学会了Flask,接着又学会了VUE前端开发,学会了docker,gunicorn,nginx部署,独立Web开发的能力终于GET了。

    内心喜悦,写文总结,记录分享。本文主要针对入门学习,希望对大家有所帮助。

    作为程序员,Web开发确实很有必要去学习。因为整个互联网的核心技术就是Web开发技术。学会了Web开发,对于整个互联网的认知,对于整个编程世界的认知,都会有非常大的提升。

    Flask框架

    Python三大主流Web框架:Django,Flask,Tornado。

    对于本人,Django入门艰难,Tornado没有接触,Flask一见钟情。

    Flask,拉起一个网站,简直太简单了,简单即是美,怎不惹人爱。

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=8080, debug=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Flask,拉起一个API服务后端,亦是如此简单,如此优雅。

    from flask import Flask
    from flask import jsonify
    app = Flask(__name__)
    
    @app.route('/api/user',methods=['GET'])
    def get_user():
        return jsonify(code=200, msg="用户查询成功!",username = '张三',userphone = '18288889999')
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=8080, debug=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Flask做API服务后端的入门学习

    做API服务后端,主要是三块内容:路由,数据库,身份验证。(不需要 渲染 这块东西了)

    from flask import Flask
    from flask import jsonify
    from flask import request
    from Tools.dbmanager import DBManager
    from Tools.decoratormanager import session_jwt_verification
    
    app = Flask(__name__)
    
    
    @app.route("/bumen",methods=['GET'])
    @session_jwt_verification
    def goto_bumen_search():
        ###############查询部门###############
        sqlstring0 = "SELECT id,bumenname,bumentips FROM jr_bumen"
        data0 = DBManager().executeQueryall(sqlstring0)
        if  data0 == False:
            return_data = dict()
            return_data['code'] = 5000
            return_data['msg'] = "数据库连接异常!"
            return jsonify(return_data)
        if  data0 == None:
            return_data = dict()
            return_data['code'] = 5001
            return_data['msg'] = "没有部门数据!"
            return jsonify(return_data)
        if  data0 != None:
            return_data = dict()
            return_data['code'] = 200
            return_data['msg'] = "查询成功!"
            return_data['bumendatas'] = data0
            return jsonify(return_data)
    
    
    
    @app.route("/bumen",methods=['POST'])
    @session_jwt_verification
    def goto_bumen_add():
        data = request.get_json()
        bumen_name = data['bumenName']
        bumen_tips = data['bumenTips']
        ###############新增部门###############
        sqlstring0 = f"INSERT INTO jr_bumen (bumenname,bumentips) VALUES ('{bumen_name}','{bumen_tips}')"
        data0 = DBManager().executeQueryID(sqlstring0)
        if  data0 == False:
            return_data = dict()
            return_data['code'] = 5000
            return_data['msg'] = "数据库连接异常!"
            return jsonify(return_data)
        if  data0 != None:
            return_data = dict()
            return_data['code'] = 200
            return_data['msg'] = "部门添加成功!"
            return_data['bumenid'] = data0
            return jsonify(return_data)
    
    
    @app.route("/bumen",methods=['PUT'])
    @session_jwt_verification
    def goto_bumen_alter():
        data = request.get_json()
        bumen_id = data['bumenId']
        bumen_name = data['bumenName']
        bumen_tips = data['bumenTips']
        ###############更新部门###############
        sqlstring0 = f"UPDATE jr_bumen SET bumenname='{bumen_name}',bumentips='{bumen_tips}' WHERE id= {bumen_id}"
        data0 = DBManager().executeQueryNO(sqlstring0)
        if  data0 == False:
            return_data = dict()
            return_data['code'] = 5000
            return_data['msg'] = "数据库连接异常!"
            return jsonify(return_data)
        if  data0 == True:
            return_data = dict()
            return_data['code'] = 200
            return_data['msg'] = "部门修改成功!"
            return jsonify(return_data)
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=8080, debug=True)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    1.关于数据库

    上例中的dbmanager 是本人自己写的数据库处理类,之前做过分享。
    文章链接:《python操作mysql数据库的精美实用模块》

    如果要用ORM,那就上Flask-SQLAlchemy库。

    (ORM,相关知识,自行百度)

    2.关于身份验证

    上例中的dsession_jwt_verification装饰器,是自定义的,用了第三方库:pyjwt。
    (JWT,相关知识,自行百度)

    from flask import request
    from flask import jsonify
    from flask import g
    from functools import wraps
    
    import jwt
    ############################################################
    # 装饰器管理模块
    ############################################################
    def session_jwt_verification(view_func):
        @wraps(view_func)  # wraps函数的作用是将wrapper内层函数的属性设置为被装饰函数view_func的属性
        def verify_view_func(*args, **kwargs):
            try:
                session_jwt = request.headers['session-jwt']
                payload = jwt.decode(session_jwt, "my_jwt_secret", algorithms=['HS256'])
                session_data = payload.get('userid')
                g.userid = session_data
            except Exception:
                return jsonify(code=5901, msg="身份认证失败!")
            ###################################################################################
            return view_func(*args, **kwargs)
        ###################################################################################
        return verify_view_func
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    3.关于路由

    实际项目中,路由这里有个问题,当我们的项目越来越大,API越来越多时,不可能把所有路由都写在一个主文件里面吧,这时就需要想办法拆分路由了。

    什么办法呢?就是蓝图BluePrint。对,蓝图的作用就是拆分路由。对于蓝图,有这个理解就够了。

    再配合工厂函数(对app进行统一加工处理的函数),最后的主文件变成了这样:

    from flask import Flask
    
    from Apis.login import login_api
    from Apis.userdata import userdata_api
    
    from Tools.config import config_map
    ####################################################################################################
    # 工厂函数,对app进行加工处理
    def create_app(config_name):
        app =Flask(__name__)
        app.config.from_object(config_map[config_name])
    
        ###注册API蓝图,并指定其对应的前缀(url_prefix)#######################
        app.register_blueprint(login_api, url_prefix="/api/login")
        app.register_blueprint(userdata_api, url_prefix="/api/userdata")
    
        ###初始化app的ORM,根据实际需要开启###################################
        # from app.models import db
        # db.init_app(app)
    
        ###初始化app的跨域,根据实际需要开启###################################
        # from flask_cors import CORS
        # cors = CORS()
        # cors.init_app(app)
    
        ###初始化app的邮件,根据实际需要开启###################################
        # from flask_mail import Mail
        # mail = Mail()
        # mail.init_app(app)
    
        return app
    
    
    
    app = create_app(config_name='development')
    #####首页视图函数,留着方便测试#############################################################
    @app.route('/')
    def index():
        return "Jrsoft Api Server"
    
    ##################################################################################
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=8080)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    整个项目的文件目录是这样:

    flask-example/
    ├── Apis
    │   ├── login.py
    │   └── userdata.py
    ├── Tools
    │   ├── config.py
    │   ├── dbmanager.py
    │   └── decoratormanager.py
    └── main.py
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    4.其他一些说明

    Flask做API服务后端,相关的知识点还是蛮多的,需要自己找资料,逐一消化理解。核心内容就是上述三块:路由,数据库,身份验证。

    当然,做API服务后端,还有一些其他框架,比较火爆强劲的就有FastAPI,大家可以了解一下,长得跟Flask有点像,但底层跟Flask不一样。(反正我没用,还是用的Flask)

    还有Flask项目本身的开发大神 李辉 做的API框架:APIFlask,可以关注一下,是基于Flask开发的。(这个框架成熟后,我会用起来)

    微信小程序的入门学习

    好了,后端Flask搞定,咱接着说前端,先说微信小程序吧,然后再说Vue。

    微信小程序,其官方文档就很详尽了,基本上看官方文档就足够了,当然根据自身情况,再去B站找些视频看看,辅助学习就可以了,没必要买书了。

    链接在此:微信小程序官方文档

    官方文档之中,有一份《小程序开发指南》,其实就是新手入门指南。入门必看!多看几遍!随着自身项目,边看边做边学,基本就会了。

    而开发指南之中,又有一小节,文档之中一笔带过,但是你绝不可错过,叫【2.3.6 官方样式库】。

    为了减轻开发者样式开发的工作量,我们提供了WeUI.wxss基础样式库。

    WeUI是一套与微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。包含button、cell、dialog、progress、toast、article、actionsheet、icon等各式原生。

    具体使用文档可参考:https://github.com/Tencent/weui-wxss

    作为独立开发者,假如没有这种东西,难道让我们自己去写样式去搞UI设计吗?这要开发到何年马月!

    类似WeUI,还有一个有赞出品的UI 组件库,也非常有名,美观而好用,叫:Vant
    Vant的官网:https://vant-contrib.gitee.io/vant-weapp
    文档很详尽,入手很简单,自己去看吧。

    Vue的入门学习

    Flask做API服务后端搞定了,微信小程序也学会搞定了,想着是时候回头搞网站了吧。

    Flask是web框架,本就是搞网站用的,搞网站就要用到Flask的网页渲染功能。

    Flask的网页渲染功能,主要靠的就是:Jinja2模板引擎和render_template渲染函数。

    学这块内容时,我是比较烦的,可能习惯了以前从事游戏开发时前后端分离的开发思维,这种前端夹着后端,傻傻分不清了,学着就有点难受,也不好学进去。

    想想我都用Flask做API服务后端,WEB开发前后端分离又是大势所趋,索性Flask的渲染不学了,火热的前端框架Vue搞起了!

    要学Vue,当然先要学Node.js,要会NPM。这Node.js的NPM就如同Python的pip,都是包管理工具。

    Vue之下,类似微信小程序的WeUI和Vant,有一个饿了么出品的UI组件库,也非常有名,叫:ElementUI。

    Vue有Vue2和Vue3两个版本,我直接用的Vue3,对应的ElementUI版本叫:ElementUI-plus。

    ElementUI-plus的官网:https://element-plus.gitee.io/zh-CN/

    另外,其实类似WeUI,Vant,ElementUI这样的UI样式库和组件库,还有不少,如:贤心的LayUI,阿里的 Ant Design

    在这里,真的要感谢这些UI样式库和组件库的分享公司,团队或大神,没有这些样式库和组件库,像我这样的个体开发者真的都不知道怎么在web开发上继续下去。

    之前,我在web开发上的学习,就是卡在了前端页面的构建上,内心形成了一种恐惧。而自从了解到有这些样式库和组件库的存在,前端瞬间变得轻松简单了,开发瞬间变得美好起来。

    Docker的入门学习

    前后端搞定,代码开发完成,最后当然要放到真正运行的服务器上,这就是部署了。

    高级的部署方法是基于容器进行部署。Docker 就是目前最流行的容器平台。

    (Docker ,相关知识,自行百度)

    微信小程序的部署,直接上传代码即可,下面主要分享Flask+Vue的网站部署

    1.项目目录结构
    myweb_project/
    │
    ├── flask
    │   ├── Dockerfile
    │   ├── gunicorn.config.py
    │   └── flask_app # flask项目的代码
    │
    ├── mysql
    │   ├── Dockerfile
    │   └── myweb.sql
    │
    ├── nginxvue
    │   ├── dist    # 打包的vue项目
    │   ├── Dockerfile
    │   └── nginx.conf
    │
    └──docker-compose.yml
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    2.Docker+Gunicorn 部署 flask后端

    gunicorn.config.py文件如下:

    import multiprocessing
    bind = '0.0.0.0:9191' # 监听内网端口80
    backlog = 512
    timeout = 30
    worker_class = 'gevent' # 工作模式协程
    workers = multiprocessing.cpu_count() * 2 + 1 # 并行工作进程数
    threads = 2               # 指定每个工作者的线程数
    
    
    pidfile = 'gunicorn.pid' # 设置进程文件目录
    loglevel = 'info'   # 设置日志记录水平
    access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
    accesslog = "gunicorn_access.log"      # 访问信息日志文件
    errorlog = "gunicorn_error.log"        # 错误信息日志文件
    reload=True  # 代码发生变化是否自动重启
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Dockerfile文件如下:

    FROM python:3.8
    WORKDIR /Project/jrsoftdemo
    COPY . .
    RUN pip install -r Tools/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
    CMD gunicorn  -k gevent   -w 5   -b 0.0.0.0:8080   backend:app
    
    • 1
    • 2
    • 3
    • 4
    • 5
    3.Docker+Nginx 部署 Vue前端

    nginx.conf文件如下:

    server {
        listen       8080;
        server_name  localhost;
        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;
            try_files $uri $uri/ /index.html;
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    
        location /api/ {  # 匹配api的,转发给后端,
            rewrite  /api/(.*)  /$1  break;
            proxy_pass http://192.168.99.100:9999;  # 这里是宿主机的ip
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Dockerfile文件如下:

    # 设置基础镜像
    FROM nginx
    
    # 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
    COPY dist/  /usr/share/nginx/html/
    
    #用本地的 nginx.conf 配置来替换nginx镜像里的默认配置
    COPY nginx.conf /etc/nginx/conf.d/default.conf
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    4.Docker部署 mysql数据库

    如果你的项目,数据库也需要Docker部署,当然也是可以的。
    Dockerfile文件如下:

    FROM mysql:5.7.20
    
    • 1

    部署成功之后,数据库软件通过IP连入,便可查看管理。

    5.Docker的相关命令
    # 创建镜像
    docker build -t  jrsoftflask  .  
    
    # 启动生产环境
    docker run -p 9999:9191  --name jrsoft_demo  -d jrsoftflask
    
    # 查看镜像
    docker images
    
    # 删除镜像
    docker rmi -f e7cd0fde3f42
    
    # 进入docker镜像环境
    docker run -it jrsoftflask /bin/bash
    
    # 列出运行容器
    docker ps
    
    # 列出全部容器
    docker ps -a
    
    # docker远程服务器部署——方案一:tar打包法
    # 生成tar
    docker save jrsoftflask>images.tar
    # 加载tar
    docker load < images.tar
    
    # docker远程服务器部署——方案二:镜像云仓库法
    # 将本地镜像推到[远程仓库]--DockerHub/阿里云Docker仓库/腾讯云Docker仓库
    docker push 178.104.162.39/dev/vdi-controller:arm0324
    # 从[远程仓库]拉取镜像--DockerHub/阿里云Docker仓库/腾讯云Docker仓库
    docker pull 178.104.162.39/dev/vdi-controller:arm0324
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    6.docker-compose编排

    像Flask+微信小程序,只需要用一个docker容器部署Flask就可以了,自然不需要docker-compose编排。

    而像Flask+Vue项目,用到多个docker容器,那用docker-compose编排,一键拉起,自然更加方便。

    docker-compose.yml文件如下:

    version: '3'
    services:
      mysql:
        build: ./mysql
        ports:
          - "3306:3306"
        container_name: mysql
        environment:
          - MYSQL_ROOT_PASSWORD=mypws123456789
        restart: always
    
      flask:
        build: ./flask
        ports:
          - "9999:9191"
        container_name: flask
        restart: always
        volumes:
         - "./flask/lab_app:/root/lab_app"
    
    
      nginx:
        build: ./nginxvue
        ports:
          - "8080:8080"
        container_name: nginxvue
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    # 启动命令
    docker-compose up -d
    
    • 1
    • 2
    7.注意事项

    Docker部署,需要注意每个容器的IP和端口,假若设置不对就连不上了。

    在docker-compose编排的时候,可进行相应的网络设置,上面文件并未涉及,大家可自行研究。

    自学方法

    1.git和github

    现在的程序员,git基本必学了,没什么好说的。一般用用的话,掌握几条命令就可以了

    # 创建仓库
    git init
    
    # 添加到暂存区
    git add .
    
    # 提交到仓库
    git commit -m '提交注释'
    
    # 关联远程仓库
    git remote add origin git@github.com:......
    
    # 推送到远程仓库
    git push -u origin master
    
    # 克隆远程仓库
    git clone git@github.com:......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    学习git,自然会用上github。github上好东西太多了,想找什么源码,尽管去上面搜索好了。

    所以,这里有个入门捷径:先去github,搜几个简单的项目源码,下载下来进行学习,看看别人都是怎么做的,最简单的项目是怎么搭建的,如此入门再好不过了!

    后面有时间有机会,我也会写几个入门项目源码,上传到github,届时分享给大家。

    2.自己的项目

    看别人的文章,看别人的视频,看别人的源码,终究是顺着别人的思维,看的时候貌似都会了,其实往往离真正会做还有一段距离。

    所以,这里有个入门捷径:学东西前,先有一个自己的项目,越现实越具体越好。
    不管是自己主动构想的项目,还是他人被动赋予的项目,都很好,只要有了项目,便有了明确的目标。
    然后边做边学,边学边做,学以致用,知行合一,如此最快,做才是真正的得到!

    3.目标拆分法

    目标往往很大,任务往往艰巨。不要怕,拆分他!

    目标拆分法是做事万能法,不管是做项目,还是学习,不管是写程序,还是写小说…

    目标越大,越需要拆分,拆分成一个个小目标,一个个可执行的不让人恐惧的小目标。

    然后一个小目标一个小目标的去完成,像做游戏任务一样,像玩游戏闯关一样,按部就班,逐个击破即可。

    这目标拆分法,也是管理学中的方法,也是游戏设计中的一大核心要义。

    游戏有四要素:目标,规则,反馈,自愿参与。

    你看,你将学习目标拆分成多个可执行的小目标后,还可以给每个小目标设定完成奖励,如此一来,你可以将学习转化为游戏一般好玩,这叫学习游戏化。

    写在最后,网站开发,我的心愿

    大约10年以前,不做游戏策划之后,便萌生了一个想法:要学会网站开发,做自己想做的网站。

    而在正式转做程序员之后,这个想法也便随之变得愈加强烈和执着,已然成为了人生的必达目标,人生的一个心愿。

    而且,时常心想:一个程序员,如果连网站开发都不会,当别人问你什么工作时,好意思跟别人说自己是程序员,是软件开发工程师吗?

    所以,很早以前,便看了html,css,javascript,但是看懂了又如何?真正搞起网站来,依然一脸懵逼。

    后来,为了搭建网站,也接触了wordpress等等各种搭建网站的工具,但这些毕竟都只是工具,并不是自己想要的能力——真正网站开发的能力。

    后来会了python,便开始学python的web框架django,可是对我来说django似乎太复杂了,起手学了两次,每次花了两三天还感觉门都没摸着,也便兴味索然,算了算了。

    后来工作之中,同事请我帮忙搭建一个API服务,那时我也不真正清楚什么是API服务,但我自信我大python啥不能干,网上一搜,短短几行代码便能搭建,so easy,便应下了同事的任务,帮忙完成了这个API服务。而这一次任务中,用的正是python的另一个web框架——flask。

    flask,短短几行代码,简单明了,便能搭建api服务,便能搭建网站,简直太棒了,一见钟情。

    于是,正式开始学习flask,以书本《Flask Web开发》(米格尔●格林贝格 著)为主要教材,以B站大神们分享的flask视频为辅助学习。

    《Flask Web开发》,逐字逐句阅读,逐行代码敲下,学了大半个月,仿佛都学下来了,其实很多概念并不清晰,很多东西把握不住。自己很清楚,真正动手去做,根本没把握独自开发一个网站,所以说到底,知识还是没有内化,功夫还是没有学到。于是,停了停,又放了一段时间。

    后来,那个同事又找我帮忙做微信小程序。微信小程序开发,我也是摸了好几次,也想学也是一直学不会,但现在有了flask的半吊子功夫,心里是有点底的,知道整体是怎么搭建的,都需要哪些知识技能,而且我内心太喜欢这种全新的实际项目了,因为我知道,在这种实际项目上,边做边学,又有项目的现实约束,学东西才是最快的。

    于是,接下来,大概一个月,我真正学会了微信小程序,学会了Flask,接着一个月,又学会了VUE前端开发,学会了docker,gunicorn,nginx部署,当然称不上完全了解和精通,但独立搭建网站已经没有问题了,更深入的原理知识根据实际需求再去了解即可。总之,当前的程度对我来说基本足够了,此生一个心愿也算了了。

    心愿已了,技能获得,内心欢喜,写下此文,以作总结,留做记录,分享于此。

  • 相关阅读:
    【51】分布式计算:如果所有人的大脑都联网会怎样?
    有没有不用加班的程序员 ?
    软件设计原则-接口隔离原则讲解以及代码示例
    golang之slice并发访问
    2023校招C++开发oppo笔试
    DevOps的未来趋势
    我的项目day01:创建项目的前端和后端,以及对前后端项目的基本配置
    如何优雅的使用contorller层
    Django框架之模型层(一)
    基于改进莱维飞行和混沌映射的粒子群优化BP神经网络预测股票价格研究(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/qq_20265805/article/details/126539261