利用Flask来实现留言板的基本操作

留言板开发

一、相关技术介绍

本项目基于现代Web开发技术栈构建,采用Python 3.12作为后端开发语言,搭配轻量级Flask 2.3.2框架实现核心功能。数据库层使用Flask-SQLAlchemy ORM框架操作MySQL 8.0数据库,通过对象关系映射简化数据操作。用户认证模块整合Flask-Login实现安全的会话管理,结合Flask-WTF处理表单验证,确保数据输入的合法性。前端界面采用Bootstrap 5框架构建响应式布局,通过Jinja2模板引擎实现动态内容渲染,整体架构遵循MVT(Model-View-Template)设计模式,实现业务逻辑、数据管理和表现层的清晰分离。详细如下

Python 3.12:作为后端编程语言

Flask 2.3.2:轻量级Web框架

Flask-SQLAlchemy:ORM框架,用于数据库操作

MySQL 8.0:关系型数据库存储数据

Flask-Login:用户认证管理

Flask-WTF:表单处理和验证

Bootstrap 5:前端UI框架

Jinja2:模板引擎

MVT设计模式:Model-View-Template架构

二、项目整体框架

1、代码目录结构

pythonProject/

├── venv/ # PyCharm自动创建的虚拟环境

├── app/ # 应用主目录

│ ├── init.py # 应用初始化文件

│ ├── auth/ # 认证蓝图

│ │ ├── init.py

│ │ ├── forms.py

│ │ └── views.py

│ ├── main/ # 主蓝图

│ │ ├── init.py

│ │ ├── forms.py

│ │ └── views.py

│ ├── models.py # 数据模型

│ └── templates/ # 模板文件

│ ├── auth/

│ │ ├── login.html

│ │ └── register.html

│ ── main/

│ ├── base.html

│ ├── create_message.html

│ ├── edit_message.html

│ ├── message_detail.html

│ └── messages.html

├── config.py # 配置文件

├── requirements.txt # 依赖文件

├── run.py # 启动文件

└── migrations/ # 数据库迁移文件夹(后续生成)

