Actix-web Rust连接Postgres数据库

Actix-web Rust连接Postgres数据库

​ Rust1.39支持了异步async,await,Actix-web在2.0.0-alpha支持了原生异步写法,所以本文中使用的Actix-web版本为2.0.0-alpha.4

​ Actix-web官方例子使用的是r2d2连接池库,这个库并不是异步库,需要用web::block的api,不是很方便,我找到了一个deadpool-postgres连接池库,采用tokio-postgres作为数据库连接。直接支持异步省去很多麻烦。

初始化项目

直接用cargo new pgtest来初始化一个项目

修改Cargo.toml

[package]
name = "pgtest"
version = "0.1.0"
authors = ["yuxq"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "2.0.0-alpha.4"
# actix运行时
actix-rt = "1.0.0-alpha.3" 
tokio-postgres = "0.5.0-alpha.2"
deadpool-postgres = "0.2.3"

修改默认main方法

官方运行异步actix服务器是使用actix-rt库,方法如下

#[actix_rt::main]
async fn main()-> std::io::Result<()> {
        HttpServer::new( ||
        App::new()
        .bind("127.0.0.1:8080")?
        .start()
        .await
}

创建postgres连接池

use deadpool_postgres::{Manager, Pool};
use tokio_postgres::{Config, NoTls};

#[actix_rt::main]
async fn main()-> std::io::Result<()> {
    let mut cfg = Config::new();
    cfg.host("localhost");//数据库地址
    cfg.user("db");//数据库用户名
    cfg.password("db");//数据库密码
    cfg.dbname("asynctest");//数据库名称
    let mgr = Manager::new(cfg, tokio_postgres::NoTls);
    let pool = Pool::new(mgr, 15);//最大15个连接
}

绑定连接池对象

actix-web官方文档对State的解释

Application state is shared with all routes and resources within the same scope. State can be accessed with the web::Data extractor. State is also available for route matching guards and middlewares.

我们可以把对象绑定进Application,同所有具有相同命名空间的路径和资源共享,之后再用web::Data提取器获取到。

use deadpool_postgres::{Manager, Pool};
use tokio_postgres::{Config, NoTls};

#[actix_rt::main]
async fn main()-> std::io::Result<()> {
    let mut cfg = Config::new();
    cfg.host("localhost");//数据库地址
    cfg.user("db");//数据库用户名
    cfg.password("db");//数据库密码
    cfg.dbname("asynctest");//数据库名称
    let mgr = Manager::new(cfg, tokio_postgres::NoTls);
    let pool = Pool::new(mgr, 15);//最大15个连接
    
    HttpServer::new( move ||
        App::new().data(pool.clone())
        .bind("127.0.0.1:8080")?
        .start()
        .await
}

handler中获取数据库连接池

首先让我们创建一个具有web::Data提取器的handler

我在本机上跑了一个docker运行postgres数据库

创建了一个users的表,字段有【id,name,age】例子只获取name

use actix_web::{web,Responder};
use deadpool_postgres::{Manager, Pool};

async fn get_user(db:web::Data<Pool>)->impl Responder{
    let mut conn=db.get().await.unwrap();
    let rows=conn.query("select * from users",&[]).await.unwrap();
    let v:String=rows[0].get("name");//get参数可以是str,也可以是i32,获取第几个。但是必须要指明获取的类型
    format!("{}",v)
}

将handler绑定至server application

    HttpServer::new( move ||
        App::new().data(pool.clone()).route("user",web::get().to(get_user))
        .bind("127.0.0.1:8080")?
        .start()
        .await

通过cargo run运行即可。

猜你喜欢

转载自www.cnblogs.com/b612/p/12026805.html