Actix-web Rust Postgres database connection

Actix-web Rust Postgres database connection

Rust 1.39supports asynchronous async, await, Actix-web in 2.0.0-alphasupport native asynchronous writing, so as used herein, Actix-web version 2.0.0-alpha.4.

Actix-web official r2d2 example uses connection pooling library, which is not the asynchronous library need to use web::blockthe api, is not very convenient, I found a deadpool-postgresconnection pooling library, using tokio-postgresa database connection. Direct support for asynchronous save a lot of trouble.

Initialize the project

Directly cargo new pgtestto initiate a project

modifyCargo.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"

Modify the default main method

The official server is running asynchronous actix use actix-rt library, as follows

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

Create a connection pool 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个连接
}

Bound connection pool object

actix-web official document of Stateinterpretation

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.

We can bind objects into the Application, all share the same path with the same name space and resources, and then after the web::Dataextractor to obtain.

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
}

In the handlerdatabase connection pool

Let us create a have web::Dataextractorhandler

I ran on the machine in a dockerrunning postgresdatabase

Create a userstable, there is a field [id, name, age] example only gets 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)
}

The handler is bound to the 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

Through the cargo runrun.

Guess you like

Origin www.cnblogs.com/b612/p/12026805.html