Flask项目实践:构建功能完善的博客系统(含评论与标签功能)
引言
在Python Web开发领域,Flask以其轻量级、灵活性和易用性赢得了众多开发者的青睐。本文将带您从零开始构建一个功能完善的博客系统,包含文章发布、评论互动和标签分类等核心功能。通过这个实战项目,您不仅能掌握Flask的核心技术,还能学习到现代Web开发的最佳实践。
一、项目概述与初始化
1.1 系统功能规划
我们的博客系统将包含以下核心功能模块:
-
用户认证(注册/登录/登出)
-
博客文章管理(创建/编辑/删除)
-
评论系统(文章评论/回复)
-
标签分类(多标签关联)
-
文章分页与搜索
1.2 环境搭建
首先创建项目环境:
# 创建项目目录
mkdir flask-blog && cd flask-blog# 创建虚拟环境
python -m venv venv# 激活虚拟环境
# Windows: venv\Scripts\activate
# Mac/Linux: source venv/bin/activate# 安装Flask及其他依赖
pip install flask flask-sqlalchemy flask-login flask-wtf flask-migrate
1.3 项目结构设计
合理的项目结构是良好开端:
flask-blog/
│
├── app/
│ ├── __init__.py # 应用工厂函数
│ ├── models.py # 数据模型
│ ├── routes.py # 路由定义
│ ├── forms.py # 表单类
│ ├── templates/ # 模板文件
│ │ ├── base.html # 基础模板
│ │ ├── auth/ # 认证相关模板
│ │ └── blog/ # 博客相关模板
│ └── static/ # 静态文件
│
├── migrations/ # 数据库迁移脚本
├── config.py # 配置文件
└── run.py # 启动脚本
二、核心功能实现
2.1 数据库模型设计
在app/models.py
中定义我们的数据模型:
from datetime import datetime
from app import db, login_manager
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash# 用户模型
class User(UserMixin, db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), index=True, unique=True)email = db.Column(db.String(120), index=True, unique=True)password_hash = db.Column(db.String(128))posts = db.relationship('Post', backref='author', lazy='dynamic')comments = db.relationship('Comment', 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 Post(db.Model):id = db.Column(db.Integer, primary_key=True)title = db.Column(db.String(140))content = db.Column(db.Text)timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)user_id = db.Column(db.Integer, db.ForeignKey('user.id'))comments = db.relationship('Comment', backref='post', lazy='dynamic')tags = db.relationship('Tag', secondary='post_tag', backref=db.backref('posts', lazy='dynamic'))# 评论模型
class Comment(db.Model):id = db.Column(db.Integer, primary_key=True)content = db.Column(db.Text)timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)user_id = db.Column(db.Integer, db.ForeignKey('user.id'))post_id = db.Column(db.Integer, db.ForeignKey('post.id'))parent_id = db.Column(db.Integer, db.ForeignKey('comment.id'))replies = db.relationship('Comment', backref=db.backref('parent', remote_side=[id]), lazy='dynamic')# 标签模型
class Tag(db.Model):id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(50), unique=True)# 文章-标签关联表
post_tag = db.Table('post_tag',db.Column('post_id', db.Integer, db.ForeignKey('post.id')),db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'))
)@login_manager.user_loader
def load_user(id):return User.query.get(int(id))
2.2 用户认证系统
实现用户注册、登录和登出功能:
# app/forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, TextAreaField
from wtforms.validators import DataRequired, Email, EqualTo, Lengthclass LoginForm(FlaskForm):username = StringField('用户名', validators=[DataRequired()])password = PasswordField('密码', validators=[DataRequired()])submit = SubmitField('登录')class RegistrationForm(FlaskForm):username = StringField('用户名', validators=[DataRequired(), Length(min=4, max=25)])email = StringField('邮箱', validators=[DataRequired(), Email()])password = PasswordField('密码', validators=[DataRequired()])password2 = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password')])submit = SubmitField('注册')# app/routes.py
from flask import render_template, flash, redirect, url_for, request
from app import app, db
from app.forms import LoginForm, RegistrationForm
from app.models import User
from flask_login import current_user, login_user, logout_user, login_required@app.route('/login', methods=['GET', 'POST'])
def login():if current_user.is_authenticated:return redirect(url_for('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('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('index'))return render_template('auth/login.html', title='登录', form=form)@app.route('/register', methods=['GET', 'POST'])
def register():if current_user.is_authenticated:return redirect(url_for('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('login'))return render_template('auth/register.html', title='注册', form=form)@app.route('/logout')
def logout():logout_user()return redirect(url_for('index'))
2.3 博客文章管理
实现文章的增删改查功能:
# app/forms.py
class PostForm(FlaskForm):title = StringField('标题', validators=[DataRequired(), Length(max=140)])content = TextAreaField('内容', validators=[DataRequired()])tags = StringField('标签(用逗号分隔)')submit = SubmitField('发布')# app/routes.py
from app.forms import PostForm
from app.models import Post, Tag@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
@login_required
def index():form = PostForm()if form.validate_on_submit():post = Post(title=form.title.data, content=form.content.data, author=current_user)# 处理标签if form.tags.data:tag_names = [name.strip() for name in form.tags.data.split(',')]for name in tag_names:tag = Tag.query.filter_by(name=name).first()if tag is None:tag = Tag(name=name)db.session.add(tag)post.tags.append(tag)db.session.add(post)db.session.commit()flash('您的文章已发布!')return redirect(url_for('index'))page = request.args.get('page', 1, type=int)posts = Post.query.order_by(Post.timestamp.desc()).paginate(page, app.config['POSTS_PER_PAGE'], False)return render_template('blog/index.html', title='首页', form=form, posts=posts)@app.route('/post/<int:post_id>')
def post(post_id):post = Post.query.get_or_404(post_id)return render_template('blog/post.html', post=post)@app.route('/edit/<int:post_id>', methods=['GET', 'POST'])
@login_required
def edit_post(post_id):post = Post.query.get_or_404(post_id)if post.author != current_user:abort(403)form = PostForm()if form.validate_on_submit():post.title = form.title.datapost.content = form.content.data# 更新标签post.tags = []if form.tags.data:tag_names = [name.strip() for name in form.tags.data.split(',')]for name in tag_names:tag = Tag.query.filter_by(name=name).first()if tag is None:tag = Tag(name=name)db.session.add(tag)post.tags.append(tag)db.session.commit()flash('文章已更新')return redirect(url_for('post', post_id=post.id))elif request.method == 'GET':form.title.data = post.titleform.content.data = post.contentform.tags.data = ', '.join([tag.name for tag in post.tags])return render_template('blog/edit_post.html', title='编辑文章', form=form)@app.route('/delete/<int:post_id>', methods=['POST'])
@login_required
def delete_post(post_id):post = Post.query.get_or_404(post_id)if post.author != current_user:abort(403)db.session.delete(post)db.session.commit()flash('文章已删除')return redirect(url_for('index'))
2.4 评论系统实现
实现多级评论功能:
# app/forms.py
class CommentForm(FlaskForm):content = TextAreaField('评论内容', validators=[DataRequired()])submit = SubmitField('提交')# app/routes.py
from app.forms import CommentForm
from app.models import Comment@app.route('/post/<int:post_id>', methods=['GET', 'POST'])
def post(post_id):post = Post.query.get_or_404(post_id)form = CommentForm()if form.validate_on_submit():if not current_user.is_authenticated:flash('请先登录再评论')return redirect(url_for('login'))comment = Comment(content=form.content.data, author=current_user, post=post)db.session.add(comment)db.session.commit()flash('您的评论已发布')return redirect(url_for('post', post_id=post.id))# 获取顶级评论(非回复的评论)top_level_comments = Comment.query.filter_by(post_id=post.id, parent_id=None)\.order_by(Comment.timestamp.desc()).all()return render_template('blog/post.html', post=post, form=form, comments=top_level_comments)@app.route('/reply/<int:comment_id>', methods=['POST'])
@login_required
def reply(comment_id):parent_comment = Comment.query.get_or_404(comment_id)post = parent_comment.postform = CommentForm()if form.validate_on_submit():comment = Comment(content=form.content.data,author=current_user,post=post,parent=parent_comment)db.session.add(comment)db.session.commit()flash('您的回复已发布')return redirect(url_for('post', post_id=post.id))
2.5 标签功能实现
添加标签相关的视图函数:
@app.route('/tag/<string:tag_name>')
def tag(tag_name):tag = Tag.query.filter_by(name=tag_name).first_or_404()page = request.args.get('page', 1, type=int)posts = tag.posts.order_by(Post.timestamp.desc()).paginate(page, app.config['POSTS_PER_PAGE'], False)return render_template('blog/tag.html', tag=tag, posts=posts)@app.route('/tags')
def tags():all_tags = Tag.query.order_by(Tag.name).all()return render_template('blog/tags.html', tags=all_tags)
三、前端模板设计
3.1 基础模板 (base.html)
<!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 %} - Flask博客</title><link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}"><link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body><nav class="navbar navbar-expand-lg navbar-dark bg-primary"><div class="container"><a class="navbar-brand" href="{{ url_for('index') }}">Flask博客</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav mr-auto"><li class="nav-item"><a class="nav-link" href="{{ url_for('index') }}">首页</a></li><li class="nav-item"><a class="nav-link" href="{{ url_for('tags') }}">标签</a></li></ul><ul class="navbar-nav">{% if current_user.is_authenticated %}<li class="nav-item"><a class="nav-link" href="#">{{ current_user.username }}</a></li><li class="nav-item"><a class="nav-link" href="{{ url_for('logout') }}">退出</a></li>{% else %}<li class="nav-item"><a class="nav-link" href="{{ url_for('login') }}">登录</a></li><li class="nav-item"><a class="nav-link" href="{{ url_for('register') }}">注册</a></li>{% endif %}</ul></div></div></nav><div class="container mt-4">{% 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="close" data-dismiss="alert"><span>×</span></button></div>{% endfor %}{% endif %}{% endwith %}{% block content %}{% endblock %}</div><footer class="mt-5 py-3 bg-light"><div class="container text-center"><span class="text-muted">© 2023 Flask博客系统</span></div></footer><script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script><script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>{% block scripts %}{% endblock %}
</body>
</html>
3.2 文章列表模板 (index.html)
{% extends "base.html" %}{% block content %}<div class="row"><div class="col-md-8"><h2 class="mb-4">最新文章</h2>{% if current_user.is_authenticated %}<div class="card mb-4"><div class="card-body"><h5 class="card-title">发表新文章</h5><form method="POST" action="">{{ form.hidden_tag() }}<div class="form-group">{{ form.title(class="form-control", placeholder="文章标题") }}</div><div class="form-group">{{ form.content(class="form-control", rows=5, placeholder="文章内容") }}</div><div class="form-group">{{ form.tags(class="form-control", placeholder="标签(用逗号分隔)") }}</div><div class="form-group">{{ form.submit(class="btn btn-primary") }}</div></form></div></div>{% endif %}{% for post in posts.items %}<div class="card mb-4"><div class="card-body"><h3 class="card-title"><a href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h3><p class="text-muted">作者: <a href="#">{{ post.author.username }}</a> | 发布于: {{ post.timestamp.strftime('%Y-%m-%d %H:%M') }}</p><p class="card-text">{{ post.content[:200] }}...</p><div class="mb-2">{% for tag in post.tags %}<a href="{{ url_for('tag', tag_name=tag.name) }}" class="badge badge-secondary">{{ tag.name }}</a>{% endfor %}</div><a href="{{ url_for('post', post_id=post.id) }}" class="btn btn-sm btn-outline-primary">阅读全文 →</a></div></div>{% endfor %}<nav aria-label="Page navigation"><ul class="pagination"><li class="page-item {% if not posts.has_prev %}disabled{% endif %}"><a class="page-link" href="{{ url_for('index', page=posts.prev_num) }}">上一页</a></li>{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=2, right_current=3) %}{% if page_num %}<li class="page-item {% if posts.page == page_num %}active{% endif %}"><a class="page-link" href="{{ url_for('index', page=page_num) }}">{{ page_num }}</a></li>{% else %}<li class="page-item disabled"><span class="page-link">...</span></li>{% endif %}{% endfor %}<li class="page-item {% if not posts.has_next %}disabled{% endif %}"><a class="page-link" href="{{ url_for('index', page=posts.next_num) }}">下一页</a></li></ul></nav></div><div class="col-md-4"><div class="card mb-4"><div class="card-header">热门标签</div><div class="card-body">{% for tag in Tag.query.order_by(Tag.name).limit(20).all() %}<a href="{{ url_for('tag', tag_name=tag.name) }}" class="badge badge-light mr-1 mb-1">{{ tag.name }}</a>{% endfor %}</div></div></div></div>
{% endblock %}
3.3 文章详情模板 (post.html)
{% extends "base.html" %}{% block content %}<div class="row"><div class="col-md-8"><article class="card mb-4"><div class="card-body"><h1 class="card-title">{{ post.title }}</h1><p class="text-muted">作者: <a href="#">{{ post.author.username }}</a> | 发布于: {{ post.timestamp.strftime('%Y-%m-%d %H:%M') }}{% if current_user == post.author %}<span class="float-right"><a href="{{ url_for('edit_post', post_id=post.id) }}" class="btn btn-sm btn-outline-secondary">编辑</a><form method="POST" action="{{ url_for('delete_post', post_id=post.id) }}" class="d-inline"><button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('确定要删除这篇文章吗?')">删除</button></form></span>{% endif %}</p><div class="mb-3">{% for tag in post.tags %}<a href="{{ url_for('tag', tag_name=tag.name) }}" class="badge badge-secondary">{{ tag.name }}</a>{% endfor %}</div><div class="card-text">{{ post.content | safe }}</div></div></article><div class="card mb-4"><div class="card-header"><h4>评论 ({{ post.comments.count() }})</h4></div><div class="card-body">{% if current_user.is_authenticated %}<form method="POST" action="">{{ form.hidden_tag() }}<div class="form-group">{{ form.content(class="form-control", rows=3, placeholder="写下你的评论...") }}</div><div class="form-group">{{ form.submit(class="btn btn-primary") }}</div></form>{% else %}<p class="text-muted"><a href="{{ url_for('login') }}">登录</a>后发表评论</p>{% endif %}<div class="mt-4">{% for comment in comments %}{% include '_comment.html' %}{% endfor %}</div></div></div></div></div>
{% endblock %}
3.4 评论子模板 (_comment.html)
<div class="media mb-4" id="comment-{{ comment.id }}"><img src="{{ url_for('static', filename='images/avatar.png') }}" class="mr-3 rounded-circle" width="50" alt="头像"><div class="media-body"><h6 class="mt-0"><strong>{{ comment.author.username }}</strong><small class="text-muted">{{ comment.timestamp.strftime('%Y-%m-%d %H:%M') }}</small>{% if current_user.is_authenticated %}<button class="btn btn-sm btn-link reply-btn" data-comment-id="{{ comment.id }}">回复</button>{% endif %}</h6><p>{{ comment.content }}</p><!-- 回复表单 (默认隐藏) --><div class="reply-form" id="reply-form-{{ comment.id }}" style="display: none;"><form method="POST" action="{{ url_for('reply', comment_id=comment.id) }}">{{ form.hidden_tag() }}<div class="form-group">{{ form.content(class="form-control", rows=2, placeholder="写下你的回复...") }}</div><div class="form-group"><button type="submit" class="btn btn-primary btn-sm">提交回复</button><button type="button" class="btn btn-secondary btn-sm cancel-reply">取消</button></div></form></div><!-- 回复列表 -->{% for reply in comment.replies.order_by(Comment.timestamp.asc()) %}<div class="media mt-3 pl-3 border-left"><img src="{{ url_for('static', filename='images/avatar.png') }}" class="mr-3 rounded-circle" width="40" alt="头像"><div class="media-body"><h6 class="mt-0"><strong>{{ reply.author.username }}</strong><small class="text-muted">{{ reply.timestamp.strftime('%Y-%m-%d %H:%M') }}</small></h6><p>{{ reply.content }}</p></div></div>{% endfor %}</div>
</div>{% block scripts %}
<script>
$(document).ready(function() {// 回复按钮点击事件$('.reply-btn').click(function() {var commentId = $(this).data('comment-id');$('#reply-form-' + commentId).show();$(this).hide();});// 取消回复按钮点击事件$('.cancel-reply').click(function() {var form = $(this).closest('.reply-form');form.hide();form.siblings('.reply-btn').show();});
});
</script>
{% endblock %}
四、项目部署与优化
4.1 配置生产环境
创建config.py
配置文件:
import os
from dotenv import load_dotenvbasedir = 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-secret-key'SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \'sqlite:///' + os.path.join(basedir, 'app.db')SQLALCHEMY_TRACK_MODIFICATIONS = FalsePOSTS_PER_PAGE = 10class ProductionConfig(Config):passclass DevelopmentConfig(Config):DEBUG = Trueconfig = {'development': DevelopmentConfig,'production': ProductionConfig,'default': DevelopmentConfig
}
4.2 使用Gunicorn部署
安装Gunicorn:
pip install gunicorn
创建启动脚本wsgi.py
:
from app import create_appapp = create_app()if __name__ == '__main__':app.run()
启动命令:
gunicorn -w 4 -b 0.0.0.0:8000 wsgi:app
4.3 性能优化建议
-
数据库优化:
-
为常用查询字段添加索引
-
使用Flask-SQLAlchemy的
get()
代替filter_by().first()
-
合理使用
lazy
加载策略
-
-
缓存策略:
-
使用Flask-Caching缓存频繁访问的数据
-
实现文章浏览计数器的延迟更新
-
-
静态文件处理:
-
配置Nginx直接处理静态文件
-
使用CDN分发静态资源
-
启用Gzip压缩
-
五、项目扩展方向
-
用户个人中心:
-
头像上传功能
-
个人资料编辑
-
用户关注系统
-
-
增强搜索功能:
-
实现全文搜索(Elasticsearch或Whoosh)
-
添加搜索建议和自动完成
-
-
社交功能:
-
文章点赞/收藏
-
用户私信系统
-
通知系统
-
-
API开发:
-
使用Flask-RESTful开发RESTful API
-
实现前后端分离架构
-
结语
通过本教程,我们完成了一个功能完善的Flask博客系统,包含了用户认证、文章管理、评论系统和标签分类等核心功能。这个项目不仅展示了Flask的核心技术,也体现了现代Web开发的最佳实践。
希望这个项目能作为您Flask学习之旅的良好起点。您可以根据自己的需求继续扩展功能,比如添加用户头像、实现文章搜索、开发RESTful API等。
如果您在实现过程中遇到任何问题,或者有改进建议,欢迎在评论区留言讨论!
相关文章:
Flask项目实践:构建功能完善的博客系统(含评论与标签功能)
引言 在Python Web开发领域,Flask以其轻量级、灵活性和易用性赢得了众多开发者的青睐。本文将带您从零开始构建一个功能完善的博客系统,包含文章发布、评论互动和标签分类等核心功能。通过这个实战项目,您不仅能掌握Flask的核心技术…...
Python爬虫实战:获取1688商品信息
在电商领域,获取1688商品信息对于市场分析、竞品研究、用户体验优化等至关重要。1688作为国内领先的B2B电商平台,提供了丰富的商品资源。通过Python爬虫技术,我们可以高效地获取1688商品的详细信息,包括商品名称、价格、图片、描述…...
Canva 推出自有应用生成器以与 Bolt 和 Lovable 竞争
AI 目前是一个巨大的市场,每个人都想从中分一杯羹。 即使是 Canva,这个以拖放图形设计而闻名的流行设计平台,也在其 Canva Create 2025 活动中发布了自己版本的代码生成器,加入了 AI 竞赛。 但为什么一个以设计为先的平台会提供代码生成工具呢? 乍看之下,这似乎有些不…...
多平台屏幕江湖生存指南
UniApp 屏幕适配大师:多平台屏幕江湖生存指南 屏幕江湖:尺寸混战 屏幕适配就像是应对不同体型的客人:从迷你的手机屏,到标准的平板,再到巨大的电视屏幕,你的应用必须有如武林高手般的适应力。 ┌──────────────────────────────────…...
BootCDN介绍(Bootstrap主导的前端开源项目免费CDN加速服务)
文章目录 BootCDN前端开源项目CDN加速服务全解析什么是BootCDN技术原理与架构CDN技术基础BootCDN架构特点1. 全球分布式节点网络2. 智能DNS解析系统3. 高效缓存管理机制4. 自动同步更新机制5. HTTPS和HTTP/2协议支持 BootCDN的核心优势速度与稳定性开源免费资源丰富度技术规范遵…...
LeetCode 153. 寻找旋转排序数组中的最小值:二分查找法详解及高频疑问解析
文章目录 问题描述算法思路:二分查找法关键步骤 代码实现代码解释高频疑问解答1. 为什么循环条件是 left < right 而不是 left < right?2. 为什么比较 nums[mid] > nums[right] 而不是 nums[left] < nums[mid]?3. 为什么 right …...
刷leetcodehot100返航版--二叉树
二叉树理论基础 二叉树的种类 满二叉树和完全二叉树,二叉树搜索树 满二叉树 如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。 节点个数2^n-1【n为树的深度】 完全二叉树 在完全二叉树…...
「Mac畅玩AIGC与多模态41」开发篇36 - 用 ArkTS 构建聚合搜索前端页面
一、概述 本篇基于上一节 Python 实现的双通道搜索服务(聚合 SearxNG 本地知识库),构建一个完整的 HarmonyOS ArkTS 前端页面。用户可在输入框中输入关键词,实时查询本地服务 http://localhost:5001/search?q...,返…...
【LINUX操作系统】生产者消费者模型(下):封装、信号量与环形队列
1.封装、完善基于阻塞队列的productor-consumer module 前文中我们封装了自己的Mutex 【LINUX操作系统】线程同步与互斥-CSDN博客 按照老规矩,现在我们对同步与互斥的理解更进一步了,现在把这种面向过程的语言封装成面向对象的写法 1.1 封装条件变量 #p…...
项目管理学习-CSPM-4考试总结
前言 经过两个月左右时间的学习,今天(2025年5月17日)参加了CSPM-4的考试,仿佛回到了2011年参加软考高项的时候。中午12点考完出来后,手都是酸酸的。不过整体感觉还可以,和预想的差不多。CSPM-4的考试一共有…...
自己手写tomcat项目
一:Servlet的原理 在Servlet(接口中)有: 1.init():初始化servlet 2.getServletConfig():获取当前servlet的配置信息 3.service():服务器(在HttpServlet中实现,目的是为了更好的匹配http的请求方式) 4.g…...
C语言—再学习(结构体)
一、建立结构体 用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体。 struct Student { int num; //学号char name[20]; //名字为字符串char sex; //性别int age; //年纪float score; //分数char addr[30]; 地址为字符…...
SpringBoot--自动配置原理详解
为什么要学习自动配置原理? 原因:在实际开发中,我们经常会定义一些公共的组件,提供各个团队来使用,为了使用方便,我们经常会将公共的组件自定义成starter,如果想自定义starter,必须…...
MiInsertPageInFreeList函数分析和MmFreePagesByColor数组的关系
第一部分: Color MI_GET_COLOR_FROM_LIST_ENTRY(PageFrameIndex, Pfn1); ColorHead &MmFreePagesByColor[ListName][Color]; 第二部分: #define MI_GET_COLOR_FROM_LIST_ENTRY(index,pfn) \ ((ULONG)(((pfn)->…...
Windows/MacOS WebStorm/IDEA 中开发 Uni-App 配置
文章目录 前言1. 安装 HBuilder X2. WebStorm/IDEA 安装 Uniapp Tool 插件3. 配置 Uniapp Tool 插件4. 运行 Uni-App 项目 前言 前端开发人员对 WebStorm 一定不陌生,但有时需要开发 Uni-App 的需求,就必须要采用 HBuilder X,如果不习惯 HBu…...
redisson分布式锁实现原理归纳总结
Redisson 分布式锁的实现原理主要依赖于 Redis 的 Hash 数据结构、Lua 脚本、发布订阅机制以及看门狗(Watchdog)机制,以下是核心要点总结: 1. 核心原理 • 互斥性与可重入性: 通过 Redis 的 Hash 数据结构保存锁的持…...
Ubuntu 添加系统调用
实验内容 通过内核编译法添加一个不用传递参数的系统调用,其功能可自定义。 (1)添加系统调用号,系统会根据这个号找到syscall_table中的相应表项。具体做法是在syscall_64.tbl文件中添加系统调用号和调用函数的对应关系。 &#…...
Olib 2.2.0 | 免费开源软件,无需注册登录即可从ZLibrary下载多语言电子书
Olib是一款专为书籍爱好者设计的免费开源软件,它允许用户无需注册或登录即可从ZLibrary高速下载各种语言的电子书。该软件支持上百种语言的电子书下载,非常适合需要多语言资源的读者和研究人员使用。Olib的操作界面非常直观,使得书籍的搜索与…...
c++动态链接库
1. 生成动态链接库 首先实现一个动态链接库的代码 // example.cpp #include <iostream> void sayHello() {std::cout << "Hello from shared library!" << std::endl; }int add(int a, int b) {return a b; }// example.h #pragma once void sa…...
HelloWorld
HelloWorld 新建一个java文件 文件后缀名为 .javahello.java【注意】系统可能没有显示文件后缀名,我们需要手动打开 编写代码 public class hello {public static void main(String[] args) {System.out.print(Hello,World)} }编译 javac java文件,会生…...
SVGPlay:一次 CodeBuddy 主动构建的动画工具之旅
我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 背景与想法 我一直对 SVG 图标的动画处理有浓厚兴趣,特别是描边、渐变、交互等效果能为图标增添许…...
SLAM定位常用地图对比示例
序号 地图类型 概述 1 格栅地图 将现实环境栅格化,每一个栅格用 0 和 1 分别表示空闲和占据状态,初始化为未知状态 0.5 2 特征地图 以点、线、面等几何特征来描绘周围环境,将采集的信息进行筛选和提取得到关键几何特征 3 拓扑地图 将重要部分抽象为地图,使用简单的图形表示…...
强化学习中,frames(帧)和 episodes(回合)
在强化学习中,frames(帧)和 episodes(回合)是两个不同的概念: 1. 定义差异 Frame(帧): 表示智能体与环境交互的单个时间步(step),例如…...
HCIP第六次作业
一、拓扑图 二、需求 1、使用PreVal策略,确保R4通过R2到达192.168.10.0/24 2、使用AS_Path策略,确保R4通过R3到达192.168.11.0/24 3、配置MED策略,确保R4通过R3到达192.168.12.0/24 4、使用Local Preference策略,确保R1通过R2…...
高频面试题(含笔试高频算法整理)基本总结回顾110
干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…...
数据湖与数据仓库融合:Hudi、Iceberg、Delta Lake 实践对比
在实时与离线一体化的今天,数据湖与数据仓库边界不断融合,越来越多企业选用如 Hudi、Iceberg、Delta Lake 等开源方案实现统一的数据存储、计算、分析平台。本篇将围绕以下关键点,展开实战对比与解决方案分享: ✅ 实时写入能力 ✅ ACID 保证 ✅ 增量数据处理能力 ✅ 流批一…...
OGG 更新表频繁导致进程中断,见鬼了?非也!
大家好,这里是 DBA学习之路,专注于提升数据库运维效率。 目录 前言问题描述问题分析解决方案后续 前言 最近几周一直遇到一个 OGG 问题,有一张表已更新就会中断 OGG 同步进程,本文记录一下分析过程以及解决方案。 问题描述 昨天…...
C++学习-入门到精通-【7】类的深入剖析
C学习-入门到精通-【7】类的深入剖析 类的深入剖析 C学习-入门到精通-【7】类的深入剖析一、Time类的实例研究二、组成和继承三、类的作用域和类成员的访问类作用域和块作用域圆点成员选择运算符(.)和箭头成员选择运算符(->)访问函数和工具函数 四、具有默认实参的构造函数重…...
非易失性存储技术综合对比:EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡
非易失性存储技术综合对比:EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡 读写性能对比 存储类型读取速度写入速度随机访问能力最小操作单位NVRAM极快(~10ns)极快(~10ns)极优(字节级)字节EEPROM中等(~100ns)慢(~5ms/字节)优(字节级)字节NOR Flash快(~50ns)慢(~5ms/…...
数字化转型- 数字化转型路线和推进
数字化转型三个阶段 百度百科给出的企业的数字化转型包括信息化、数字化、数智化三个阶段 信息化是将企业在生产经营过程中产生的业务信息进行记录、储存和管理,通过电子终端呈现,便于信息的传播与沟通。数字化通过打通各个系统的互联互通,…...
ARM (Attention Refinement Module)
ARM模块【来源于BiSeNet】:细化特征图的注意力,增强重要特征并抑制不重要的特征。 Attention Refinement Module (ARM) 详解 ARM (Attention Refinement Module) 是 BiSeNet 中用于增强特征表示的关键模块,它通过注意力机制来细化特征图&…...
符合Python风格的对象(对象表示形式)
对象表示形式 每门面向对象的语言至少都有一种获取对象的字符串表示形式的标准方 式。Python 提供了两种方式。 repr() 以便于开发者理解的方式返回对象的字符串表示形式。str() 以便于用户理解的方式返回对象的字符串表示形式。 正如你所知,我们要实现_…...
AtCoder AT_abc406_c [ABC406C] ~
前言 除了 A 题,唯一一道一遍过的题。 题目大意 我们定义满足以下所有条件的一个长度为 N N N 的序列 A ( A 1 , A 2 , … , A N ) A(A_1,A_2,\dots,A_N) A(A1,A2,…,AN) 为波浪序列: N ≥ 4 N\ge4 N≥4(其实满足后面就必须满足这…...
多指标组合策略
该策略(MultiConditionStrategy)是一种基于多种技术指标和市场条件的交易策略。它通过综合考虑多个条件来生成交易信号,从而决定买入或卖出的时机。 以下是对该策略的详细分析: 交易逻辑思路 1. 条件1:星期几和价格变化判断 - 该条件根据当前日期是星期几以及价格的变化…...
系统架构-大数据架构设计
基础介绍 三大挑战: 如何处理非结构化和半结构化数据如何探索大数据复杂性、不确定性特征描述的刻画方法及大数据的系统建模数据异构性与决策异构性的关系对大数据知识发现与管理决策的影响 架构特征: 鲁棒性(稳定性)和容错性…...
R语言空间数据处理入门教程
我的课程《R语言空间数据处理入门教程》已重新恢复课程售卖,有需要的读者可以学习。 👇点击下方链接(文末“阅读原文”可直达),立即开启你的空间数据之旅: https://www.bilibili.com/cheese/play/ss13775…...
QT+EtherCAT 主站协议库—SOEM主站
SOEM 是 Simple Open EtherCAT Master Library 的缩写,是瑞典 rt-lab 提供 的一个开源 EtherCAT 主站协议库 。 SOEM 库使用 C 语言编写,可以在 windows 以及 Linux 平台上运行,并也可以方便地移植到嵌入式平台上。 SOEM 支持 CoE ࿰…...
Java-反射(Reflection)
一:概述 (1)出现背景 (2)解决方案 (3)使用场景 业务开发用的少,框架使用的多,业务反射被认为是动态语言的关键 (4)与原方法对比 (5…...
第一次经历项目上线
这几天没写csdn,因为忙着项目上线的问题,我这阶段改了非常多的前端bug哈哈哈哈,说几个比较好的bug思想! 这个页面算是我遇到的比较大的bug,因为我一开始的逻辑都写好了,询价就是在点击快递公司弹出弹框的时…...
基于C#的MQTT通信实战:从EMQX搭建到发布订阅全解析
MQTT(Message Queueing Telemetry Transport) 消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点。 它被设计用于低带宽,不稳定或高延迟的…...
DeepSeek超大模型的高效训练策略
算力挑战 训练DeepSeek此类千亿乃至万亿级别参数模型,对算力资源提出了极高要求。以DeepSeek-V3为例,其基础模型参数量为67亿,采用专家混合(MoE)架构后实际激活参数可达几百亿。如此规模的模型远超单张GPU显存容量极限,必须借助分布式并行才能加载和训练。具体挑战主要包…...
【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理
转眼做人脸复原(face restoration)算法也一段时间了,根据自己的记忆整理一下自己的一些看法,算作个人记录,当然如果有人愿意分享自己的看法也是极好的。先挂下文章链接,下一篇在写总结。 一、前述 人脸修复(face restoration)任…...
最小二乘法拟合平面(线性回归法、梯度下降、PCA法)
参考笔记: Open3D 最小二乘拟合平面(直接求解法)【2025最新版】_python open3d已知平面方程绘制平面-CSDN博客 目录 1.前言 2.线性回归法 2.1 模型假设 2.2 定义误差函数 2.3 求偏导并解方程 2.4 解方程 2.5 案例演示 2.5.1 手工计…...
数组名既可作为指针也可作为变量名
在C语言中,数组名在不同的上下文中既可以作为指向数组首个元素的指针,也可以代表整个数组,这是由C语言的设计和语法规则决定的,下面我来详细解释一下。 1. 数组名作为指向首元素的指针 在大多数情况下,当数组名出现在…...
MySQL相关
1.多表查询关键点在哪 📖 1️⃣ 明确关联关系 先搞清楚多表之间的关联关系: 一对一(1:1) 一对多(1:N) 多对多(M:N) 比如: 一个课程对应一个教室(1:1&am…...
Axure制作可视化大屏动态滚动列表教程
在可视化大屏设计中,动态滚动列表是一种常见且实用的展示方式,能够有效地展示大量信息。本文将详细介绍如何使用Axure制作一个动态滚动的列表展示模块。 一、准备工作 打开Axure软件:确保你已经安装并打开了Axure RP软件。创建新项目&#x…...
计算机网络(1)——概述
1.计算机网络基本概念 1.1 什么是计算机网络 计算机网络的产生背景 在计算机网络出现之前,计算机之间都是相互独立的,每台计算机只能访问自身存储的数据,无法与其他计算机进行数据交换和资源共享。这种独立的计算机系统存在诸多局限性&#…...
融智学视域下的系统性认知增强框架——基于文理工三类AI助理赋能HI四阶跃迁路径
融智学视域下的系统性认知增强框架 ——基于文理工三类AI助理赋能HI四阶跃迁路径 一、如何排除50个认知偏差:消除50类偏差的精准矫正系统 1. 技术架构 文科AI: 构建文化语义场(Cultural Semantic Field, CSF),通过…...
C++ - 仿 RabbitMQ 实现消息队列(2)(Protobuf 和 Muduo 初识)
C - 仿 RabbitMQ 实现消息队列(2)(Protobuf 和 Muduo 初识) Protobuf1. 序列化/反序列化方法(最核心)_InternalSerialize()_InternalParse() 2. 内存管理方法SharedCtor()/SharedDtor()InternalSwap() 3. 字…...
FTP与NFS服务实战:从配置到应用
一、FTP服务进阶:客户端工具与访问控制 1. FTP客户端工具对比 在Linux中,ftp和lftp是常用的FTP客户端工具,功能各有侧重: 工具特点适用场景ftp基础命令交互,需手动输入用户名/密码简单文件传输lftp支持多协议、批量…...