天天看点

rust的actix web框架试试手(json数据传输和接受,数据库操作,rust后端操作)

文章目录

##Actix Web(RUST)

###代码

main.rs

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    <script>
        $(document).ready(function() {

            $("#btn").click(function() {
                alert(true)
                $.ajax({
                    type: "POST",
                    url: 'http://127.0.0.1:8088/app',
                    async:true, // 使用同步方式
                    // 1 需要使用JSON.stringify 否则格式为 a=2&b=3&now=14...
                    // 2 需要强制类型转换,否则格式为 {"a":"2","b":"3"}
                    data: JSON.stringify({
                        name: $("#name").val(),
                        card_id: $("#card_id").val(),
                        gender: $("#gender").val(),
                        class: parseInt($("#class").val()),
                        age: parseInt($("#age").val())
                    }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data) {
                        $('#result').text(data.result);
                    } // 注意不要在此行增加逗号
                });
                return false
            })
            $("#re").click(function () {
                alert(true)
                $.ajax({
                    type: "POST",
                    url: 'http://127.0.0.1:8088/rp',
                    async: false, // 使用同步方式
                    // 1 需要使用JSON.stringify 否则格式为 a=2&b=3&now=14...
                    // 2 需要强制类型转换,否则格式为 {"a":"2","b":"3"}
                    data: JSON.stringify({
                            name:"name"
                    }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data) {
                       $("#name").val(data.name),
                            $("#card_id").val(data.card_id),
                            $("#gender").val(data.gender),
                           $("#class").val(data.class),
                           $("#age").val(data.age)
                    } ,// 注意不要在此行增加逗号
                    error: function() {
                       alert("失败")
                    }

                });
                return false
            })
        })
    </script>
</head>
<body>
<form type=”button”>
    <input id="name">姓名
    <input id="card_id">card_id
    <input id="gender">gender
    <input id="class">class
    <input id="age">age

</form>
<button id="btn">tip</button>
<br>
<button id="re">ppp</button>
</body>
</html>
           

stu.rs

use mysql as my;
use serde_derive::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Eq, Deserialize,Serialize)]
pub struct student_info {
    pub name: String,
    pub card_id: String,
    pub gender: String,
    pub class: i32,
    pub age: i32,
}

impl student_info {
    pub fn new(name: String, card_id: String, gender: String, class: i32, age: i32) -> student_info {
        student_info {
            name: name,
            card_id: card_id,
            gender: gender,
            class: class,
            age: age
        }
    }
}
impl student_info {
    pub fn copy(sp:&student_info) -> student_info {
        student_info {
            name: sp.name.clone(),
            card_id: sp.card_id.clone(),
            gender: sp.gender.clone(),
            class: sp.class.clone(),
            age: sp.age.clone()
        }
    }
}
pub fn stu_select()->Vec<student_info>{
    let pool = my::Pool::new("mysql://root:[email protected]:3306/studentinfo").unwrap();

    let mut selected_payments:Vec<student_info> =
        pool.prep_exec("SELECT  *  from stuinfo limit 1", ())
            .map(|result|
                {
                    result.map(|x| x.unwrap()).map(|row|{
                        let (name, card_id, gender,class,age) = my::from_row(row);
                        student_info {
                            name: name,
                            card_id: card_id,
                            gender: gender,
                            class:class,
                            age:age
                    }
                    }).collect()
                }
            ).unwrap();
    selected_payments
}

pub fn stu_insert(v: student_info) {
    let pool = my::Pool::new("mysql://root:[email protected]:3306/studentinfo").unwrap();
    for mut stmt in pool.prepare(r"INSERT INTO stuinfo
                                       (stuname, card_id, gender,class,age)
                                   VALUES
                                       (:name, :card_id, :gender,:class,:age)").into_iter() {

        stmt.execute(params! {
                "name" => &v.name,
                "card_id" => &v.card_id,
                "gender" => &v.gender,
                "class" => &v.class,
                "age" => &v.age,
            }).unwrap();
    }
}
           

###解释部分

####后端启动器

HttpServer::new(|| App::new()
        .data(AppState {
            foo: "bar".to_string(),
        })
        .service(stream)
        .default_service(web::resource("").route(web::get().to(p404)))
        .service(fs::Files::new("/static", "static").show_files_listing())
        .service(inlex)
        .service(web::resource("/form").route(web::get().to(index2)))
        .service(web::resource("/post1").route(web::post().to(handle_post_1)))
        .service(web::resource("/post2").route(web::post().to(handle_post_2)))
        .service(web::resource("/app").route(web::post().to(hand_app)))
        .service(web::resource("/post3").route(web::post().to(handle_post_3)))
        .service(web::resource("/rp").route(web::post().to(replay)))
//        .service(web::resource("/tx").route(web::post().to(index)))

        )
        .bind("127.0.0.1:8088")
        .unwrap()
        .run()
        .unwrap();
           

可以看的出来这个代码部分的结构很明确,就是app。service(映射地址)路由到函数部分。(当然这个有贼多个方式表示,自此不一一列举)

然后可以看到绑定端口,然后在跑起来。

#####函数部分

1.返回json到ajax

fn replay(req:HttpRequest,item: web::Json<plic>)->Result<Json<stu::student_info>>{

    let p=stu::stu_select();
    println!("{:#?}",p);
    println!("{:#?}",req);
    Ok(Json(stu::student_info::copy(&p[0])))
}
           

可以看到这里的参数有2个一个是json一个是req,req没有用我只是单纯想看看输出数据的。

