发布日期:2024-01-04 15:57浏览次数:
作为一个主攻后端研究的码狗来说,前端在我心中一直是那么的神秘而又高大上,什么vue框架啦,什么javasript,css,html啦,虽然都有所了解但是其实一直不知道从哪入手,也就一直没有了解。然而最近我在写一个c++网络库(hfh1999/feipu: a network library ,inspired by muduo),在写到http模块时,突然发觉自己对后端和前端的的交互并不熟悉,于是就决定自己来写一个简单的网站,从而了解前后端的交互过程。下面让我们开始吧:)
这个小项目的示例可以在hfh1999/fei_blogs: 写一个简单的博客网站中找到。
关于后端语言的话,由于我没学过java,又鉴于C++后端薄弱的生态,于是我选择了我最钟爱的rust-lang。那么还需要再选择一个好用的后端框架。经过我“严密”地调查后,最终选定使用axum - crates.io: Rust Package Registry作为后端框架。axum是基于tokio异步io框架的web框架,所以其io性能可以得到充分地保证,而其使用也比较简便,文档也较为详细,像我这种新手只研究了半天就明白了其基本的使用。
由于我没有精力将前端的所有知识都学一遍,于是只好借助于前端框架。当然了前端框架也是有许多选择的,常用的有vue,网站建设策划书react等等。但是,先等一下,像我这样懒的人怎么会花那么大的精力去学习vue和react呢:)?经过搜索,很快发现了我的目标:amis,这个前端框架利用低代码的思想,只需要在网页中利用json配置就可以很好地呈现出不同的效果,更完美的是,它还有个可视化编辑器!
可视化编辑器
在可视化编辑器中设计好后就可以提取出相应的json代码,把json代码粘贴进框架里的html页面即可。amis的一些部件会在一些条件发出request,比如按钮会在按下时发出请求,而增删改查部件则会在初始化时发出请求,在框架里都用api字段表示,可以在api字段配置request的类型及发出的request的格式。像我下面的主页中的增删改查部件就会在初始化时发出get请求,且其url的参


下面是写(拖)出来的主界面,从上往下分别是标题栏,文本区域,两个按钮,和增删改查组件:
写出来的主界面
点击绿色按钮时会跳转到留言页面,下面是写出来的留言页面:
image.png
主页面有两个部分需要注意:
绿色按钮,会触发网页重定向,向服务器请求(GET)新的页面;
增删改查组件(就是哪个表格状的东西),这个组件在初始化时也会向服务器发送请求(GET)。
留言见面只有一个部分需要注意:
在点击提交按钮的时候会向服务器发送请求(POST)来提交表单。
rust是一个复杂的语言,后端技术更是一个复杂的技术栈,但是两者一组合,没想到世界居然突然就变得美好了,当然了这一切都要多谢那些开源世界的大佬们,他们帮我们处理好了所有的复杂细节,于是我们就只需要考虑业务代码了。
我们在这个小项目里用到的后端框架是axum框架,来一小段代码来展示以下axum的使用:
大家看到这么多稀奇古怪的表达,未免觉得无从下手,不过我们只需要看最核心的一个表达式:
这就是一个最简单的处理,意思是假若请求的url指向"push_text" 且请求类型为post时就利用get_text进行处理。route方法就是axum的一个核心的概念,把请求想象成流水,route方法就是水管上一个个不同位置的洞,当满足相应条件时就会从洞中流出,进入到相应的处理函数,然后再返回给客户。
我们再看下这个最简单例子的处理函数:
让我们从上往下分析以下这个处理函数:
http的数据在1处进行解析,通过Json
发送来的数据经过解析后,我们需要处理,这里我们只是简单地在服务端打印到标准输出中。紧接着来到2处,这里需要稍微介绍下,为什么要定义Return这样一个样式的数据结构呢?这并不是我们自作主张,主要是因为前端框架amis需要服务器在收到请求后回复的格式形如下面的json结构:
于是我们不得不定义Return为下面的类型以进行序列化。(关于序列化和反序列化这部分,建议看看rust的序列化/非序列化生态:serde - crates.io: Rust Package Registry)下面是Return的定义:
然后在3处,我们构造一个http回复,这也是由框架自动完成的,我们只需要返回一个实现trait的类型就可以了,我们这里返回一个元组:
元组类型已经被自动实现了trait,这里的含义是返回的恢复的返回码是201(CREATED),搭载的数据是json格式数据,且数据由类型Return序列化而成。
那么这个后端框架的基本使用我们就学会了,于是我们编写一些新的router和新的router处理函数来应付不同的请求就可以了。当然了,我们这样远不能称为网站,因为我们只是写了一个个api等待来自客户端的http消息而已。但是,我们完全可以离线实验一下是否能成功连接到后台。我们从文件夹中打开编写好的index.html文件,然后惊喜地发现果然在浏览器中显示出了好看的界面,于是点击按钮向服务器发起请求==> 提示错误。为什么呢?
于是打开浏览器的开发者面板,重新发起请求,发现浏览器根本没有按照预料发起get和post请求,竟然意外地发送了OPTIONS。这是为什么呢?经过搜索,我终于明白了关键所在,我的网页是在本地资源上,而服务器是设置在共有ip上的,这样http请求就"跨域请求资源"了,自然要发出OPTION
S请求,而我的服务器代码根本没有处理OPTIONS的,自然出现错误了。想到这,我们的改进方法就很好办,我们需要实现网页资源也从服务器上获取,这样网页和服务器资源就在同一个域上了。网页服务很简单,基本原理就是浏览器通过get请求请求相应文件的过程,本质上就是提供一个文件的下载服务。主要过程只要从url中解析出需要的文件的路径,根据路径找到相应文件然后将文件内容放到数据段返回给浏览器就可以了。但是有一个关键的地方需要我们尤其注意,那就是我们需要在http回复的content-type字段填写相应的文件类型。这可就有些困难了,首先文件类型有许多种,我们很难自己处理,其次每次都在http恢复中设置content-type也很麻烦。
第一个想到的方案就是在crates.io中搜索有关content-type的库,果然让我们找到了,利用mime-guess来判断文件类型,利用mime来确定相应类型的字符串形式。这样得到相应的文件的类型后我们就在回复中填入相应的字符串即可。不过,慢着,这是否有些不对劲?
再看看我们的第二个方案,我们可以利用几行代码就完成这样一个服务:
我们增加下面几个router即可,利用rust强大的web生态,为route增加几个service,也就是在route中更改get为get_service即可,然后利用从tower_http库中的services模块中的ServeFile,和ServeDir服务就可以实现这一目标,至于为什么突然出现,还请大家观看axum的官方文档。这两个服务的主要流程和我上面的方案一样,但是既然别人已经写好了而且很好用,为什么不用呢?
我们在编译运行服务器,然后在浏览器中输入127.0.0.1回车,果然一个"精美"的网站就出现了,而且向服务器请求数据和发送数据都完全正常!这就是一个简单的网站的搭架,对于不会前端的同学来说是不是很简单呢?
原创文章出自IM电竞,欢迎转载!