Skip to content

Commit 9c28cc7

Browse files
committed
升级0.1.1
1.升级了依赖版本,并根据新版本依赖修改了代码结构。 2. 将service集中到独立的service目录下方便管理
1 parent 3e582b8 commit 9c28cc7

File tree

16 files changed

+351
-597
lines changed

16 files changed

+351
-597
lines changed

Cargo.lock

Lines changed: 175 additions & 495 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
[package]
22
name = "ru_webapi_codebase"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2021"
55

66
[dependencies]
7-
axum = "0.6.20"
8-
clap = "3.2.25"
7+
axum = "0.8.3"
8+
clap = { version = "4.5.36", features = ["derive"] }
99
ru-di = "0.1.1"
10-
serde = { version = "1.0.196", features = ["derive"] }
11-
serde_json = "1.0.113"
12-
tokio = { version = "1.36.0", features = ["full"] }
13-
futures = "0.3.30"
14-
redis = { version = "0.23", features = ["tokio-comp"] }
15-
reqwest = {version = "0.11.27", default-features = false, features = ["rustls-tls", "serde_json", "json"] }
16-
chrono = "0.4.38"
17-
http = "0.2.11"
18-
log = "0.4.20"
19-
simple_logger = "4.3.3"
20-
uuid = { version = "1.10.0", features = ["v4", "fast-rng"] }
10+
serde = { version = "1.0.219", features = ["derive"] }
11+
serde_json = "1.0.140"
12+
tokio = { version = "1.44.2", features = ["full"] }
13+
futures = "0.3.31"
14+
redis = { version = "0.29.5", features = ["tokio-comp"] }
15+
reqwest = {version = "0.12.15", default-features = false, features = ["rustls-tls", "json"] }
16+
chrono = "0.4.40"
17+
http = "1.3.1"
18+
log = "0.4.27"
19+
simple_logger = "5.0.0"
20+
uuid = { version = "1.16.0", features = ["v4", "fast-rng"] }
2121
hmac = "0.12.1"
2222
sha1 = "0.10.6"
23-
base64 = "0.21.7"
23+
base64 = "0.22.1"
2424
libaes = "0.7.0"
25-
utoipa = { version = "4.2.3", features = ["axum_extras"] }
26-
utoipa-rapidoc = { version = "4", features = ["axum"] }
25+
utoipa = { version = "5.3.1", features = ["axum_extras"] }
26+
utoipa-rapidoc = { version = "6.0.0", features = ["axum"] }
2727
aliyun-sts-rust-sdk = { version ="0.1.1", path="/Users/alex/Projects/workspace/aliyun-sts-rust-sdk"}
28-
sqlx = { version = "0.7.3", default-features = false, features = ["tls-rustls", "runtime-tokio", "postgres", "json", "uuid", "bigdecimal", "macros"] }
28+
sqlx = { version = "0.7.4", default-features = false, features = ["tls-rustls", "runtime-tokio", "postgres", "json", "uuid", "bigdecimal", "macros"] }
2929
sqlx_struct_enhanced = { version = "*", path = "/Users/alex/Projects/workspace/sqlx_struct_enhanced", features = ["postgres"] }

README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 自用项目模版,请谨慎使用!
2+
3+
## A:使用方法
4+
5+
### A1: 手动
6+
7+
在release中下载最新的代码,解压后,将文件夹重命名为项目名称
8+
9+
修改 Cargo.toml 中的 name 字段为项目名称
10+
11+
修改 Cargo.toml 中的 version 字段为项目版本号
12+
13+
修改 Cargo.toml 中的 authors 字段为项目作者
14+
15+
修改 Cargo.toml 中的 description 字段为项目描述
16+
17+
在终端进入项目目录,执行以下命令
18+
```bash
19+
git init
20+
git add .
21+
git commit -m "init"
22+
git remote add origin <your-repo-url>
23+
git push -u origin master
24+
cargo build
25+
```
26+
27+
如果编译成功,即可即刻进入项目开发阶段
28+
29+
### A2: 使用 cargo-generate
30+
31+
在终端执行以下命令
32+
```bash
33+
cargo install cargo-generate
34+
cargo generate --git [email protected]:ipconfiger/ru_webapi_codebase.git --name <your-project-name>
35+
cd <your-project-name>
36+
cargo build
37+
```
38+
39+
## B: 项目依赖
40+
41+
项目模版中使用了几个私有项目,如果不需要,可以删除 Cargo.toml 中的依赖项
42+
### aliyun-sts-rust-sdk
43+
这个项目是阿里云的 sts rust sdk,用于获取阿里云的临时访问凭证,用于访问阿里云的服务,因为阿里云本身没有提供Rust的SDK,所以自己实现了一个
44+
45+
### sqlx_struct_enhanced
46+
这个项目是自己对sqlx的简单封装,主要是给struct注入了增删改查的方法,方便使用,主要针对自己的使用习惯,你可以删掉换上自己习惯的ORM框架
47+
48+
### rmmp
49+
这是在同步模型设计到目标代码的生成器,项目在 https://github.com/ipconfiger/rmmp 中,主要用来将models目录下的模型定义同步生成数据库的models结构体,各种接口定义的结构体,返回数据结构的结构体,以及给前端访问接口定义的请求参数和返回值的结构体定义,和Rust代码同步,方便开发。同时也生成了结构体的类关系图,方便在文档中引用。
50+
!!! 注意:生成UML图依赖了工具 dot_graph,你需要先自己安装
51+
52+
### C: 开发说明
53+
54+
项目模版定义了双层Router结构,方便拆分子项目。
55+
56+
example 为定义的模版子Router结构,最好不要修改
57+
58+
使用的时候使用在 scripts目录下的脚本 create.sh 来创建子Router结构,脚本会自动创建子Router结构。
59+
60+
```bash
61+
./scripts/create.sh mod <your-sub-router-name>
62+
```
63+
64+