他的返回是一个结果集以json的方式返回,

这里stu_select是数据库提取器。

2.表单类型

fn handle_post_1(params: web::Form<MyParams>) -> Result<HttpResponse> {

    Ok(HttpResponse::Ok()
        .content_type("text/plain")
        .body(format!("Your name is {}", params.name)))
}
           

可以看出其实结构都差不多,就是参数的类型不同,这个其实就是一个form表单的类型了。

3.静态文件直接访问

ttpServer::new(|| App::new()
        .data(AppState {
            foo: "bar".to_string(),
        })
        .service(stream)
        .default_service(web::resource("").route(web::get().to(p404)))
        .service(fs::Files::new("/static", "static").show_files_listing())
        ...//省略掉run的部分
           

这里创建了一个static的文件夹,里面放的静态文件,这样就可以直接访问这个文件夹的文件了。

4.如何返回一个HTML页面

#[get("/welcome")]
fn stream(req: HttpRequest) -> Result<HttpResponse>{
    Ok(HttpResponse::build(StatusCode::OK)
        .content_type("text/html; charset=utf-8")
        .body(include_str!("../static/index.html")))
}
           

这里可以直接使用#[get("/url)]来直接寻址,或者你也可以用之前的方法效果是一样的。

他的写法也有些不同,是.service(stream)就行了,就个人习惯而言。等会说说可能碰到的错误。

####前端部分

Ajax接受和返回参数

1.前端接受参数

$("#re").click(function () {
                alert(true)
                $.ajax({
                    type: "POST",
                    url: 'http://127.0.0.1:8088/rp',
                    async: false, // 使用同步方式
                    // 1 需要使用JSON.stringify 否则格式为 a=2&b=3&now=14...
                    // 2 需要强制类型转换,否则格式为 {"a":"2","b":"3"}
                    data: JSON.stringify({
                            name:"name"
                    }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data) {
                       $("#name").val(data.name),
                            $("#card_id").val(data.card_id),
                            $("#gender").val(data.gender),
                           $("#class").val(data.class),
                           $("#age").val(data.age)
                    } ,// 注意不要在此行增加逗号
                    error: function() {
                       alert("失败")
                    }

                });
                return false
            })
           

因为才看的Ajax,不知道发生的时候,是否可以不带那个data部分,就随便搞了一个,如果大家有更好的办法,可以分享下,感激不尽

他这到了rust的函数部分后

fn replay(req:HttpRequest,item: web::Json<plic>)->Result<Json<stu::student_info>>{

    let p=stu::stu_select();
    println!("{:#?}",p);
    println!("{:#?}",req);
    Ok(Json(stu::student_info::copy(&p[0])))
}
           

可以看的出来这里啥也没写,就是一个提取和一个返回。

2.前端发送参数部分

$("#btn").click(function() {
                alert(true)
                $.ajax({
                    type: "POST",
                    url: 'http://127.0.0.1:8088/app',
                    async:true, // 使用同步方式
                    // 1 需要使用JSON.stringify 否则格式为 a=2&b=3&now=14...
                    // 2 需要强制类型转换,否则格式为 {"a":"2","b":"3"}
                    data: JSON.stringify({
                        name: $("#name").val(),
                        card_id: $("#card_id").val(),
                        gender: $("#gender").val(),
                        class: parseInt($("#class").val()),
                        age: parseInt($("#age").val())
                    }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data) {
                        $('#result').text(data.result);
                    } // 注意不要在此行增加逗号
                });
                return false
            })
           

这个地方就比较容易了,前端只用传输数据,

到了后端的

fn hand_app(req:HttpRequest,item: web::Json<stu::student_info>)->Result<HttpResponse>{
    println!("{:#?}",req);
    stu::stu_insert(item.0);
    Ok(HttpResponse::build(StatusCode::OK)
        .content_type("text/html; charset=utf-8")
        .body(include_str!("../static/tx/index.html")))
}
//其实这个返回一点用也没有。。。没出问题我就没管了。
//这里的stu_insert是一个添加函数,这个可以去前面的stu.rs看下怎么弄的,如果有需要怎么搞数据库这边的可以给我留言。
           

###错误

1.get

The attribute `get` is currently unknown to the compiler and may have meaning added to it in the future
           

这个错误是因为没有引入get

use actix_web::{get,post};
           

只需要引入这个包就行了

2.

the trait bound `for<'de> MyParams: _IMPL_DESERIALIZE_FOR_plic::_serde::Deserialize<'de>` is not satisfied
           

这个类型的错误都有一个特点,就是看

MyParams: _IMPL_DESERIALIZE_FOR_plic::_serde::这个之后的那个内容是什么,缺这个就要补上这个

//首先引入这个
use serde_derive::{Deserialize, Serialize};
//这个往往是在结构体的前面的
#[derive(Deserialize)]
pub struct MyParams {
    name: String,
}
           
help: consider removing the borrow: `p[0]`
           

这是一个很常见的错误。

我现在也没有很好的解决方案,只能用clone,

所以碰到结构体除了这个问题,我也就一个一个的参数去clone

impl student_info {
    pub fn copy(sp:&student_info) -> student_info {
        student_info {
            name: sp.name.clone(),
            card_id: sp.card_id.clone(),
            gender: sp.gender.clone(),
            class: sp.class.clone(),
            age: sp.age.clone()
        }
    }
}
           

类似于这个样子,其实这个主要是因为数据库的返回有点问题才引入这个函数。