【山竹记账后端】1.搭建后端项目

【山竹记账后端】1.搭建后端项目

从无到有创建 Rails API


大纲链接 §

toc


1. 初始化目录 [⇧](#1. 初始化目录 ⇧ "#catalogue")

前提:已经创建好 oh-my-env 的容器环境,打开容器项目

  • 已预装 ruby@3.0.0p0 或者 rvm use 3.1.2
  • 已预装 gem@3.2.3
  • 已预装 bundle@2.5.23
  • 已预装 rvm@1.29.12

还需要配置安装的:

  • gembundle 的源未配置国内镜像
  • rails 未安装
  • postgresql 未安装

命令行步骤

  • VSCode 中启动 oh-my-env 的容器环境
  • 无需重新 build
zsh 复制代码
# 更换gem国内源
gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/ --remove https://gems.ruby-china.com/
# 更换bundle国内源
bundle config set --global mirror.https://rubygems.org https://mirrors.tuna.tsinghua.edu.cn/rubygems
# 安装rails,版本尽量和我的一致,会有日志,等待时间较长
gem install rails -v 7.2.3.2
# 在 docker 镜像的 linux 中安装 postgresql 驱动;
# 已在 `Dockerfile` 内置命令 `RUN pacman -S postgresql-lib`,可省略
pacman -S postgresql-libs
# 创建rails项目;只是用 api 模式;数据库 使用 postgresql;跳过自带测试(之后使用第三方测试);
cd ~/repos
rails new --api --database=postgresql --skip-test mangosteen-1
# 使用 VSCode 打开在容器中项目
code mangosteen-1 # code ~/repos/mangosteen-1
# 新建一个zsh终端后,启动rails服务;需要关闭server 请按Ctrl+C
bundle exec rails server
  • 如果报错 gem:14: command not found: gem,需要切一下版本 rvm use 3 或者 rvm use 3.1.2
  • 安装rails,版本尽量和我的一致 rails -v 7.2.3.2,更新到稳定版
  • rails new --api --database=postgresql --skip-test mangosteen-1 参数解释
    • rails new 创建框架新项目
    • --api 只是用 api 模式
    • --database=postgresql 指定使用 PostgreSQL 数据库
    • --skip-test 跳过自带测试(之后使用第三方测试)
    • mangosteen-1 创建的项目目录名称
  • rails new 创建项目还需要安装另外的依赖,需要等待时间较长
    • 提示运行 bundle binstubs bundler前,需要先进入项目目录 cd mangosteen-1
    • 进入后可以看到已经创建了一堆项目文件,已经 git init,但还没有提交

rails api 模式下的目录

  • 使用 code . 在当前目录中打开容器项目,由于全局环境和项目环境会有不一致,需要保证在项目中运行
  • 启动rails服务 bundle exec rails server 或者 bundle exe rails server
    • 可以简写为 bundle exec rails s
    • 也可以简写为 bin/rails s
    • 不推荐 rails s,因为全局环境和项目环境软件版本可能不一致
      • 项目中的 rails 版本在 Gemfile 中指定 gem "rails", "~> 7.2.3", ">= 7.2.3.2"
  • 启动后可以看到终端 => Booting Puma
    • Min threads:5 最小进程数
    • Max threads:5 最大进程数
    • Environment:development 默认环境为开发环境
    • Listening on http://127.0.0.1:3000 默认监听端口 3000,自动转发到主机系统中
  • 直接访问 http://127.0.0.1:3000 会看到报错 ActiveRecord::ConnectionNotEstablished
    • 这是因为数据库没有启动,需要先启动数据库,定位报错信息 PGSQL.5432 ,需要执行docker命令来启动数据库

国内源 [⇧](#国内源 ⇧ "#catalogue")

  • 清华镜像 https://mirrors.tuna.tsinghua.edu.cn/rubygems/
  • 南阳镜像 https://mirror.nyist.edu.cn/rubygems/
zsh 复制代码
# 移除已失效的 Ruby China 源和官方源
gem sources --remove https://gems.ruby-china.com/
gem sources --remove https://rubygems.org/
# 添加全新可用的国内源
# 中国科学技术大学 (USTC) 源
gem sources -a https://mirrors.ustc.edu.cn/rubygems/
# 清华大学 (TUNA) 源
gem sources -a https://mirrors.tuna.tsinghua.edu.cn/rubygems/
# 官方源
gem sources -a https://rubygems.org/rubygems/

# 验证当前源
gem sources -l

2. 启动数据库镜像 [⇧](#2. 启动数据库镜像 ⇧ "#catalogue")

zsh 复制代码
docker run -d --name db-for-mangosteen -e POSTGRES_USER=mangosteen -e POSTGRES_PASSWORD=123456 -e POSTGRES_DB=mangosteen_dev -e PGDATA=/var/lib/postgresql/data/pgdata -v mangosteen-data:/var/lib/postgresql/data -p 5432:5432 --network=network1 postgres:14
  • 命令不可折行,会有bug,以下为参数说明
    • docker run -d 启动一个新容器,-d 后台保持运行
    • --name db-for-mangosteen 命名该容器的名称
    • e POSTGRES_USER=mangosteen 环境变量:用户名
    • e POSTGRES_PASSWORD=123456 环境变量:密码
    • e POSTGRES_DB=mangosteen_dev 环境变量:数据库名称
      • 以区分测试环境mangosteen_test和生产环境mangosteen_production的数据库
    • e PGDATA=/var/lib/postgresql/data/pgdata 环境变量:PostgreSQL 数据目录,官方指定
    • v mangosteen-data:/var/lib/postgresql/data 挂载数据卷,将主机上的数据挂载到容器中
      • 自动创建并持久化数据卷,容器重启后数据不会丢失
    • -p 5432:5432 指定端口映射,将容器的5432端口映射到主机的5432端口,可选,使用 VSCode 时可不用
    • --network=network1 指定网络,可以通过 db-for-mangosteen 这个名称来访问网络
      • 前提是之前已在在命令行运行 docker network create network1 创建网络
    • postgres:14 镜像名称与版本号
  • 这行命令需要在 windows (docker的外部)系统中运行
  • 命令运行后会返回一串哈希,说明数据库已经启动
  • 此时在 docker desktop 中可以看到数据库容器正在运行
  • 可以通过 docker ps 查看数据库容器是否启动

3. 配置项目开发数据库,并运行命令连接 [⇧](#3. 配置项目开发数据库,并运行命令连接 ⇧ "#catalogue")

修改 config/database.yml 配置开发数据库 [⇧](#修改 config/database.yml 配置开发数据库 ⇧ "#catalogue")

yaml 复制代码
development:
  # noinspection YAMLUnresolvedAlias
  <<: *default
  database: mangosteen_dev
  username: mangosteen
  password: 123456
  host: db-for-mangosteen
  • 数据库名称 database: mangosteen_dev
  • 用户名 username: mangosteen
  • 密码 password: 123456
  • 主机名 host: db-for-mangosteen,理论上应填写一个ip或域名,这里填写的是容器名称
    • 这是之前运行容器的参数 docker run -d --name db-for-mangosteen ...

运行 sever [⇧](#运行 sever ⇧ "#catalogue")

  • 此时需要按 Ctrl+C 先断开之前的服务,重新启动 bin/rails s

看到以下界面说明已经成功启动服务

对于一个熟练的 ruby 程序员来说,主要步骤就三步

  • 创建目录
  • 启动数据库
  • 配置数据库,刷新

记得及时提交代码


4. rails 项目的选择 [⇧](#4. rails 项目的选择 ⇧ "#catalogue")

  • 创建时使用 api 模式
  • 数据库 使用 postgresql
  • 跳过自带测试(之后使用第三方测试)

rails的理念:约定大于配置,即直接给到最佳实践


5. 实现一个后台功能 [⇧](#5. 实现一个后台功能 ⇧ "#catalogue")

简单实现一个后台功能,看看完整过程时怎样的

设计数据库 [⇧](#设计数据库 ⇧ "#catalogue")

山竹记账需要哪些数据?

设计数据库的两种思路 [⇧](#设计数据库的两种思路 ⇧ "#catalogue")
  • 自上而下:现想大概,再添加细节
    • 大概有哪些表,有那些数据字段
  • 自下而上:用到什么加什么,会出现打脸的情况
  • 两种思路可以混合,我们先采用 自下而上

rsils提供的设计数据库工具 [⇧](#rsils提供的设计数据库工具 ⇧ "#catalogue")

  • 建模工具:bin/rails g model user email:string name:string
    • g 代表 generate 会自动生成 模型类迁移文件
    • 模型类: app/models/user.rb 文件
    • 迁移文件: db/migrate/YYYYMMDD_create_users.rb 文件
      • YYYYMMDD 为当前日期,用于区分不同的迁移文件
      • 需要自行填充 change 方法的逻辑
  • 数据库操作工具:ActiveRecord::Migration
    • 同步到数据库:bin/rails db:migrate
    • 反悔命令:bin/rails db:rollback step=1
      • step=1 表示回滚最近一次迁移

rsils创建新建数据库代码 [⇧](#rsils创建新建数据库代码 ⇧ "#catalogue")

在进行数据库相关操作前,确保当前代码都已提交

ruby 复制代码
bin/rails g model user email:string name:string
# invoke  active_record
# create    db/migrate/20260906082930_create_users.rb
# create    app/models/user.rb

查看 app/models/user.rb

ruby 复制代码
class User < ApplicationRecord
end

查看 db/migrate/20260906082930_create_users.rb

ruby 复制代码
class CreateUsers < ActiveRecord::Migration[7.2]
  def change
    create_table :users do |t|
      t.string :email, limit: 100
      t.string :name

      t.timestamps
    end
  end
end
  • 声明类 class CreateUsers < ActiveRecord::Migration[7.2]
    • Migration[7.2] 表示使用 rails 7.2 版本的迁移类
  • def change 代表对数据库做的变动
    • create_table :users do |t| 接受两个参数
    • 第一个参数 :users 创建一个名为 users 的表
    • 第二个参数为一个函数 do |t| ... end ,用于定义表的字段
      • t.string :email 添加一个字符串类型的 email 字段
      • t.string :name 添加一个字符串类型的 name 字段
      • t.timestamps 会自动添加 created_atupdated_at 字段,用于记录创建时间和更新时间
  • 类似于 js 代码 createTable('users', (api) => {api.string('email', {limit: 100})})

参考

目前并没有直接变更数据库,只是把将要变更的写到代码中,需要运行 bin/rails db:migrate 才会变更数据库。

rsils第一次迁移数据库 [⇧](#rsils第一次迁移数据库 ⇧ "#catalogue")

运行 bin/rails db:migrate 后,数据库会自动创建 users

ruby 复制代码
bin/rails db:migrate

# == 20260906082930 CreateUsers: migrating ======================================
# -- create_table(:users)
#    -> 0.0393s
# == 20260906082930 CreateUsers: migrated (0.0394s) =============================

rsils反悔迁移数据库 [⇧](#rsils反悔迁移数据库 ⇧ "#catalogue")

运行 bin/rails db:rollback 可以回滚最近一次迁移 运行 bin/rails db:rollback step=1 可以回滚指定步数的迁移

ruby 复制代码
bin/rails db:rollback

# == 20260906082930 CreateUsers: reverting ======================================
# -- drop_table(:users)
#    -> 0.0076s
# == 20260906082930 CreateUsers: reverted (0.0138s) =============================
  • 智能自动识别之前 create_table 的反操作为 drop_table 删除
  • 其他后端框架做不到自识别 create_table 的反操作为 drop_table

这样就可以随时对数据库进行操作,增删字段、迁移数据库、反悔操作


6. 创建路由 [⇧](#6. 创建路由 ⇧ "#catalogue")

手动添加路由(原始) [⇧](#手动添加路由(原始) ⇧ "#catalogue")

config/routes.rb

ruby 复制代码
Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  post '/users', to: 'users#create'
  get '/users/:id', to: 'users#show'
end
  • 相当于js中类似代码,post('/users', {to: 'users#create'})
  • ruby但更简洁,少了括号的杂音 post '/users', to: 'users#create'
  • to: 'users#create' 表示将 POST 请求路由到 UsersControllercreate 方法
  • to: 'users#show' 表示将 GET 请求路由到 UsersControllershow 方法

目前还未实现 createshow 这两个方法,继续实现前别忘记提交代码


7.创建 Controller [⇧](#7.创建 Controller ⇧ "#catalogue")

实现 createshow 这两个方法

  • 脚手架 bin/rails g controller users create show
  • 输出 JSON 视图 render json: user
zsh 复制代码
bin/rails g controller users create show

# create  app/controllers/users_controller.rb
#  route  get "users/create"
#  get "users/show"
  • 注意 users 不要写错成 user,复数形式很重要
    • 确保文件名为 app/controllers/users_controller.rb
    • 确保的该文件中的类名为 UsersController
    • 如果错误发起请求时会报错
    • ActionController::RoutingError (uninitialized constant UsersController Did you mean?UserController):
  • 自动创建了 app/controllers/users_controller.rb 文件
  • 运行命令后,在 config/routes.rb 中自动添加了路由 get "users/create"get "users/show"
    • 不够精确,可删除,使用手动添加的

app/controllers/users_controller.rb

ruby 复制代码
class UsersController < ApplicationController
  def create
    p "你访问了 create"
  end

  def show
    p "你访问了 show"
  end
end
  • 添加打印日志,验证当用户访问这两个接口时,确实走了这两个方法的逻辑
  • 先确保服务已经启动 bin/rails s
  • 另外打开一个终端,拆分到右侧,使用 curl 命令访问api接口,成功运行,可以在puma控制台看到输出
  • 正确发起请求后,查看控制台打印

config/routes.rb

ruby 复制代码
Rails.application.routes.draw do
  # get "user/create"
  # get "user/show"
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  post '/users', to: 'users#create'
  get '/users/:id', to: 'users#show'
end

调试填充功能逻辑 app/controllers/users_controller.rb

ruby 复制代码
class UsersController < ApplicationController
  def create
    user = User.new email: 'frank@x.com', name: 'frank'
    if user.save
      p 'save 成功了'
    else
      p 'save 失败了'
    end
  end

  def show
    p "你访问了 show"
  end
end
  • 使用 User.new 创建一个对象
  • 使用 user.save 保存对象,if user.save 返回一个布尔值,根据结果打印日志

安装VSCode插件查看数据库,验证是否成功创建表

  • PostgreSQL
    • 点击+连接
    • 输入 hostnamedb-formangosteen
    • 输入用户名 mangosteen
    • 输入密码 123456
    • 输入端口 5432
    • 点选 Standart Conection
    • 点选 数据库 mangosteen_dev
  • 查看数据库中该表的字段

渲染信息 [⇧](#渲染信息 ⇧ "#catalogue")

app/controllers/users_controller.rb

ruby 复制代码
class UsersController < ApplicationController
  def create
    user = User.new email: "frank@x.com", name: "frank"
    if user.save
      render json: user
    else
      render json: user.errors
    end
  end

  def show
  end
end
  • 直接使用 render json: user 渲染用户信息
    • 这句代码相当于 jsrender({json: user.errors})
  • 使用 curl -X POST http://127.0.0.1:3000/users 添加一个用户,查看后台打印信息

添加字段验证 [⇧](#添加字段验证 ⇧ "#catalogue")

app/models/user.rb

ruby 复制代码
class User < ApplicationRecord
  validates :email, presence: true
end

app/controllers/users_controller.rb 尝试修改 不写 email 字段

ruby 复制代码
def create
    user = User.new name: "frank"
    if user.save
      render json: user
    else
      render json: user.errors
    end
end
  • 请求 curl -X POST http://127.0.0.1:3000/users
  • 返回报错 {"email":["can't be blank"]}#

实现 show 方法 [⇧](#实现 show 方法 ⇧ "#catalogue")

app/controllers/users_controller.rb

ruby 复制代码
class UsersController < ApplicationController
  def create
   # ...
  end

  def show
    p "--------------------"
    p params[:id]
    p "--------------------"
    user = User.find params[:id]
    render json: user
  end
end
  • 请求 curl -X GET http://127.0.0.1:3000/users/1 查看后台打印
  • 打印找不到的情况,请求 curl -X GET http://127.0.0.1:3000/users/1000
  • 由于 User.find 可能返回异常报错,自动返回 404 并且逻辑不再往下处理,截胡代码逻辑
    • 解决方法:使用 find_by_id 方法,返回 nil 时,返回 404 错误
    • find_by_idRuby元编程 方法
    • 并未在app/models/user.rb中主动定义该方法,自动读取数据库字段生成
    • 意味着还有 find_by_namefind_by_email 等方法
    • 建议开发中少使用 find,直接终端当前方法,返回 404
    • 当需要对错误做另外处理时,使用find_by_xxx
  • 使用 curl -v http://127.0.0.1:3000/users/1
    • 查看响应头 < HTTP/1.1 404 Not Found

最终 app/controllers/users_controller.rb

ruby 复制代码
class UsersController < ApplicationController
  def create
   # ...
  end

  def show
    user = User.find_by_id params[:id]
    if user
      render json: user
    else
      head 404
    end
  end
end

Router + MVC [⇧](#Router + MVC ⇧ "#catalogue")

  • 目前实现了
    • 路由 config/routes.rb
    • Model app/models/user.rb
    • 控制器 app/controllers/users_controller.rb
    • 视图(api模式没有视图,只是返回json)
  • 理解这些 rails 就入门了

8. 总结和实战操作 [⇧](#8. 总结和实战操作 ⇧ "#catalogue")

创建一个后台的工作流,启动数据库服务,启动服务 bin/rails s

  • 创建 Model 的命令:bin/rails g model user email:string name:string
    • 生成 app/models/user.rb 添加验证逻辑
    • 生成 db/migrate/xxxx_create_users_table.rb
      • CreateUsers#change 方法中添加自定义字段
  • 迁移数据库的命令:bin/rails db:migrate
  • 反悔命令:bin/rails db:rollback step=1
  • 通过插件或自带数据库功能,可以查看数据库中的表
  • 手动在 config/routes.rb 中创建路由
    • post '/users', to: 'users#create'
    • get '/users/:id', to: 'users#show'
  • 创建 Controller 运行命令 bin/rails g controller users create show
    • 生成 app/controllers/users_controller.rb, 补充操作逻辑
      • 暂时使用 curl 命令访问接口,查看后台打印
      • 通过插件或自带数据库功能,可以查看数据库中的数据
    • 在路由文件中自动添加了两个方法,但不够精确,目前不用,手动删除
      • get 'user/create'
      • get 'user/show'

命令

zsh 复制代码
# Model
bin/rails g model user email:string name:string
# Data Migration
bin/rails db:migrate
# Data Rollback
bin/rails db:rollback step=1
# Controller & Route
bin/rails g controller users create show

创建一个github仓库,实现如下功能

  • post /users 可以创建用户(属性随意)
  • get /users/:id 可以展示用户(属性随意)

9.使用 JetBrainsDev Container 远程开发 V.S. VSCodeDev Container [⇧](#9.使用 JetBrains 的 Dev Container 远程开发 V.S. VSCode 的 Dev Container ⇧ "#catalogue")

总结使用 VSCodeDev Container 远程开发 [⇧](#总结使用 VSCode 的 Dev Container 远程开发 ⇧ "#catalogue")

win11WSL2 环境,并安装 Docker Desktop 客户端为例

  • 本地下载 oh-my-env 项目,使用 VSCode 打开,在容器中打开,构建镜像
  • 成功启动开发容器,新建终端zsh,打开repos中的项目目录
    • 确认开启docker容器数据库镜像服务(重新构建数据库镜像后,需要执行迁移数据库命令)
    • 仅首次构建或rebuild,从oh-my-env2目录拷贝初始配置
      • 替换覆盖 /root项目目录中的配置
    • 项目目录打开成功,检查环境依赖配置版本,启动项目服务
    • 端口自动转发 127.0.0.1:3000 成功访问初始页面

设置并备份环境配置,持久化默认开发配置

  • 仅首次构建或rebuild,从oh-my-env2目录拷贝初始配置
    • 替换覆盖 /root 项目目录中的配置
  • 备份脚本,将主要配置拷贝到 本地目录 oh-my-env

使用 JetBrainsDev Container 远程开发 [⇧](#使用 JetBrains 的 Dev Container 远程开发 ⇧ "#catalogue")

win11WSL2 环境,并安装 Docker Desktop 客户端为例

  • 本地下载 oh-my-env 项目,使用 RubyMine 打开
    • 可以选择消息提示浮动框,在容器中重新打开,构建镜像
    • 或者点击菜单中的 文件 -> 远程开发 -> Dev Container
    • 或者在服务面板中点击 Dev Container 对应的容器启动
  • 成功启动开发容器,新建终端zsh, 打开repos中的项目目录
    • 确认开启docker容器数据库镜像服务(重新构建数据库镜像后,需要执行迁移数据库命令)
      • 创建数据库镜像时,需要添加 -p 5432:5432 指定端口映射
      • 将容器的5432端口映射到主机的5432端口
    • 仅首次构建或rebuild,从oh-my-env2目录拷贝初始配置
      • 替换覆盖 /root 项目目录中的配置
    • 项目目录打开成功,检查环境依赖配置版本,启动项目服务
    • 点击弹出框,确认端口转发 127.0.0.1:3000 成功访问初始页面

消息提示浮动框,在容器中重新打开,构建镜像

远程开发

确认端口转发


10. 连接查看数据库 [⇧](#10. 连接查看数据库 ⇧ "#catalogue")

每次重启后忘记开数据库 [⇧](#每次重启后忘记开数据库 ⇧ "#catalogue")

会看到启动页面报错

运行启动命令

bash 复制代码
docker start db-for-mangosteen

# 成功运行会返回id
# db-for-mangosteen
  • 再次刷新页面即可

将创建数据库命令和启动命令写到 README.md 中,添加运行脚本

  • create_database_container.sh
  • start_database_container.sh

数据库容器已经持久化到 mangosteen-data 数据卷中


使用插件或者 DataGrip 或者 DBeaver 数据库 IDE

  • 待更新

11. 需要运行的命令参考 [⇧](#11. 需要运行的命令参考 ⇧ "#catalogue")

需要运行的命令参考

zsh 复制代码
# 更换gem国内源
gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/ --remove https://gems.ruby-china.com/
# 更换bundle国内源
bundle config set --global mirror.https://rubygems.org https://mirrors.tuna.tsinghua.edu.cn/rubygems
# 安装rails,版本尽量和我的一致,会有日志,等待时间较长
gem install rails -v 7.2.3.2
# 创建rails项目;只是用 api 模式;数据库 使用 postgresql;跳过自带测试(之后使用第三方测试);
cd ~/repos
rails new --api --database=postgresql --skip-test mangosteen-1
# 使用 VSCode 打开在容器中项目
code mangosteen-1 # code ~/repos/mangosteen-1
# 启动数据库容器
docker run -d --name db-for-mangosteen -e POSTGRES_USER=mangosteen -e POSTGRES_PASSWORD=123456 -e POSTGRES_DB=mangosteen_dev -e PGDATA=/var/lib/postgresql/data/pgdata -v mangosteen-data:/var/lib/postgresql/data -p 5432:5432 --network=network1 postgres:14
# 新建一个zsh终端后,启动rails服务;需要关闭server 请按Ctrl+C
bundle exec rails server

# 创建数据库模型类 Model
bin/rails g model user email:string name:string
# 迁移数据库 Migration
bin/rails db:migrate
# 反悔迁移数据库 Rollback
bin/rails db:rollback step=1
# Controller & Route
bin/rails g controller users create show

·未完待续·


参考文章

源代码镜像服务

数据迁移


相关文章


  • 作者: Joel
  • 文章链接:
  • 版权声明
  • 非自由转载-非商用-非衍生-保持署名


相关推荐
Moment42 分钟前
为什么越来越多开发者开始用 PostgreSQL?
前端·后端·面试
YHL44 分钟前
🚀 从 SPA 到 Next.js 全栈:一个大前端的 SEO 突围笔记
前端·后端
颜进强1 小时前
从零跑通一套 WorkBuddy Skill 骨架:【能跑通+代码】生成HTML报告实战
前端·后端·ai编程
Shinomiya1 小时前
Mysql之表的约束详解
后端
Java内核笔记1 小时前
Spring Boot 4 与 Spring AI 2.0 深度集成:ChatClient、Advisor 链与 MCP(源码级实战)
java·后端
吃饱了得干活1 小时前
一个订单的奇幻漂流:RabbitMQ 五大难题实战
spring boot·后端·rabbitmq
她的男孩1 小时前
账号锁定配了"错 4 次锁 30 分钟",我连错 100 次一次没锁上:扒完 4091 行认证源码,找到 5 个坑
java·后端·架构
Methy1 小时前
一次线上死锁排查:std::list::size () 居然是 O (n)?
c++·后端
MacroZheng1 小时前
Redis官方发布高颜值可视化工具,功能更是强的离谱!
java·redis·后端