models/responses.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
StatusResponse:
2+
# 状态码
3+
@rust String
4+
@ts string
5+
status: 状态值
6+
17
LoginResponse:
28
# 登陆结果
39
@rust String

outputs/response-uml.png

5.11 KB
Loading

outputs/response.dot

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ digraph G {
1313
fontsize = 8
1414
]
1515

16+
// 定义类
17+
StatusResponse [label = "{ -StatusResponse- |+ status : 状态值\l }"]
18+
1619
// 定义类
1720
LoginResponse [label = "{ -LoginResponse- |+ token : 令牌\l+ expires : 过期时间\l }"]
1821

outputs/response.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
interface StatusResponse {
2+
status: string;
3+
4+
}
15
interface LoginResponse {
26
token: string;
37
expires: number;

src/app.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ use std::net::SocketAddr;
22
use std::time::Duration;
33
use axum::response::{Html, IntoResponse, Response};
44
use axum::{Json, Router};
5+
use axum::http::{header, Request, StatusCode};
56
use axum::middleware::Next;
67
use axum::routing::get;
7-
use http::{header, Request, StatusCode};
8+
//use http::{header, Request, StatusCode};
89
use log::{error, info};
910
use serde_json::json;
1011
use sqlx::postgres::PgPoolOptions;
1112
use utoipa::OpenApi;
1213
use utoipa_rapidoc::RapiDoc;
1314
use crate::errors::ErrResponse;
1415
use crate::conf::Configuration;
15-
use crate::example;
16+
use crate::{example, services};
1617
use crate::redis::{RedisHolder, RedisSession};
1718

1819
#[derive(Clone)]
@@ -34,7 +35,7 @@ pub async fn init(cfg: &Configuration) {
3435
ru_di::Di::register(move |_| {
3536
pool_inner.clone()
3637
});
37-
example::init().await;
38+
services::init().await;
3839
}
3940

4041
pub async fn start_serve(cfg: &Configuration) {
@@ -50,18 +51,13 @@ pub async fn start_serve(cfg: &Configuration) {
5051
.nest("/example", example::handlers::router(state.clone()))
5152
.layer(axum::middleware::from_fn(log_request));
5253
info!("server will start at 0.0.0.0:{}", cfg.port);
53-
let serv = axum::Server::bind(&SocketAddr::from(([0, 0, 0, 0], cfg.port)))
54-
.serve(app.into_make_service())
55-
.await;
56-
match serv {
57-
Ok(_)=>{
54+
if let Ok(listener) = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", cfg.port).as_str()).await {
55+
if let Err(e) = axum::serve(listener, app).await {
56+
error!("server fault with err:{}", e);
57+
}else{
5858
info!("server stopped normally");
5959
}
60-
Err(err)=>{
61-
error!("server fault with err:{}", err);
62-
}
6360
}
64-
6561
}
6662

6763
async fn not_found() -> Html<String> {
@@ -71,16 +67,16 @@ async fn status()->impl IntoResponse {
7167
Json(json!({"status": "it works!"}))
7268
}
7369

74-
async fn log_request<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse {
70+
async fn log_request(req: Request<axum::body::Body>, next: Next) -> Response {
7571
info!("{} {}", req.method(), req.uri());
76-
next.run(req).await.into_response()
72+
next.run(req).await
7773
}
7874

7975
async fn redoc_js() -> Response {
8076
Response::builder()
8177
.status(StatusCode::OK)
8278
.header(header::CONTENT_TYPE, "application/javascript")
83-
.body(axum::body::boxed(axum::body::Full::from(include_str!("../templates/rapidoc-min.js")))).unwrap()
79+
.body(axum::body::Body::new::<String>(include_str!("../templates/rapidoc-min.js").to_string())).unwrap()
8480
}
8581

8682
async fn redoc_ui() -> Html<String> {

src/conf.rs

Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,37 @@
1-
use clap::{App, Arg, ArgMatches};
1+
use clap::{Parser, Subcommand};
2+
3+
#[derive(Parser, Debug, Clone)]
4+
#[command(version, about, long_about = None)]
25
pub struct Configuration {
6+
#[arg(short, long)]
37
pub db_uri: String,
8+
#[arg(short, long)]
49
pub port: u16,
5-
pub redis_uri: String
10+
#[arg(short, long)]
11+
pub redis_uri: String,
12+
13+
#[command(subcommand)]
14+
pub command: Option<Commands>,
615
}
716

8-
pub fn get_matches() -> ArgMatches {
9-
App::new("Server Configuration")
10-
.arg(Arg::with_name("port")
11-
.short('p')
12-
.long("port")
13-
.help("服务器运行端口")
14-
.required(true)
15-
.takes_value(true)
16-
.default_value("9527"))
17-
.arg(Arg::with_name("redis")
18-
.short('r')
19-
.long("redis")
20-
.help("Redis连接URI")
21-
.required(true)
22-
.takes_value(true))
23-
.arg(Arg::with_name("db_uri")
24-
.short('d')
25-
.long("db_uri")
26-
.help("数据库连接URI")
27-
.required(true)
28-
.takes_value(true))
29-
.arg(Arg::with_name("cmd")
30-
.short('c')
31-
.long("cmd")
32-
.help("执行命令的名字")
33-
.required(false)
34-
.takes_value(true))
35-
.arg(Arg::with_name("serve")
36-
.long("serve")
37-
.help("运行服务器")
38-
.required(false)
39-
)
40-
.get_matches()
17+
#[derive(Subcommand, Debug, Clone)]
18+
pub enum Commands {
19+
Serve,
20+
Cli
4121
}
4222

43-
pub fn config_from_matches(matches: &ArgMatches) -> Configuration {
44-
let db_uri = matches.get_one::<String>("db_uri").expect("need db_uri");
45-
let port = matches.get_one::<String>("port").expect("need port");
46-
let redis_uri = matches.get_one::<String>("redis").expect("need redis_uri");
47-
Configuration{
48-
db_uri: db_uri.to_string(),
49-
port: port.parse::<u16>().expect("port must be a number"),
50-
redis_uri: redis_uri.to_string(),
51-
}
23+
pub fn get_config() -> Configuration {
24+
Configuration::parse()
5225
}
5326

27+
// pub fn config_from_matches(matches: &ArgMatches) -> Configuration {
28+
// let db_uri = matches.get_one::<String>("db_uri").expect("need db_uri");
29+
// let port = matches.get_one::<String>("port").expect("need port");
30+
// let redis_uri = matches.get_one::<String>("redis").expect("need redis_uri");
31+
// Configuration{
32+
// db_uri: db_uri.to_string(),
33+
// port: port.parse::<u16>().expect("port must be a number"),
34+
// redis_uri: redis_uri.to_string(),
35+
// }
36+
// }
37+

src/example/handlers.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ use axum::{Json, Router};
22
use axum::routing::get;
33
use serde_json::{json, Value};
44
use crate::app::AppContext;
5-
use crate::example::services;
5+
use crate::services::example_service::ExampleServices;
66
use crate::types::{get_serve, APIResult};
7+
use crate::errors::ErrResponse;
8+
use crate::response::StatusResponse;
79

810
#[utoipa::path(
911
get,
1012
path = "/example/",
1113
responses(
12-
(status = 200, description = "获取文章列表有限条数", body = Response),
14+
(status = 200, description = "测试Handler返回Json", body = StatusResponse),
1315
(status = 500, description = "服务器错误", body = ErrResponse),
1416
(status = 401, description = "认证失败", body = ErrResponse),
1517
(status = 403, description = "没有权限", body = ErrResponse)
@@ -18,10 +20,10 @@ use crate::types::{get_serve, APIResult};
1820
("bearerAuth" = [])
1921
)
2022
)]
21-
async fn it_works() -> APIResult<Value> {
22-
let serv = get_serve::<services::ExampleServices>();
23+
async fn it_works() -> APIResult<StatusResponse> {
24+
let serv = get_serve::<ExampleServices>();
2325
serv.test().await?;
24-
Ok(Json(json!({"status": "it works".to_string()})))
26+
Ok(Json(StatusResponse{status: "it works".to_string()}))
2527
}
2628

2729
// 导出路由

0 commit comments

Comments
 (0)