当前位置: 首页 > news >正文

【从零开始的rust web开发之路 一】axum学习使用

系列文章目录

第一章 axum学习使用

文章目录

  • 系列文章目录
  • 前言
    • 老规矩先看官方文档介绍
    • 高级功能
    • 兼容性
  • 二、hello world
  • 三、路由
  • 四,handler和提取器
  • 五,响应


前言

本职java开发,兼架构设计。空闲时间学习了rust,目前还不熟练掌握。想着用urst开发个web服务,正好熟悉一下rust语言开发。
目前rust 语言web开发相关的框架已经有很多,但还是和java,go语言比不了。
这个系列想完整走一遍web开发,后续有时间就出orm,还有一些别的web用到的库教程。
言归正传,开始学习axum框架

老规矩先看官方文档介绍

Axum是一个专注于人体工程学和模块化的Web应用程序框架。

高级功能

使用无宏 API 将请求路由到处理程序。
使用提取程序以声明方式分析请求。
简单且可预测的错误处理模型。
使用最少的样板生成响应。
充分利用塔和塔-http生态系统 中间件、服务和实用程序。
特别是,最后一点是与其他框架的区别。 没有自己的中间件系统,而是使用tower::Service。这意味着获得超时、跟踪、压缩、 授权等等,免费。它还使您能够与 使用 hyper 或 tonic 编写的应用程序。axumaxumaxum

兼容性

Axum旨在与Tokio和Hyper配合使用。运行时和 传输层独立性不是目标,至少目前是这样。

tokio框架在rust异步当中相当流行。axum能很好地搭配tokio实现异步web

二、hello world

看看官方例子

use axum::{routing::get,Router,
};#[tokio::main]
async fn main() {// 构建routerlet app = Router::new().route("/", get(|| async { "Hello, World!" }));// 运行hyper  http服务 localhost:3000axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
}

要想使用还需要引入库

[dependencies]
axum = "0.6.19"
tokio = { version = "1.29.1", features = ["full"] }
tower = "0.4.13"

这时候就可以运行了,访问localhost:3000此时就能在页面看到Hello, World!

三、路由

路由设置路径有哪些handler去处理
handler可以理解为springboot开发当中的controller里面的方法

use axum::{Router, routing::get};// our router
let app = Router::new().route("/", get(root))  //路径对应handler.route("/foo", get(get_foo).post(post_foo)).route("/foo/bar", get(foo_bar));// 一个个handler
async fn root() {}
async fn get_foo() {}
async fn post_foo() {}
async fn foo_bar() {}

创建路由

Router::new()

说一些常用方法
nest方法可以嵌套一些别的路由

use axum::{routing::{get, post},Router,
};
let user_routes = Router::new().route("/:id", get(|| async {}));
let team_routes = Router::new().route("/", post(|| async {}));let api_routes = Router::new().nest("/users", user_routes).nest("/teams", team_routes);let app = Router::new().nest("/api", api_routes);
//此时有两个路径
// - GET /api/users/:id
// - POST /api/teams

其实就大致相当于springboot当中在controller类上设置总路径。
merge方法将两个路由器合并为一个

use axum::{routing::get,Router,
};// user路由
let user_routes = Router::new().route("/users", get(users_list)).route("/users/:id", get(users_show));
// team路由
let team_routes = Router::new().route("/teams", get(teams_list));// 合并
let app = Router::new().merge(user_routes).merge(team_routes);//  此时接受请求
// - GET /users
// - GET /users/:id
// - GET /teams

router可以接受多个handler方法,对于不同的请求方式

use axum::{Router, routing::{get, delete}, extract::Path};
let app = Router::new().route("/",get(get_root).post(post_root).delete(delete_root),
);
async fn get_root() {}
async fn post_root() {}
async fn delete_root() {}

如果你之前用过go语言中的gin框架,那么上手这个会简单很多

四,handler和提取器

handler是一个异步函数,它接受零个或多个“提取器”作为参数并返回一些 可以转换为响应。
处理程序是应用程序逻辑所在的位置,也是构建 axum 应用程序的位置 通过在处理程序之间路由。
它采用任意数量的 “提取器”作为参数。提取器是实现 FromRequest 或 FromRequestPart 的类型