2、项目配置文件(config. py

import os

from dotenv import load_dotenv

basedir = os.path.abspath(os.path.dirname(file))

load_dotenv(os.path.join(basedir, '.env'))

class Config:

SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-key-123'

SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \

'mysql+pymysql://username:password@localhost/flask_data'

SQLALCHEMY_TRACK_MODIFICATIONS = False

MESSAGES_PER_PAGE = 5

3、项目扩展包文件(requirements.txt)

Flask==2.3.2

Flask-SQLAlchemy==3.0.3

Flask-Login==0.6.2

Flask-WTF==1.1.1

Flask-Migrate==4.0.4

PyMySQL==1.0.3

python-dotenv==1.0.0

email-validator==2.0.0

三、数据库设计

1、对于数据库上的操作

检查MySQL服务状态

sudo systemctl status mysql

如果未运行,启动它

sudo systemctl start mysql

2、在mysql中创建数据库flask_data

CREATE DATABASE flask_data CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

3、数据库连接

CREATE DATABASE flask_data CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

GRANT ALL PRIVILEGES ON flask_data.* TO 'root'@'%' IDENTIFIED BY '12345678';

FLUSH PRIVILEGES;

EXIT;

在pycharm终端执行

flask db init

flask db migrate -m "initial migration"

flask db upgrade

4、数据库表设计

A pp/ models.py 核心代码

from datetime import datetime

from flask_login import UserMixin

from werkzeug.security import generate_password_hash, check_password_hash

from app import db, login

class User(UserMixin, db.Model):

"""用户表"""

tablename = 'users'

id = db.Column(db.Integer, primary_key=True)

username = db.Column(db.String(64), unique=True, nullable=False)

email = db.Column(db.String(120), unique=True, nullable=False)

password_hash = db.Column(db.String(255)) # 加密后的密码

messages = db.relationship('Message', backref='author', lazy='dynamic')

def set_password(self, password):

self.password_hash = generate_password_hash(password)

def check_password(self, password):

return check_password_hash(self.password_hash, password)

class Message(db.Model):

tablename = 'messages'

id = db.Column(db.Integer, primary_key=True)

title = db.Column(db.String(100), nullable=False)

content = db.Column(db.Text, nullable=False)

user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

created_at = db.Column(db.DateTime, default=datetime.utcnow)

updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

三线表描述
  1. users表结构

|---------------|--------------|------------|
| 字段名 | 类型 | 说明 |
| id | INT | 主键,自增 |
| username | VARCHAR(64) | 用户名,唯一 |
| email | VARCHAR(120) | 邮箱,唯一 |
| password_hash | VARCHAR(255) | 加密后的密码 |
| created_at | DATETIME | 创建时间 |

  1. messages表结构

|-------------|--------------|---------------|
| 字段名 | 类型 | 说明 |
| id | INT | 主键,自增 |
| title | VARCHAR(100) | 留言标题 |
| content | TEXT | 留言内容 |
| user_id | INT | 外键,关联users.id |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 最后更新时间 |

四、留言板模块设计

1、登陆模块

功能组成:登录模块提供完整的用户认证流程,包含四大核心功能:首先,用户注册功能实现账户创建,采用密码加密存储确保安全性;其次,登录功能支持凭证验证和会话管理;第三,退出功能可安全终止用户会话;最后,"记住我"选项通过持久化Cookie提升用户体验。所有密码均通过加密算法处理后再存储,即使数据库泄露也不会暴露原始密码。
核心代码 (auth/views.py):

from flask import render_template, redirect, url_for, flash, request

from flask_login import login_user, logout_user, current_user

from app import db

from app.auth import bp

from app.auth.forms import LoginForm, RegistrationForm

from app.models import User

@bp.route('/login', methods=['GET', 'POST'])

def login():

if current_user.is_authenticated:

return redirect(url_for('main.index'))

form = LoginForm()

if form.validate_on_submit():

user = User.query.filter_by(username=form.username.data).first()

if user is None or not user.check_password(form.password.data):

flash('无效的用户名或密码')

return redirect(url_for('auth.login'))

login_user(user, remember=form.remember_me.data)

next_page = request.args.get('next')

return redirect(next_page) if next_page else redirect(url_for('main.index'))

return render_template('auth/login.html', title='登录', form=form)

@bp.route('/logout')

def logout():

print(f"退出前用户: {current_user}") # 调试信息

logout_user()

print(f"退出后用户: {current_user}") # 调试信息

return redirect(url_for('main.index'))

@bp.route('/register', methods=['GET', 'POST'])

def register():

if current_user.is_authenticated:

return redirect(url_for('main.index'))

form = RegistrationForm()

if form.validate_on_submit():

user = User(username=form.username.data, email=form.email.data)

user.set_password(form.password.data)

db.session.add(user)

db.session.commit()

flash('恭喜,注册成功!')

return redirect(url_for('auth.login'))

return render_template('auth/register.html', title='注册', form=form)

2、留言板模块

功能组成: 留言板模块构成应用的核心功能体系:分页显示的留言列表提供内容概览;留言详情页展示完整内容和元信息;新增留言功能支持富文本内容创建;编辑功能允许作者修改已有内容;删除功能实现内容移除。每个功能点都进行了严格的权限控制,确保用户只能管理自己的内容,同时所有数据库操作都通过ORM进行,避免SQL注入风险

核心代码 (main/views.py):

@bp.route('/')

def index():

page = request.args.get('page', 1, type=int)

messages = Message.query.order_by(Message.created_at.desc()).paginate(

page=page, per_page=current_app.config['MESSAGES_PER_PAGE'])

return render_template('main/messages.html', messages=messages)

@bp.route('/create_message', methods=['GET', 'POST'])

@login_required

def create_message():

form = MessageForm()

if form.validate_on_submit():

message = Message(

title=form.title.data,

content=form.content.data,

author=current_user

)

db.session.add(message)

db.session.commit()

flash('留言已发布!')

return redirect(url_for('main.index'))

return render_template('main/create_message.html', form=form)

@bp.route('/message/<int:id>')

def message_detail(id):

message = Message.query.get_or_404(id)

return render_template('main/message_detail.html', message=message)

@bp.route('/edit_message/<int:id>', methods=['GET', 'POST'])

@login_required

def edit_message(id):

message = Message.query.get_or_404(id)

if message.author != current_user:

abort(403)

form = MessageForm()

if form.validate_on_submit():

message.title = form.title.data

message.content = form.content.data

db.session.commit()

flash('留言已更新!')

return redirect(url_for('main.message_detail', id=id))

elif request.method == 'GET':

form.title.data = message.title

form.content.data = message.content

return render_template('main/edit_message.html', form=form)

@bp.route('/delete_message/<int:id>', methods=['POST'])

@login_required

def delete_message(id):

message = Message.query.get_or_404(id)

if message.author != current_user:

abort(403)

db.session.delete(message)

db.session.commit()

flash('留言已删除!')

return redirect(url_for('main.index'))

五、页面设计

1、登陆模块

以下我分别用dbb、hahaha、dbbb三个号来讲述

登录页面 (login.html) 特点:

登录页面采用Bootstrap 5框架实现响应式布局,能够完美适配从手机到桌面电脑的各种设备屏幕尺寸。表单设计实现了双重验证机制,既包含前端JavaScript实时验证,又通过Flask-WTF进行服务器端校验,确保数据安全性。错误提示采用醒目的红色边框和文字说明,直观展示验证失败的具体原因,帮助用户快速定位问题。"记住我"功能通过设置持久化Cookie实现,为用户提供便捷的自动登录体验。页面底部设有明显的注册入口链接,引导未注册用户快速跳转到注册页面,形成完整的用户引导流程。

代码如下

{% extends "main/base.html" %}

{% block title %}登录{% endblock %}

{% block content %}

<div class="row justify-content-center">

<div class="col-md-6">

<div class="card">

<div class="card-body">

<h2 class="card-title text-center mb-4">登录</h2>

<form method="POST" action="{{ url_for('auth.login') }}">

{{ form.hidden_tag() }}

<div class="mb-3">

{{ form.username.label(class="form-label") }}

{{ form.username(class="form-control") }}

{% if form.username.errors %}

<div class="invalid-feedback d-block">

{% for error in form.username.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3">

{{ form.password.label(class="form-label") }}

{{ form.password(class="form-control") }}

{% if form.password.errors %}

<div class="invalid-feedback d-block">

{% for error in form.password.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3 form-check">

{{ form.remember_me(class="form-check-input") }}

{{ form.remember_me.label(class="form-check-label") }}

</div>

<div class="d-grid">

{{ form.submit(class="btn btn-primary") }}

</div>

</form>

<div class="mt-3 text-center">

<p>新用户?<a href="{{ url_for('auth.register') }}">点击注册</a></p>

</div>

</div>

</div>

</div>

</div>

{% endblock %}

注册页面 (register.html) 特点:

注册页面实现了全面的表单验证体系,包括用户名唯一性检查(实时查询数据库)、标准邮箱格式验证(使用email-validator库)以及密码强度要求(最少8位字符)。密码确认字段通过WTForms的EqualTo验证器确保两次输入一致,防止输入错误。所有验证结果都会通过动态错误提示实时反馈,在输入框下方即时显示具体错误信息,大幅提升填写效率。页面保留了良好的用户引导设计,底部设有登录入口链接,方便已有账号的用户快速切换到登录界面,形成注册-登录的闭环体验。

代码如下:{% extends "main/base.html" %}

{% block title %}注册{% endblock %}

{% block content %}

<div class="row justify-content-center">

<div class="col-md-6">

<div class="card">

<div class="card-body">

<h2 class="card-title text-center mb-4">注册</h2>

<form method="POST" action="{{ url_for('auth.register') }}">

{{ form.hidden_tag() }}

<div class="mb-3">

{{ form.username.label(class="form-label") }}

{{ form.username(class="form-control") }}

{% if form.username.errors %}

<div class="invalid-feedback d-block">

{% for error in form.username.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3">

{{ form.email.label(class="form-label") }}

{{ form.email(class="form-control") }}

{% if form.email.errors %}

<div class="invalid-feedback d-block">

{% for error in form.email.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3">

{{ form.password.label(class="form-label") }}

{{ form.password(class="form-control") }}

{% if form.password.errors %}

<div class="invalid-feedback d-block">

{% for error in form.password.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3">

{{ form.password2.label(class="form-label") }}

{{ form.password2(class="form-control") }}

{% if form.password2.errors %}

<div class="invalid-feedback d-block">

{% for error in form.password2.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="d-grid">

{{ form.submit(class="btn btn-primary") }}

</div>

</form>

<div class="mt-3 text-center">

<p>已有账号?<a href="{{ url_for('auth.login') }}">点击登录</a></p>

</div>

</div>

</div>

</div>

</div>

{% endblock %}

2、留言板模块

基础模板 (base.html) 特点:

基础模板采用Bootstrap 5框架构建统一的UI风格,确保整个应用保持一致的视觉效果。响应式导航栏能自动适应不同设备屏幕尺寸,并根据用户登录状态动态显示对应的功能入口(如登录用户显示"发布留言"和"退出"按钮,未登录用户显示"登录"和"注册"按钮)。通过Flask的消息闪现系统,所有操作结果都会以醒目的提示框形式展示在页面顶部,增强用户交互体验。导航栏还实时显示当前登录用户名,让用户随时感知自己的登录状态。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}留言板{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
padding-top: 20px;
background-color: #f8f9fa;
}
.message-card {
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.pagination {
justify-content: center;
margin-top: 20px;
}
/* 确保导航栏项目正确对齐 */
.navbar-nav {
align-items: center;
}
</style>
</head>
<body>
<div class="container">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('main.index') }}">留言板</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.index') }}">首页</a>
</li>
{% if current_user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.create_message') }}">发布留言</a>
</li>
{% endif %}
</ul>
<ul class="navbar-nav">
{% if current_user.is_authenticated %}
<li class="nav-item">
<span class="navbar-text me-2">欢迎, {{ current_user.username }}</span>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('auth.logout') }}" id="logoutLink">退出</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('auth.login') }}">登录</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('auth.register') }}">注册</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>

{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}

{% block content %}{% endblock %}
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 确保退出链接正常工作
document.getElementById('logoutLink')?.addEventListener('click', function() {
// 可以在这里添加确认对话框
return confirm('确定要退出吗?');
});
</script>
</body>
</html>

留言列表 (messages.html) 特点:

留言列表页面采用卡片式布局展示内容摘要,每张卡片包含留言标题、部分内容和关键元信息。分页控件位于页面底部,支持大量数据的分批加载和浏览。每条留言卡片都清晰标注作者用户名和发布时间,并采用条件渲染技术,仅对留言作者显示"编辑"和"删除"操作按钮。卡片标题链接到详情页,方便用户查看完整内容。整体布局简洁明了,信息层级分明。

代码如下:

{% extends "main/base.html" %}

{% block title %}留言板{% endblock %}

{% block content %}

<div class="row">

<div class="col-md-8 mx-auto">

<h1 class="mb-4">所有留言</h1>

{% for message in messages.items %}

<div class="card message-card mb-3">

<div class="card-body">

<h2 class="card-title">

<a href="{{ url_for('main.message_detail', id=message.id) }}" class="text-decoration-none">

{{ message.title }}

</a>

</h2>

<p class="card-text text-muted">

{{ message.content[:100] }}... <!-- 显示前100个字符 -->

</p>

<div class="d-flex justify-content-between align-items-center">

<small class="text-muted">

作者: {{ message.author.username }} |

发布于: {{ message.created_at.strftime('%Y-%m-%d %H:%M') }}

</small>

{% if current_user == message.author %}

<div>

<a href="{{ url_for('main.edit_message', id=message.id) }}" class="btn btn-sm btn-outline-primary">编辑</a>

</div>

{% endif %}

</div>

</div>

</div>

{% else %}

<div class="alert alert-info">暂无留言</div>

{% endfor %}

<!-- 分页导航 -->

<nav aria-label="Message navigation">

<ul class="pagination justify-content-center">

{% if messages.has_prev %}

<li class="page-item">

<a class="page-link" href="{{ url_for('main.index', page=messages.prev_num) }}">上一页</a>

</li>

{% endif %}

<li class="page-item disabled">

<span class="page-link">第 {{ messages.page }} 页 / 共 {{ messages.pages }} 页</span>

</li>

{% if messages.has_next %}

<li class="page-item">

<a class="page-link" href="{{ url_for('main.index', page=messages.next_num) }}">下一页</a>

</li>

{% endif %}

</ul>

</nav>

<div class="text-center mt-3">

<a href="{{ url_for('main.create_message') }}" class="btn btn-primary">发布新留言</a>

</div>

</div>

</div>

{% endblock %}

留言详情 (message_detail.html) 特点:

详情页完整展示留言的标题和内容,在显著位置标注作者信息和创建时间。如果留言被编辑过,还会额外显示最后更新时间,让读者了解内容的新鲜度。页面底部为留言作者提供了专属操作区,包含"编辑"和"删除"按钮,非作者用户则看不到这些功能入口。所有内容采用舒适的排版和合适的字体大小,确保最佳阅读体验。

代码如下:

{% extends "main/base.html" %}

{% block title %}{{ message.title }}{% endblock %}

{% block content %}
<div class="row">
<div class="col-md-8 mx-auto">
<div class="card message-card">
<div class="card-body">
<h2 class="card-title">{{ message.title }}</h2>
<div class="card-text mb-4">
{{ message.content|safe }}
</div>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">
作者: {{ message.author.username }} |
发布于: {{ message.created_at.strftime('%Y-%m-%d %H:%M') }} |
最后更新: {{ message.updated_at.strftime('%Y-%m-%d %H:%M') }}
</small>
{% if current_user == message.author %}
<div>
<a href="{{ url_for('main.edit_message', id=message.id) }}" class="btn btn-outline-primary">编辑</a>
<form action="{{ url_for('main.delete_message', id=message.id) }}" method="post" class="d-inline">
<button type="submit" class="btn btn-outline-danger" οnclick="return confirm('确定删除吗?')">删除</button>
</form>
</div>
{% endif %}
</div>
</div>
</div>

<div class="mt-3">
<a href="{{ url_for('main.index') }}" class="btn btn-secondary">返回列表</a>
</div>
</div>
</div>
{% endblock %}

创建/编辑页面 (create_message.html/edit_message.html) 特点:

这两个页面共享相似的表单结构,都实现了严格的表单验证机制,包括必填项检查和内容长度限制。富文本编辑区域支持基本的格式设置,提升内容输入体验。在编辑模式下,表单会自动载入原有数据,方便用户修改。所有破坏性操作(如删除)都要求二次确认,通过JavaScript弹窗提示用户确认操作,有效防止误操作导致的数据丢失。页面布局保持简洁,突出核心的表单区域。

create_message.html:

{% extends "main/base.html" %}

{% block title %}发布留言{% endblock %}

{% block content %}

<div class="row">

<div class="col-md-8 mx-auto">

<h1 class="mb-4">发布留言</h1>

<form method="POST" action="{{ url_for('main.create_message') }}">

{{ form.hidden_tag() }}

<div class="mb-3">

{{ form.title.label(class="form-label") }}

{{ form.title(class="form-control") }}

{% if form.title.errors %}

<div class="invalid-feedback d-block">

{% for error in form.title.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3">

{{ form.content.label(class="form-label") }}

{{ form.content(class="form-control", rows=8) }}

{% if form.content.errors %}

<div class="invalid-feedback d-block">

{% for error in form.content.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="d-grid">

{{ form.submit(class="btn btn-primary") }}

</div>

</form>

</div>

</div>

{% endblock %}
edit_message.html:

{% extends "main/base.html" %}

{% block title %}编辑留言{% endblock %}

{% block content %}

<div class="row">

<div class="col-md-8 mx-auto">

<h1 class="mb-4">编辑留言</h1>

<form method="POST" action="{{ url_for('main.edit_message', id=message.id) }}">

{{ form.hidden_tag() }}

<div class="mb-3">

{{ form.title.label(class="form-label") }}

{{ form.title(class="form-control") }}

{% if form.title.errors %}

<div class="invalid-feedback d-block">

{% for error in form.title.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="mb-3">

{{ form.content.label(class="form-label") }}

{{ form.content(class="form-control", rows=8) }}

{% if form.content.errors %}

<div class="invalid-feedback d-block">

{% for error in form.content.errors %}

{{ error }}

{% endfor %}

</div>

{% endif %}

</div>

<div class="d-grid gap-2 d-md-flex justify-content-md-end">

<a href="{{ url_for('main.message_detail', id=message.id) }}" class="btn btn-secondary me-md-2">取消</a>

{{ form.submit(class="btn btn-primary") }}

</div>

</form>

</div>

</div>

{% endblock %}

第一次进入页面

使用dbbb这个号第三次进入页面就有之前两个的留言

用第三个dbbb号进入并发布新留言

编辑留言

成功删除留言

相关推荐
喵手2 分钟前
StringUtils 工具类实战详解,你还不进来学习!
java·后端·java ee
喵手5 分钟前
如何快速实现文件上传、下载与读写操作?FileUtils有话要说~
java·后端·java ee
DongLi018 分钟前
Rust 变量和可变性
后端
Jooolin9 分钟前
【Python】什么?Python 可以用来写 Galgame?
python·游戏·ai编程
里探21 分钟前
Django中为api自定义一些装饰器:如参数校验等
python·django·装饰器模式
陈随易29 分钟前
一段时间没写文章了,花了10天放了个屁
前端·后端·程序员
星星电灯猴32 分钟前
抓包工具分析接口跳转异常:安全校验误判 Bug 全记录
后端
调试人生的显微镜33 分钟前
后台发热、掉电严重?iOS 应用性能问题实战分析全过程
后端
深栈解码42 分钟前
OpenIM 源码深度解析系列(十八):附录二数据库结构
后端
前端付豪1 小时前
Google Ads 广告系统排序与实时竞价架构揭秘
前端·后端·架构