web应用
Posted ydz1993
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web应用相关的知识,希望对你有一定的参考价值。
web应用
目录
- 一:web应用程序是什么
- 二:基于socket写一个web应用
- 三:手撸简单web框架
一:web应用程序是什么
Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件。
应用程序的分类
-
C/S模式:C/S是客户端/服务器端程序,也就是说这类程序一般独立运行。
-
B/S模式:B/S就是浏览器端/服务器端应用程序,这类应用程序一般借助IE等浏览器来运行。WEB应用程序一般是B/S模式。
-
从本质上看:B/S模式也是C/S模式
Web应用程序的优点
- 网络应用程序不需要任何复杂的“展开”过程,你所需要的只是一个适用的浏览器;
- 网络应用程序通常耗费很少的用户硬盘空间,或者一点都不耗费;
- 它们不需要更新,因为所有新的特性都在服务器上执行,从而自动传达到用户端;
- 网络应用程序和服务器端的网络产品都很容易结合,如email功能和搜索功能;
- 因为它们在网络浏览器窗口中运行,所以大多数情况下它们是通过跨平台使用的 (例如Windows,Mac,Linux等等)
Web应用程序的缺点
- 网络应用程序强调浏览器的适用性。如果浏览器方没有提供特定的功能,或者弃用特定的平台或操作系统版本(导致不适用),就会影响大量用户;
- 网络应用依靠互联网远程服务器端的应用文件。因此,当连接出问题时,应用将不能正常使用。
- 许多网络应用程序不是开源的,只能依赖第三方提供的服务,因此不能针对用户定制化、个性化,而且大多数情况下用户不能离线使用,因而损失了很多灵活性;
- 它们完全依赖应用服务商的可及性。如果公司倒闭,服务器停止使用,用户也无法追索以前的资料。对比而看,即使软件制造商倒闭了,传统的安装软件也可以继续运行,尽管不能再更新或有其他用户服务;
- 相似地,提供方公司对软件和其功能有了更大的控制权。只要他们愿意就能为软件添加新特性,即使用户想等bugs先被解决再更新。跳过较差的软件版本也不可能了。公司可以强加不受欢迎的特性给用户,也可以随意减少带宽来削减开支。
- 公司理论上可以检索任何的用户行为。这有可能引起隐私安全问题。
B/S架构优点
浏览器/服务器架构(Browser/Server,简称B/S)能够很好地应用在广域网上,成为越来越多的企业的选择。浏览器/服务器架构相对于其他几种应用程序体系结构,有如下3方面的优点:
- 这种架构采用Internet上标准的通信协议(通常是TCP/IP协议)作为客户机同服务器通信的协议。这样可以使位于Internet任意位置的人都能够正常访问服务器。对于服务器来说,通过相应的Web服务和数据库服务可以对数据进行处理。对外采用标准的通信协议,以便共享数据。
- 在服务器上对数据进行处理,就处理的结果生成网页,以方便客户端直接下载。
- 在客户机上对数据的处理被进一步简化,将浏览器作为客户端的应用程序,以实现对数据的显示。不再需要为客户端单独编写和安装其他类型的应用程序。这样,在客户端只需要安装一套内置浏览器的操作系统,直接安装一套浏览器,就可以实现服务器上数据的访问。而浏览器是计算机的标准设备
总结一下,本质上:浏览器是一个socket客户端,服务器是一个socket服务端
二:编写web应用
基于socket写一个web应用
- 手撸web框架
# 手撸web框架.py
# 你可以将web框架理解成服务端
import socket
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
")
data = data.decode("urf-8") #字符串
# 获取字符串中特定的内容 正则 如果字符串有规律也可以考虑用切割
conn.send(b"HTTP/1.1 200 OK
")
current_path = data.split(" ").[1]
# print(current_path)
if current_path =="/index":
# conn.send(b"index heiheihei") #发送字符串
with open(r"template/01 myhrml.html","rb") as f: #发送文件
conn.send(f.read())
elif current_path =="/login":
conn.send(b"login")
else:
# 你直接忽略favicon.ico
conn.send(b"hello web")
conn.close()
# 01 myhtml.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1>你好啊 宝贝</h1>
</body>
</html>
- 不足之处
- 代码重复(服务端代码所有人都要重复写)
- 手动处理http格式的数据 并且只能拿到url后缀 其他数据获取繁琐(数据格式一样处理的代码其实也大致一样 重复写)
- 并发的问题
借助于wsgiref模块
# 02 基于wsgiref模块.py
from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run(env,response):
"""
env:请求相关的所有的所有数据
response:响应相关的所有数据
return:返回浏览器的数据·
"""
# print(env) #大字典,wsgiref模块帮你处理好http格式的数据 封装成了字典让你更加方便的操作
# 从env中取
response("200 ok",[]) #响应首行 响应头
current_path = env.get("PATH_INFO")
# if current_path =="/index":
#return [b"index"]
# elif current_path =="/login":
# return [b"login"]
# return [b"404 error"]
# 定义一个变量 存储匹配到的函数名
func = None
for url in urls: # url (),()
if current_path ==url[0]:
# 将url对应的函数名赋值给func
func = url[1]
break #匹配到一个之后 应该立即结束for 循环
# 判断func是否有值
if func:
res = func(env)
else:
res = error(env)
return [res.encode("utf-8")]
if __main__ =="__main__":
server=make_server("127.0.0.1",8080,run)
‘‘‘
会实时监听127.0.0.1:8080的地址 只要有客户端来了 都会交给run函数处理(加括号触发run函数的运行)
flask 启动源码
make_server("127.0.0.1",8080,obj)
__call__
‘‘‘
server.serve_forever() #启动服务器
from view import *
# url 与视图函数的对应关系
urls=[
("/index",index),
("/login",login),
("/xxx",xxx)
]
# views.py 文件
def index(env):
return "index"
def login(env):
return "login"
def xxx(env):
with open(r"templates/02 myxxx.html","r",encoding="utf-8") as f:
return f.read()
def error(env):
return "404 error"
- 文件拆分说明
urls.py 路由与视图函数对应关系
views.py 视图函数(后端业务逻辑)
templates文件夹 专门存放html文件
按照功能的不同拆分之后 后续添加功能只需要在urls.py书写对应关系 然后去views.py书写业务逻辑即可
动静态网页
静态网页
页面上的数据是直接写死的 万年不变
动态网页
数据是实时获取的
eg:
1.后端获取当前时间 展示到html页面上
2.数据从数据库中获取的 展示到html页面上
- 获取时间
#urls.py 文件
from view import *
# url 与视图函数的对应关系
urls=[
("/index",index),
("/login",login),
("/xxx",xxx)
("/get_time",get_time)
]
view.py文件
import datetime
def get_time(env):
current_time=datatime.datatime.new().strtime("%Y-%m-%d %X")
# 如何将后端获取的数据“传递”给html文件?
with open(r"templates/03 mytime.html","r",encoding="utf-8") as f:
data = f.read()
# data就算一堆字符串
data = data.replace("ooxx",current_time) #在后端将html页面处理好之后返回给前端
return data
temlates文件夹下 03 mytime.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1>我真的是一个html文件</h1>
ooxx
</body>
</html>
- 将一个字典传递给html文件 并且可以在文件上方便快捷的操作字典数据
- 借助于jinja2模块
from jinja2 import Template
def get_dict(env):
user_dict = {"username":"jason","age":18,"hobby":"read"}
with open(r"template/04 get_dict.html","r",encoding="utf-8") as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user=user_dic)
# get_dict.html 传递了一个值 页面上通过变量名user就能够拿到user_dict
return res
"""模版语法是在后端起作用的"""
# 模版语法(非常贴近python语法)
{{ user }}
{{ user.get(‘username‘)}}
{{ user.age }}
{{ user[‘hobby‘] }}
{% for user_dict in user_list %}
<tr>
<td>{{ user_dict.id}}</td>
<td>{{ user_dict.username}}</td>
<td>{{ user_dict.password}}</td>
<td>{{ user_dict.hobby}}</td>
</tr>
{% endfor%}
- 后端获取数据库中数据展示到前端页面
#urls.py 文件
from view import *
# url 与视图函数的对应关系
urls=[
("/index",index),
("/login",login),
("/xxx",xxx),
("/get_time",get_time),
("/get_dict",get_dict)
]
views.py文件
import pymysql
def get_user(env):
# 去数据库中获取数据 传递给html页面 借助于模版语法 发送给浏览器
conn = pymysql.connect(
host ="127.0.0.1",
port = 3306,
user = "root",
password ="123",
db="day059",
charset = "utf-8",
autocommit = True
)
cursor = conn.cursor(cursor = pymysql.cursors.DictCursor)
sql = "select * from t1"
affect_rows = cursor.execute(sql)
data_list = cursor.fetchall()
#将获取的数据传递给html文件
with open(r"templates/111.html","r",encoding="utf-8") as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user_list=data_list)
return res
templates文件下 111.html文件、
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 class = "text-center">用户数据</h1>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>ID</th>
<th>username</th>
<th>password</th>
<th>hobby</th>
</tr>
</thead>
<tbody>
{% for user_dict in user_list %}
<tr>
<td>{{ use_dict.id }}</td>
<td>{{ use_dict.username }}</td>
<td>{{ use_dict.password }}</td>
<td>{{ use_dict.hobby }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
自定义简易版本web框架请求流程图
wsgire 模块
1.请求来的时候解析http格式的数据 封装成大字典
2.响应走的时候给数据打包成符合http格式 再返回给浏览器
以上是关于web应用的主要内容,如果未能解决你的问题,请参考以下文章