例如,Json 提取器,它使用请求正文和 将其反序列化为 JSON 为某种目标类型,可以用来解析json格式

use axum::{extract::Json,routing::post,handler::Handler,Router,
};
use serde::Deserialize;
#[derive(Deserialize)]
struct CreateUser {email: String,password: String,
}
async fn create_user(Json(payload): Json<CreateUser>) {// 这里payload参数类型为CreateUser结构体,并且字段参数已经被赋值
}
let app = Router::new().route("/users", post(create_user));

注意需要引入serde 依赖

serde = { version = "1.0.176", features = ["derive"] }
serde_json = "1.0.104"

还有一些其他的常用的提取器,用于解析不同类型参数

use axum::{extract::{Json, TypedHeader, Path, Extension, Query},routing::post,headers::UserAgent,http::{Request, header::HeaderMap},body::{Bytes, Body},Router,
};
use serde_json::Value;
use std::collections::HashMap;// `Path`用于解析路径上的参数,比如/path/:user_id,这时候请求路径/path/100,那么user_id的值就是100,类似springboot当中@PathVariable注解
async fn path(Path(user_id): Path<u32>) {}// 查询路径请求参数值,这里转换成hashmap对象了,类似springboot当中@RequestParam注解
async fn query(Query(params): Query<HashMap<String, String>>) {}// `HeaderMap`可以获取所有请求头的值
async fn headers(headers: HeaderMap) {}//TypedHeader可以用于提取单个标头(header),请注意这需要您启用了axum的headers功能
async fn user_agent(TypedHeader(user_agent): TypedHeader<UserAgent>) {}//获得请求体中的数据,按utf-8编码
async fn string(body: String) {}//获得请求体中的数据,字节类型
async fn bytes(body: Bytes) {}//这个使json类型转换成结构体,上面的例子讲了
async fn json(Json(payload): Json<Value>) {}// 这里可以获取Request,可以自己去实现更多功能
async fn request(request: Request<Body>) {}//Extension从"请求扩展"中提取数据。这里可以获得共享状态
async fn extension(Extension(state): Extension<State>) {}//程序的共享状态,需要实现Clone
#[derive(Clone)]
struct State { /* ... */ }let app = Router::new().route("/path/:user_id", post(path)).route("/query", post(query)).route("/user_agent", post(user_agent)).route("/headers", post(headers)).route("/string", post(string)).route("/bytes", post(bytes)).route("/json", post(json)).route("/request", post(request)).route("/extension", post(extension));

每个handler参数可以使用多个提取器提取参数

use axum::{extract::{Path, Query},routing::get,Router,
};
use uuid::Uuid;
use serde::Deserialize;let app = Router::new().route("/users/:id/things", get(get_user_things));#[derive(Deserialize)]
struct Pagination {page: usize,per_page: usize,
}impl Default for Pagination {fn default() -> Self {Self { page: 1, per_page: 30 }}
}async fn get_user_things(Path(user_id): Path<Uuid>,pagination: Option<Query<Pagination>>,
) {let Query(pagination) = pagination.unwrap_or_default();// ...
}

提取器的顺序
提取程序始终按函数参数的顺序运行,从左到右。
请求正文是只能使用一次的异步流。 因此,只能有一个使用请求正文的提取程序
例如


use axum::Json;
use serde::Deserialize;#[derive(Deserialize)]
struct Payload {}async fn handler(// 这种是不被允许的,body被处理了两次string_body: String,json_body: Json<Payload>,
) {// ...
}

那么如果参数是可选的需要这么多,使用Option包裹

use axum::{extract::Json,routing::post,Router,
};
use serde_json::Value;async fn create_user(payload: Option<Json<Value>>) {if let Some(payload) = payload {} else {}
}let app = Router::new().route("/users", post(create_user));

五,响应

响应内容只要是实现 IntoResponse就能返回

