zoukankan      html  css  js  c++  java
  • 纯手撸web框架

    纯手撸web框架

    一、Web应用的组成

    接下来我们学习的目的是为了开发一个Web应用程序,而Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览器,需要强调的一点是:S端由server和application两大部分构成,如图所示:

    上图:Web应用组成

    img

    二、手鲁web应用

    2.1 基本版

    import socket
    
    """
    @author RansySun
    @create 2019-10-18-11:59
    """
    
    # 创建服务端
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(5)
    
    while True:
        # 等待连接
        conn, addr = server.accept()
        
        # 接收浏览器发送的消息
        data = conn.recv(1024)
        print(data)
        # 请求行 请求头  空行 请求体, 返回响应首行
        conn.send(b'HTTP/1.1 200 OK 
    
     Hello web')
        conn.close()
    

    img

    2.2 根据请求地址,返回请求内容

    import socket
    
    """
    @author RansySun
    @create 2019-10-18-11:59
    """
    
    # 创建服务端
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(5)
    
    while True:
    
        # 等待连接
        conn, addr = server.accept()
    
        # 接收服务端发送消息
        data = conn.recv(1024)
        
        # 获取请求内容
        data = str(data, encoding="utf8").split(" ")[1]
        
        # 发送请求头
        conn.send(b'HTTP/1.1 200 OK 
    
     ')
        print(data)
    
        data = bytes(data, encoding="utf8")
        # 响应客户端
        conn.send(data)
    

    img

    img

    2.3 根据请求地址返回响应html

    <!-- index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>首页</h1>
    </body>
    </html>
    
    <!-- index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎来到鸡公煲, baby</h1>
    </body>
    </html>
    
    import socket
    
    """
    @author RansySun
    @create 2019-10-19-9:54
    """
    
    # 创建连接对象
    server = socket.socket()
    server.bind(("127.0.0.1", 8080))
    server.listen(4)
    
    while True:
    
        # 等待连接
        conn, addr = server.accept()
        data = conn.recv(1024)
    
        # 接收客户端请求
        data = str(data, encoding="utf8").split(" ")[1]
    
        print(data)
    
        # 发送请求头
        conn.send(b"HTTP//1.1 200 OK 
    
    ")
    
        # 判断请求对象
        if data == '/index':
    
            # 返回页面请求
            with open("index.html", "rb") as fr:
                conn.send(fr.read())
        elif data == '/login':
            with open("login.html", "rb") as fr:
                conn.send(fr.read())
        else:
            conn.send(b"<h1 style='color:red'>404 error</h1>")
    
    

    img

    img

    img

    到此为止.....

    img

    三、Web框架的由来

    综上案例我们可以发现一个规律,在开发S端时,server的功能是复杂且固定的(处理socket消息的收发和http协议的处理),而业务逻辑却各不相同(不同的软件就应该有不同的业务逻辑),重复开发复杂且固定的server是毫无意义的,有一个wsgiref模块帮我们写好了server的功能,这样我们便只需要专注于功能的编写

    3.1 简易版

    from wsgiref.simple_server import make_server
    
    """
    @author RansySun
    @create 2019-10-19-10:20
    """
    
    
    def run(env, response):
        """
    
        :param env: 请求相关的所有数据
        :param response: 对页面做出相关响应
        :return:
        """
    
        # 发送请求
        response("200 OK 
    
    ", [])
    
        # 响应页面
        res = 'hello web'
        print(env.get("PATH_INFO"))
        return [res.encode('utf8')]
    
    if __name__ == '__main__':
        server = make_server("127.0.0.1", 8080, run)
    
        # 实时监听地址,只要有客户端来连接, 统一交给run函数处理
        server.serve_forever()
    
    

    img

    3.2 根据请求做出响应

    <!-- index -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>首页</h1>
    </body>
    </html>
    
    
    <!-- login -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎来到鸡公煲, baby</h1>
    </body>
    </html>
    
    <!-- get_time -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    time
    <body>
    
    </body>
    </html>
    
    <!-- get_user -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <p>{{ user }}</p>
    <p>{{ user.name }}</p>
    <p>{{ user['pwd'] }}</p>
    <p>{{ user.get('hobby') }}</p>
    <h1></h1>
    <h1></h1>
    </body>
    </html>
    
    <!-- get_db -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-2">
                <h1 class="text-center"></h1>
                <table class="table table-bordered table-striped table-hover">
                   <thead>
                        <tr>
                            <th>id</th>
                            <th>x</th>
                            <th>y</th>
                        </tr>
                    </thead>
                    <tbody>
                    <tbody>
                        {% for user_dict in user %}
                            <tr>
                                <td>{{ user_dict.id }}</td>
                                <td>{{ user_dict.x }}</td>
                                <td>{{ user_dict.y }}</td>
                            </tr>
                        {% endfor %}
                    </tbody>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    # url.py
    from views import *
    """
    @author RansySun
    @create 2019-10-19-10:49
    """
    urls = [
        ('/index', index),
        ('/login', login),
        ('/xxx', xxx),
        ('/get_time', get_time),
        ('/get_user', get_user),
        ('/get_db', get_db),
    ]
    
    
    # views.py
    from datetime import datetime
    
    """
    @author RansySun
    @create 2019-10-19-10:49
    """
    
    
    def index():
        return "index"
    
    
    def login():
        return "login"
    
    
    def xxx():
        return "xxx"
    
    
    def error(env):
        return '404 error'
    
    
    def get_time():
        """
        获取时间
        :return:
        """
        data_time = datetime.now().strftime('%Y-%m-%d %X')
        with open(r"templates	ime.html", 'r', encoding='utf8') as fr:
            data = fr.read()
        data = data.replace("time", data_time)
        return data
    
    
    from jinja2 import Template
    
    
    def get_user():
        """
        前端通过字典获取用户信息
        :return:
        """
        dic = {'name': 'randy', 'pwd': '123123', 'hobby': ['read', 'running', 'music']}
        with open(r'templates/user.html', 'r', encoding="utf-8") as fr:
            data = fr.read()
        temp = Template(data)
        # 将字典dic传递给前端页面 页面上通过变量名user就能够获取到该字典
        res = temp.render(user=dic)
        return res
    
    
    import pymysql
    
    
    def get_db():
        mysql = pymysql.connect(
            host="127.0.0.1",
            user="root",
            password="root",
            charset="utf8",
            db="db1",
            autocommit=True
        )
    
        sql = "select * from a1"
    
        cursor = mysql.cursor(pymysql.cursors.DictCursor)
        cursor.execute(sql)
    
        res = cursor.fetchall()
        with open("templates/get_db.html", "r", encoding='utf8') as fr:
            data = fr.read()
        # print(res)
    
        temp = Template(data)
        data = temp.render(user=res)
        return data
    
    # wsgiref.py
    
    from wsgiref.simple_server import make_server
    from url import *
    from views import *
    
    """
    @author RansySun
    @create 2019-10-19-10:20
    """
    
    
    def run(env, response):
        """
    
        :param env: 请求相关的所有数据
        :param response: 对页面做出相关响应
        :return:
        """
    
        # 发送请求
        response("200 OK", [])
    
        # 获取连接请求后缀
        resp = env.get("PATH_INFO")
    
        # 用来存储后续匹配到的函数名
        func = None
    
        # 查找匹配的后缀函数
        for url in urls:
            if resp == url[0]:
                func = url[1]
                break
    
        # 判断func是否有值
        if func:
            res = func()
        else:
            res = error(env)
    
        return [res.encode('utf8')]
    
    
    if __name__ == '__main__':
        server = make_server("127.0.0.1", 8080, run)
    
        # 实时监听地址,只要有客户端来连接, 统一交给run函数处理
        server.serve_forever()
    
    

    至此,我们就针对web开发的开发自定义了一个框架,所以说框架的本质就是一系列功能的集合体、不同的功能放到不同的文件中。有了该框架,可以让我们专注于业务逻辑的编写,极大的提高了开发web应用的效率(开发web应用的框架可以简称为web框架),比如我们新增一个业务逻辑,要求为:浏览器输入http://127.0.0.1:8011/home 就能访问到home.html页面,在框架的基础上具体开发步骤如下:

    步骤一:在templates文件夹下新增home.html

    步骤二:在url.py的urls中新增一条映射关系

    urls = [
        ('/index', index),
        ('/timer', timer),
        ('/home', home), # 新增的映射关系
    ]
    

    步骤三:在views.py中新增一个名为home的函数

    def home(environ):
        with open('templates/home.html', 'r',encoding='utf-8') as f: 
            data = f.read()
        return data.encode('utf-8')
    

    我们自定义的框架功能有限,在Python中我们可以使用别人开发的、功能更强大的Django框架

    img

    img

    img

    img

    在当下的阶段,必将由程序员来主导,甚至比以往更甚。
  • 相关阅读:
    java基础-基本的输入与输出
    Java基础-位运算符Bitwise Operators
    Java基础-字符串连接运算符String link operator
    Java基础-赋值运算符Assignment Operators与条件运算符Condition Operators
    Java基础-逻辑运算符Logic Operators
    Java基础-比较运算符Compare Operators
    Java基础-算术运算符(Arithmetic Operators)
    NGUI裁剪模型和粒子
    编辑器插件数据保存之Serializable
    using语法糖
  • 原文地址:https://www.cnblogs.com/randysun/p/11708708.html
Copyright © 2011-2022 走看看