Actix-web Rust Postgres database connection
Rust 1.39
supports asynchronous async
, await
, Actix-web in 2.0.0-alpha
support 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::block
the api, is not very convenient, I found a deadpool-postgres
connection pooling library, using tokio-postgres
a database connection. Direct support for asynchronous save a lot of trouble.
- deadpool-postgres
- a-postgres
- actix-web v:
2.0.0-alpha.4
Initialize the project
Directly cargo new pgtest
to 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 State
interpretation
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::Data
extractor 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 handler
database connection pool
Let us create a have web::Data
extractorhandler
I ran on the machine in a docker
running postgres
database
Create a users
table, 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 run
run.