use axum::{Json,response::{Html, IntoResponse},http::{StatusCode, Uri, header::{self, HeaderMap, HeaderName}},
};// 空的
async fn empty() {}// 返回string,此时`text/plain; charset=utf-8` content-type
async fn plain_text(uri: Uri) -> String {format!("Hi from {}", uri.path())
}// 返回bytes`application/octet-stream` content-type
async fn bytes() -> Vec<u8> {vec![1, 2, 3, 4]
}// 返回json格式
async fn json() -> Json<Vec<String>> {Json(vec!["foo".to_owned(), "bar".to_owned()])
}// 返回html网页格式`text/html` content-type
async fn html() -> Html<&'static str> {Html("<p>Hello, World!</p>")
}// 返回响应码,返回值空
async fn status() -> StatusCode {StatusCode::NOT_FOUND
}// 返回值的响应头
async fn headers() -> HeaderMap {let mut headers = HeaderMap::new();headers.insert(header::SERVER, "axum".parse().unwrap());headers
}// 数组元组设置响应头
async fn array_headers() -> [(HeaderName, &'static str); 2] {[(header::SERVER, "axum"),(header::CONTENT_TYPE, "text/plain")]
}// 只要是实现IntoResponse 都可以返回
async fn impl_trait() -> impl IntoResponse {[(header::SERVER, "axum"),(header::CONTENT_TYPE, "text/plain")]
}

关于自定义IntoResponse,看看ai怎么说

要自定义实现IntoResponse,按照以下步骤进行:
创建一个实现http::Response的结构体,该结构体将承载您的自定义响应对象。
创建一个impl块,实现IntoResponse trait。
在into_response方法中,根据需要生成您的自定义响应。

use axum::{http::{Response, StatusCode}, into_response::IntoResponse, response::Html};// 创建一个自定义响应对象
struct MyResponse(String);// 创建一个impl块,实现`IntoResponse` trait
impl IntoResponse for MyResponse {type Body = Html<String>;type Error = std::convert::Infallible;fn into_response(self) -> Response<Self::Body> {// 根据需要生成您的自定义响应Response::builder().status(StatusCode::OK).header("Content-Type", "text/html").body(Html(self.0)).unwrap()}
}

在上面的代码中,我们实现了一个名为MyResponse的自定义响应对象,并为其实现了IntoResponse trait。在into_response方法中,我们将自定义响应对象转换为一个HTML响应,并返回。

您可以像下面这样使用这个自定义响应对象:

async fn my_handler() -> impl IntoResponse {MyResponse("<h1>Hello, Axum!</h1>".to_string())
}

相关文章:

【从零开始的rust web开发之路 一】axum学习使用

系列文章目录 第一章 axum学习使用 文章目录 系列文章目录前言老规矩先看官方文档介绍高级功能兼容性 二、hello world三、路由四&#xff0c;handler和提取器五&#xff0c;响应 前言 本职java开发&#xff0c;兼架构设计。空闲时间学习了rust&#xff0c;目前还不熟练掌握。…...

oracle警告日志\跟踪日志磁盘空间清理

oracle警告日志\跟踪日志磁盘空间清理 问题现象&#xff1a; 通过查看排查到alert和tarce占用大量磁盘空间 警告日志 /u01/app/oracle/diag/rdbms/orcl/orcl/alert 跟踪日志 /u01/app/oracle/diag/rdbms/orcl/orcl/trace 解决方案&#xff1a; 用adrci清除日志 确定目…...

【vue】el-table 数据更新后,刷新表格数据

表格里面的数据更新后&#xff0c;可以通过以下方法来刷新表格 方法1 用更新后的数据&#xff0c;覆盖之前的数据 var newTableData[];for(var i0;i<that.tableData.length;i){ if(aIdthat.selectStationId&&bIdthat.selectDeviceId){that.tableData[i].physica…...

AVL——平衡搜索树

✅<1>主页&#xff1a;我的代码爱吃辣&#x1f4c3;<2>知识讲解&#xff1a;数据结构——AVL树☂️<3>开发环境&#xff1a;Visual Studio 2022&#x1f4ac;<4>前言&#xff1a;AVL树是对二叉搜索树的严格高度控制&#xff0c;所以AVL树的搜索效率很高…...

TCP通信流程以及一些TCP的相关概念

1.TCP和UDP区别 都为传输层协议 UDP&#xff1a;用户数据报协议&#xff0c;面向无连接&#xff0c;可以单播&#xff0c;多播&#xff0c;广播&#xff0c;面向数据报&#xff0c;不可靠 TCP&#xff1a;传输控制协议&#xff0c;面向连接的&#xff0c;可靠的&#xff0c;基…...

PyTorch学习笔记(十七)——完整的模型验证(测试,demo)套路

完整代码&#xff1a; import torch import torchvision from PIL import Image from torch import nnimage_path "../imgs/dog.png" image Image.open(image_path) print(image)# 因为png格式是四个通道&#xff0c;除了RGB三通道外&#xff0c;还有一个透明度通…...

WPF开篇

一、为什么要学习WPF 大环境不好&#xff0c;公司要求逐年提高&#xff0c;既要会后端又要会客户端WPF相对于WinForm来说用户界面效果更好&#xff0c;图像更加立体化也是给自己增加一项技能&#xff0c;谨记一句话&#xff0c;技多不压身&#xff1b;多一份技能就多一份竞争力…...

linux 压缩解压缩

压缩解压缩 linux中压缩和解压文件也是很常见的 zip格式 zip格式的压缩包在windows很常见&#xff0c;linux中也有zip格式的压缩包 #压缩#zip [选项] 压缩包名 文件(多个文件空格隔开)zip 1.zip 123.txt 456.txt zip -r 2.zip /home/user1 ---------------------- -r 压缩目录 …...

centos9 mysql8修改数据库的存储路径

一、环境 系统&#xff1a;CentOS Stream release 9 mysql版本&#xff1a;mysql Ver 8.0.34 for Linux on x86_64 (MySQL Community Server - GPL) 二、修改mysql的数据库&#xff0c;存储路径 查看目录数据存储的位置 cat /etc/my.cnf操作 1、新建存放的目录&#xff0c;…...

【C++】<Windows编程中消息即事件的处理>

目录 一、注册窗口类&#xff0c;指定消息处理函数&#xff0c;捕获消息并发给处理函数 二、消息处理函数 三、通用窗口消息 四、其他消息 1.滚动条消息 2.按钮控件消息 3.按钮控件通知消息 4.按键消息 5.系统菜单等消息 6.组合框控件消息 7.组合框控件通知消息 8.列…...

数据库SQL语句使用

-- 查询所有数据库 show databases; -- 创建数据库&#xff0c;数据库名为mydatabase create database mydatabase; -- 如果没有名为 mydatabase的数据库则创建&#xff0c;有就不创建 create database if not exists mydatabase; -- 如果没有名为 mydatabase的数据库则创建…...

从零开始 Spring Cloud 12:Sentinel

从零开始 Spring Cloud 12&#xff1a;Sentinel 1.初识 Sentinel 1.1雪崩问题 1.1.1什么是雪崩问题 微服务中&#xff0c;服务间调用关系错综复杂&#xff0c;一个微服务往往依赖于多个其它微服务。 如图&#xff0c;如果服务提供者I发生了故障&#xff0c;当前的应用的部分…...

@Resurce和@Autowired的区别

Resource 和 Autowired 是 Java 中常用的两个注解&#xff0c;用于自动装配依赖对象。它们的主要区别如下&#xff1a; 来源不同&#xff1a; Resource 是 Java EE 提供的注解&#xff0c;属于 J2EE 的一部分&#xff0c;它由 JSR-250 规范定义。 Autowired 是 Spring 框架提供…...

ResNet简介

ResNet (Residual Network) 此网络于2015年&#xff0c;国人何先生提出&#xff0c;用于解决随着深度学习的层数加深造成的网络退化现象和梯度消失、梯度爆炸。 问题1 退化现象 当深度学习的各项指标能够随着训练轮数收敛的情况下&#xff0c;网络的层数增强未能像理论一样&…...

了解单例模式,工厂模式(简单易懂)

文章目录 单例模式饿汉模式懒汉模式对比 工厂模式简单工厂模式&#xff08;Simple Factory Pattern&#xff09;工厂方法模式&#xff08;Factory Method Pattern&#xff09;抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;对比 单例模式 什么是单例&#xff…...

【中危】 Apache NiFi 连接 URL 验证绕过漏洞 (CVE-2023-40037)

漏洞描述 Apache NiFi 是一个开源的数据流处理和自动化工具。 在受影响版本中&#xff0c;由于多个Processors和Controller Services在配置JDBC和JNDI JMS连接时对URL参数过滤不完全。使用startsWith方法过滤用户输入URL&#xff0c;导致过滤可以被绕过。攻击者可以通过构造特…...

【Git版本控制工具使用---讲解一】

Git版本控制工具使用 安装设置用户名签名和邮箱Git常用的命令 初始化本地库查看本地状态Git 命令添加暂存区提交本地库查看版本信息修改文件版本穿梭 安装 首先根据自身电脑的配置选择性的安装是32位的还是64位的Git版本控制工具 我这边安装的是64位的 以下是我安装的时候的过…...

NLP | 基于LLMs的文本分类任务

比赛链接&#xff1a;讯飞开放平台 来源&#xff1a;DataWhale AI夏令营3&#xff08;NLP&#xff09; Roberta-base&#xff08;BERT的改进&#xff09; ①Roberta在预训练的阶段中没有对下一句话进行预测&#xff08;NSP&#xff09; ②采用了动态掩码 ③使用字符级和词级…...

攻防世界-base÷4

原题 解题思路 base644&#xff0c;莫不是base16&#xff0c;base16解码网站&#xff1a; 千千秀字...

【Java转Go】快速上手学习笔记(三)之基础篇二

【Java转Go】快速上手学习笔记&#xff08;二&#xff09;之基础篇一 了解了基本语法、基本数据类型这些使用&#xff0c;接下来我们来讲数组、切片、值传递、引用传递、指针类型、函数、map、结构体。 目录 数组和切片值传递、引用传递指针类型defer延迟执行函数map结构体匿名…...

【vue 引入pinia与pinia的详细使用】

vue引入pinia与使用 安装引入使用定义 store在组件中使用 store在插件中使用 store配置 store 总结 Pinia 是一个用于 Vue 3 的状态管理库&#xff0c;其设计目标是提供一个简单、一致的 API 和强类型支持。下面介绍如何引入 Pinia 并使用它。 安装 npm install pinia引入 在…...

USACO18DEC Fine Dining G

P5122 [USACO18DEC] Fine Dining G 题目大意 有一个由 n n n个点 m m m条边构成的无向连通图&#xff0c;这 n n n个点的编号为 1 1 1到 n n n。前 n − 1 n-1 n−1个点上都有一头奶牛&#xff0c;这些奶牛都要前往 n n n号点。第 i i i条边连接 a i a_i ai​和 b i b_i bi​…...

fckeditor编辑器的两种使用方法

需要的资源包我放我资源里了&#xff0c;不要积分 https://download.csdn.net/download/wybshyy/88245895 首先把FredCK.FCKeditorV2.dll添加到引用 具体方法如下&#xff0c;一个是客户端版本&#xff0c;一个是服务器端版本 客户端版本&#xff1a; <% Page Language…...

数据结构,查找算法(二分,分块,哈希)

一、查找算法 1、二分查找:(前提条件: 必须有序的序列) #include <stdio.h> //二分查找 value代表的是被查找的值 int findByHalf(int *p, int n, int value) {int low = 0;//low低int high = n-1;//high高int middle;//用来保存中间位置的下标while(low <= high…...

C++(Qt)软件调试---gdb调试入门用法(12)

gdb调试—入门用法&#xff08;1&#xff09; 文章目录 gdb调试---入门用法&#xff08;1&#xff09;1、前言1.1 什么是GDB1.2 为什么要学习GDB1.3 主要内容1.4 GDB资料 2、C/C开发调试环境准备3、gdb启动调试1.1 启动调试并传入参数1.2 附加到进程1.3 过程执行1.4 退出调试 4…...

shell和Python 两种方法分别画 iostat的监控图

在服务器存储的测试中,经常需要看performance的性能曲线&#xff0c;这样最能直接观察HDD或者SSD的性能曲线。 如下这是一个针对HDD跑Fio读写的iostat监控log,下面介绍一下分别用shell 和Python3 写画iostat图的方法 1 shell脚本 环境:linux OS gnuplot工具 第一步 :解析iosta…...

设计模式(9)建造者模式

一、 1、概念&#xff1a;将一个复杂对象的构造与它的表示分离&#xff0c;使得同样的构造过程可以创建不同的表示。建造者模式主要用于创建一些复杂的对象&#xff0c;这些对象内部构建间的顺序通常是稳定的&#xff0c;但对象内部的构建通常面临着复杂的变化&#xff1b;建造…...

PHP 创业感悟交流平台系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 创业感悟交流平台系统&#xff08;含论坛&#xff09;是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 源码下载&#xff1a; https://download.csdn.…...

工作流程引擎之flowable(集成springboot)

0、背景 现状&#xff1a;公司各部门业务系统有各自的工作流引擎&#xff0c;也有cross function的业务在不同系统或OA系统流转&#xff0c;没有统一的去规划布局统一的BPM解决方案&#xff0c;近期由于一个项目引发朝着整合统一的BPM方案&#xff0c;特了解一下市面上比较主流…...

leetcode54. 螺旋矩阵(java)

螺旋矩阵 题目描述解题 收缩法 上期经典算法 题目描述 难度 - 中等 原题链接 - leecode 54 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7…...

网站需要在公安局备案/外包网络推广公司

成为经理人的捷径 (一) 其实世界上没有一步登天的捷径&#xff0c;“条条大路通罗马。”选择哪条、怎么走完全是个人的意愿。要能找一条最适合自己的路&#xff0c;想成为高效的经理人&#xff0c;就要靠有效的方法。接下来我们就围绕着这个“方法”展开简单的讨论。 高的效绩是…...

天津网站建设zmad/最近最新的新闻

现在微信已经关闭了QQ号和邮箱注册的功能&#xff0c;那如何才能用邮箱登陆微信呢&#xff1f;下面小编以TOM邮箱为例&#xff0c;分享一下邮箱登录微信的具体操作~ 1、打开微信&#xff0c;点击注册&#xff0c;默认为手机号注册。输入手机号注册一个账号&#xff08;只用手机…...

什么程序做教育网站好/网站提交收录软件

本博文介绍如何使用 UTL_SMTP来发送邮件UTL_SMTP是基于SMTP协议来发送邮件1、需要安装UTL_SMTP包要利用oracle的系统包实现发送邮件的功能&#xff0c;必须先以sys用户登录执行以下两个脚本&#xff1a;$ORACLE_HOME/rdbms/admin/utlsmtp.sql$ORACLE_HOME/rdbms/admin/utltcp.s…...

wordpress写书typecho主题/推广普通话的意义

collection   定义命名元祖,让元祖的每个元素可以通过类似对象属性的方法用".属性"及其方便的取值.  定义可前后拿取值且可迭代的双端队列  定义有顺序的字典  定义有默认值的字典ps:  队列 &#xff1a;先进先出  堆栈 &#xff1a;先进后出具体用到的或…...

动态页网站/网络营销师报考条件

一同事的朋友正在参加笔试&#xff0c;遇到这么一个问题让他帮忙解决&#xff0c;结果同事又找到我帮他搞定。真是感慨&#xff1a;通讯发达在某些方面来说&#xff0c;真不知是不是好事啊&#xff01;题目大致如下所示&#xff0c;一般我们使用ifconfig查看网卡信息&#xff0…...

做暧暧网站免费/官网首页入口百度

褚时健“烟王”到“橙王”&#xff1b;顾雏军“十大经济人物”到“帝国崩塌”&#xff1b;郑俊怀“乳业教父”到“争议不断”&#xff1b;还有冯鑫由“暴风主宰”变成“身陷风暴”。 从“红塔山”到“暴风”&#xff0c;1999到2019&#xff0c;相似的一幕跨越20年依旧在上演。…...