From 842da158865e87456182beeb3e16d5ad448213b2 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Tue, 23 Sep 2025 15:13:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E9=87=8D=E6=96=B0=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 68 +++ Dockerfile | 8 + api/__init__.py | 7 + api/blog.py | 82 +++ api/session.py | 18 + config/auth.py | 85 +++ config/database.py | 23 + config/logging.py | 65 +++ config/setting.py | 19 + id_generator/__init__.py | 0 id_generator/generator.py | 38 ++ id_generator/idregister.py | 134 +++++ id_generator/options.py | 43 ++ id_generator/snowflake.py | 20 + id_generator/snowflake_m1.py | 147 +++++ main.py | 14 + middleware/blog_visit_middleware.py | 41 ++ middleware/exceptions.py | 54 ++ models/base.py | 57 ++ models/blog.py | 99 ++++ requirements.txt | 1 + schemas/blog.py | 105 ++++ schemas/paginate_query.py | 27 + schemas/pagination.py | 42 ++ schemas/session.py | 6 + service/blog_service.py | 326 +++++++++++ service/session_service.py | 23 + sys.stdout | 816 ++++++++++++++++++++++++++++ test_main.http | 11 + utils/blog_utils.py | 108 ++++ utils/common.py | 13 + 31 files changed, 2500 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 api/__init__.py create mode 100644 api/blog.py create mode 100644 api/session.py create mode 100644 config/auth.py create mode 100644 config/database.py create mode 100644 config/logging.py create mode 100644 config/setting.py create mode 100644 id_generator/__init__.py create mode 100644 id_generator/generator.py create mode 100644 id_generator/idregister.py create mode 100644 id_generator/options.py create mode 100644 id_generator/snowflake.py create mode 100644 id_generator/snowflake_m1.py create mode 100644 main.py create mode 100644 middleware/blog_visit_middleware.py create mode 100644 middleware/exceptions.py create mode 100644 models/base.py create mode 100644 models/blog.py create mode 100644 requirements.txt create mode 100644 schemas/blog.py create mode 100644 schemas/paginate_query.py create mode 100644 schemas/pagination.py create mode 100644 schemas/session.py create mode 100644 service/blog_service.py create mode 100644 service/session_service.py create mode 100644 sys.stdout create mode 100644 test_main.http create mode 100644 utils/blog_utils.py create mode 100644 utils/common.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ddac70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +# Python 字节码文件 +__pycache__/ +*.py[cod] +*$py.class + +# C 扩展 +*.so + +# 分发/打包 +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# 虚拟环境 +venv/ +env/ +ENV/ +.env +.venv + +# 测试 +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Django 相关 +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +media/ + +# PyCharm IDE +.idea/ +*.iml +*.iws +*.ipr + +# VS Code +.vscode/ +*.code-workspace +.history/ + +# 其他 +.DS_Store + +logs/ +packages/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..19295d7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.12-slim +WORKDIR /app +COPY ./packages /app/packages +COPY requirements.txt /app/ +RUN pip install --no-cache-dir --no-index --find-links=/app/packages -r requirements.txt +COPY . /app/ +EXPOSE 8082 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8082"] \ No newline at end of file diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..70bac50 --- /dev/null +++ b/api/__init__.py @@ -0,0 +1,7 @@ +from fastapi import FastAPI +from .blog import router as blog_router +from .session import router as session_router + +def register_routers(app: FastAPI): + app.include_router(blog_router, prefix="") + app.include_router(session_router, prefix="") diff --git a/api/blog.py b/api/blog.py new file mode 100644 index 0000000..12449ff --- /dev/null +++ b/api/blog.py @@ -0,0 +1,82 @@ +from typing import List + +from fastapi import APIRouter, Depends, Query, Request +from sqlalchemy.orm import Session + +from config.auth import verify_token +from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStatsResponse, \ + BlogLatestResponse, BlogCommentCreate, BlogCommentResponse, BlogVisitResponse, BlogCreate, BlogUpdate +from schemas.pagination import PageResult +from config.database import get_db +from service import blog_service + +router = APIRouter( + prefix="/blog", + tags=["博客管理"], + responses={404: {"description": "Not found"}} +) + + +@router.get("/page", summary="分页查询博客", response_model=PageResult[BlogResponse]) +def query_blog_by_page(current_page: int = Query(1, ge=1, alias="currentPage", description="当前页码"), + page_size: int = Query(10, ge=1, le=100, alias="pageSize", description="每页数量"), + db: Session = Depends(get_db)): + return blog_service.query_blog_by_page(db, current_page, page_size) + + +@router.get("/condition", summary="条件查询博客", response_model=List[BlogResponse]) +def query_blog_by_condition(query: BlogQuery = Depends(), + db: Session = Depends(get_db)): + return blog_service.query_blog_by_condition(db, query) + + +@router.get("/content/{blog_id}", summary="查询博客内容", response_model=BlogResponse) +def query_blog_by_id(blog_id: int, db: Session = Depends(get_db)): + return blog_service.query_blog_by_id(db, blog_id) + + +@router.post("", summary="新增博客内容", response_model=bool) +def add_blog(blog: BlogCreate, db: Session = Depends(get_db), _ = Depends(verify_token)): + return blog_service.add_blog(db, blog) + + +@router.put("/{blog_id}", summary="更新博客内容", response_model=bool) +def update_blog(blog_id: int, blog: BlogUpdate, db: Session = Depends(get_db), _ = Depends(verify_token)): + return blog_service.update_blog(db, blog_id, blog) + + +@router.delete("/{blog_id}", summary="删除博客内容", response_model=bool) +def delete_blog(blog_id: int, db: Session = Depends(get_db), _ = Depends(verify_token)): + return blog_service.delete_blog(db, blog_id) + + +@router.get("/category", summary="查询博客分类", response_model=List[BlogCategoryResponse]) +def query_blog_category(db: Session = Depends(get_db)): + return blog_service.query_blog_category(db) + + +@router.get("/stats", summary="查询博客统计信息", response_model=BlogStatsResponse) +def query_blog_stats(db: Session = Depends(get_db)): + return blog_service.query_blog_stats(db) + + +@router.get("/visit", summary="查询博客访问信息", response_model=PageResult[BlogVisitResponse]) +def query_blog_visit(current_page: int = Query(1, ge=1, alias="currentPage", description="当前页码"), + page_size: int = Query(10, ge=1, le=100, alias="pageSize", description="每页数量"), + db: Session = Depends(get_db)): + return blog_service.query_blog_visit(db, current_page, page_size) + + +@router.get("/latest", summary="查询近期博客", response_model=list[BlogLatestResponse]) +def query_blog_latest(db: Session = Depends(get_db)): + return blog_service.query_blog_latest(db) + + +@router.put("/comment", summary="新增博客评论", response_model=bool) +def add_blog_comment(blog_comment: BlogCommentCreate, request: Request, db: Session = Depends(get_db)): + return blog_service.add_blog_comment(db, request, blog_comment) + + +@router.get("/comment/{blog_id}", summary="查询博客评论", response_model=list[BlogCommentResponse]) +def query_blog_comment(blog_id: int, db: Session = Depends(get_db)): + return blog_service.query_blog_comment(db, blog_id) diff --git a/api/session.py b/api/session.py new file mode 100644 index 0000000..1a459ca --- /dev/null +++ b/api/session.py @@ -0,0 +1,18 @@ +from fastapi import APIRouter, Depends +from fastapi.security import OAuth2PasswordRequestForm +from sqlalchemy.orm import Session + +from config.database import get_db +from schemas.session import SessionResponse +from service import session_service + +router = APIRouter( + prefix="/session", + tags=["会话"], + responses={404: {"description": "Not found"}} +) + + +@router.post("", summary="创建会话", response_model=SessionResponse) +def create(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): + return session_service.create(db, form_data.username, form_data.password) diff --git a/config/auth.py b/config/auth.py new file mode 100644 index 0000000..5a761ef --- /dev/null +++ b/config/auth.py @@ -0,0 +1,85 @@ +from contextvars import ContextVar +from datetime import datetime, timedelta +from typing import Optional + +from fastapi import Depends +from fastapi.security import OAuth2PasswordBearer +import jwt +from passlib.context import CryptContext + +from middleware.exceptions import get_credentials_exception + +# 密钥和算法配置 +SECRET_KEY = "sjdi@!#3ksj2780se1283" +ALGORITHM = "HS256" +ACCESS_TOKEN_EXPIRE_MINUTES = 30 + +# 密码哈希上下文 +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + +# OAuth2 方案 +# 设置默认登录接口 +oauth2_scheme = OAuth2PasswordBearer(tokenUrl="session") + +# 请求上下文 +context_sub: ContextVar[str] = ContextVar('sub') + + +# 获取数据库 加密密码 +def get_password_hash(password: str): + return pwd_context.hash(password) + + +# 验证数据库密码 +def verify_password(plain_password: str, hashed_password: str): + return pwd_context.verify(plain_password, hashed_password) + + +# 生成payload +def create_payload(sub: str) -> dict: + return { + "sub": sub + } + + +# 验证payload +def verify_payload(payload: dict) -> bool: + return "sub" in payload + + +# 从payload中获取用户 +def get_payload_sub(payload: dict) -> str: + return payload["sub"] + + +# 创建token +def create_token(payload: dict, expires_delta: Optional[timedelta] = None): + # 复制一份 + payload_copy = payload.copy() + + # 加上有效时间 + if expires_delta: + expire = datetime.now() + expires_delta + else: + expire = datetime.now() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) + payload_copy.update({"exp": expire}) + + # 生成jwt Token + return jwt.encode(payload_copy, SECRET_KEY, algorithm=ALGORITHM) + + +# 验证token +async def verify_token(token: str = Depends(oauth2_scheme)): + try: + # 1. 检验token信息 + payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) + # 2. 校验payload信息 + if not verify_payload(payload): + raise get_credentials_exception() + # 3. 校验数据库中是否存在 payload中的账户信息 + sub = get_payload_sub(payload) + + # 4. 存储账户信息 + context_sub.set(sub) + except jwt.exceptions.InvalidTokenError: + raise get_credentials_exception() diff --git a/config/database.py b/config/database.py new file mode 100644 index 0000000..e600cb2 --- /dev/null +++ b/config/database.py @@ -0,0 +1,23 @@ +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +from config.setting import settings + +DATABASE_URL = f"mysql+pymysql://{settings.DB_USER}:{settings.DB_PASSWORD}@{settings.DB_HOST}:{settings.DB_PORT}/{settings.DB_NAME}" + +engine = create_engine(url=DATABASE_URL) + +# 会话工厂 +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) +# ORM基类 +Base = declarative_base() + + +def get_db(): + # 创建数据库会话实例 + db = SessionLocal() + try: + yield db + finally: + db.close() diff --git a/config/logging.py b/config/logging.py new file mode 100644 index 0000000..4f834d9 --- /dev/null +++ b/config/logging.py @@ -0,0 +1,65 @@ +from loguru import logger +from pathlib import Path + +from config.setting import settings + +# 日志目录 +LOG_DIR = Path(__file__).parent.parent.parent / "logs" +LOG_DIR.mkdir(exist_ok=True) + +# 日志级别 +LOG_LEVEL = settings.LOG_LEVEL.upper() + +# 日志格式 +STDOUT_FORMAT = ( + "{time:YYYY-MM-DD HH:mm:ss.SSS} | " + "{level: <8} | " + "{name}:{function}:{line} - " + "{message}" +) + +FILE_FORMAT = ( + "{time:YYYY-MM-DD HH:mm:ss.SSS} | " + "{level: <8} | " + "{name}:{function}:{line} - {message}" +) + +# 移除默认处理器 +logger.remove() + +# 添加控制台处理器 +logger.add( + sink="sys.stdout", + level=LOG_LEVEL, + format=STDOUT_FORMAT, + colorize=True, + backtrace=True, # 显示完整异常堆栈 + diagnose=True, # 显示详细异常信息 +) + +# 添加文件处理器 - 常规日志 +logger.add( + sink=LOG_DIR / "app.log", + level="INFO", + format=FILE_FORMAT, + rotation="10 MB", # 日志文件大小达到10MB时自动分割 + retention="7 days", # 保留7天的日志 + compression="zip", # 归档时压缩为zip + enqueue=True, # 异步写入 + serialize=False, # 不使用JSON格式 +) + +# 添加文件处理器 - 错误日志 +logger.add( + sink=LOG_DIR / "error.log", + level="ERROR", + format=FILE_FORMAT, + rotation="10 MB", + retention="30 days", + compression="zip", + enqueue=True, + serialize=False, +) + +# 导出配置好的logger +__all__ = ["logger"] \ No newline at end of file diff --git a/config/setting.py b/config/setting.py new file mode 100644 index 0000000..6f53870 --- /dev/null +++ b/config/setting.py @@ -0,0 +1,19 @@ +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + DB_HOST: str + DB_PORT: int + DB_USER: str + DB_PASSWORD: str + DB_NAME: str + + LOG_LEVEL: str + + class Config: + env_file = ".env" # 指定.env文件路径 + case_sensitive = False # 忽略变量名大小写 + + +# 全局配置实例 +settings = Settings() diff --git a/id_generator/__init__.py b/id_generator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/id_generator/generator.py b/id_generator/generator.py new file mode 100644 index 0000000..fc995d7 --- /dev/null +++ b/id_generator/generator.py @@ -0,0 +1,38 @@ +""" +雪花算法生成器IdGenerator +""" + +# !/usr/bin/python +# coding=UTF-8 + + +from . import options +from . import snowflake_m1 + + +class DefaultIdGenerator: + """ + ID生成器 + """ + + def __init__(self): + self.snowflake = None + + def set_id_generator(self, option: options.IdGeneratorOptions): + """ + 设置id生成规则信息 + """ + + if option.base_time < 100000: + raise ValueError("base time error.") + + self.snowflake = snowflake_m1.SnowFlakeM1(option) + + def next_id(self) -> int: + """ + 获取新的UUID + """ + + if self.snowflake is None: + raise ValueError("please set id generator at first.") + return self.snowflake.next_id() diff --git a/id_generator/idregister.py b/id_generator/idregister.py new file mode 100644 index 0000000..787faac --- /dev/null +++ b/id_generator/idregister.py @@ -0,0 +1,134 @@ +""" +worker id generator +""" + +# !/usr/bin/python +# coding=UTF-8 + + +from threading import Thread +import time +import logging +import redis + + +class Register: + """ + redis封装 + - host 代表redis ip + - port 代表redis端口 + - max_worker_id worker_id的最大值, 默认为100 + - password redis的密码, 默认为空 + """ + + def __init__(self, host, port, max_worker_id=100, password=None): + self.redis_impl = redis.StrictRedis(host=host, port=port, db=0, password=password) + self.loop_count = 0 + self.max_loop_count = 10 + self.worker_id_expire_time = 15 + self.max_worker_id = max_worker_id + self.worker_id = -1 + self.is_stop = False + + def get_lock(self, key): + """ + 获取分布式全局锁,并设置过期时间为30秒 + """ + + if self.redis_impl.setnx(key, 1): + self.redis_impl.expire(key, 30) + return True + if self.redis_impl.ttl(key) < 0: + self.redis_impl.expire(key, 30) + return False + + def stop(self): + """ + 退出注册器的线程 + """ + + self.is_stop = True + + def get_worker_id(self): + """ + 获取全局唯一worker_id, 会创建一个线程给worker id续期 + 失败返回-1 + """ + + self.loop_count = 0 + + def extern_life(my_id): + while 1: + time.sleep(self.worker_id_expire_time / 3) + # 是否关闭了 + if self.is_stop: + return + # 更新生命周期 + if self.worker_id != my_id: + break + try: + self.redis_impl.expire( + f"IdGen:WorkerId:Value:{my_id}", + self.worker_id_expire_time) + except Exception as exe: + logging.error(exe) + continue + + self.worker_id = self.__get_next_worker_id() + if self.worker_id > -1: + Thread(target=extern_life, args=[self.worker_id]).start() + return self.worker_id + + def __get_next_worker_id(self): + """ + 获取全局唯一worker id内部实现 + """ + + cur = self.redis_impl.incrby("IdGen:WorkerId:Index", 1) + + def can_reset(): + try: + reset_value = self.redis_impl.incr("IdGen:WorkerId:Value:Edit") + return reset_value != 1 + except Exception as ept: + logging.error(ept) + return False + + def end_reset(): + try: + self.redis_impl.set("IdGen:WorkerId:Value:Edit", 0) + except Exception as ept: + logging.error(ept) + + def is_available(worker_id: int): + try: + rst = self.redis_impl.get(f"IdGen:WorkerId:Value:{worker_id}") + return rst != "Y" + except Exception as ept: + logging.error(ept) + return False + + if cur > self.max_worker_id: + if can_reset(): + self.redis_impl.set("IdGen:WorkerId:Index", -1) + end_reset() + self.loop_count += 1 + + if self.loop_count > self.max_loop_count: + self.loop_count = 0 + return -1 + + time.sleep(0.2 * self.loop_count) + return self.__get_next_worker_id() + time.sleep(0.2) + return self.__get_next_worker_id() + if is_available(cur): + self.redis_impl.setex( + f"IdGen:WorkerId:Value:{cur}", + self.worker_id_expire_time, + "Y" + ) + self.loop_count = 0 + return cur + + return self.__get_next_worker_id() diff --git a/id_generator/options.py b/id_generator/options.py new file mode 100644 index 0000000..8558381 --- /dev/null +++ b/id_generator/options.py @@ -0,0 +1,43 @@ +""" +生成器IdGenerator配置选项 +""" + +# !/usr/bin/python +# coding=UTF-8 + + +class IdGeneratorOptions: + """ + ID生成器配置 + - worker_id 全局唯一id, 区分不同uuid生成器实例 + - worker_id_bit_length 生成的uuid中worker_id占用的位数 + - seq_bit_length 生成的uuid中序列号占用的位数 + """ + + def __init__(self, worker_id=0, worker_id_bit_length=6, seq_bit_length=6): + + # 雪花计算方法,(1-漂移算法|2-传统算法), 默认1。目前只实现了1。 + self.method = 1 + + # 基础时间(ms单位), 不能超过当前系统时间 + self.base_time = 1582136402000 + + # 机器码, 必须由外部设定, 最大值 2^worker_id_bit_length-1 + self.worker_id = worker_id + + # 机器码位长, 默认值6, 取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) + self.worker_id_bit_length = worker_id_bit_length + + # 序列数位长, 默认值6, 取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) + self.seq_bit_length = seq_bit_length + + # 最大序列数(含), 设置范围 [max_seq_number, 2^seq_bit_length-1] + # 默认值0, 表示最大序列数取最大值(2^seq_bit_length-1]) + self.max_seq_number = 0 + + # 最小序列数(含), 默认值5, 取值范围 [5, max_seq_number], 每毫秒的前5个序列数对应编号0-4是保留位 + # 其中1-4是时间回拨相应预留位, 0是手工新值预留位 + self.min_seq_number = 5 + + # 最大漂移次数(含), 默认2000, 推荐范围500-10000(与计算能力有关) + self.top_over_cost_count = 2000 diff --git a/id_generator/snowflake.py b/id_generator/snowflake.py new file mode 100644 index 0000000..ea36cfa --- /dev/null +++ b/id_generator/snowflake.py @@ -0,0 +1,20 @@ + +""" +雪花算法生成器接口声明 +""" + +# !/usr/bin/python +# coding=UTF-8 + + +class SnowFlake(): + + def __init__(self, options): + self.options = options + + def next_id(self) -> int: + """ + 获取新的UUID + """ + + return 0 diff --git a/id_generator/snowflake_m1.py b/id_generator/snowflake_m1.py new file mode 100644 index 0000000..596b76d --- /dev/null +++ b/id_generator/snowflake_m1.py @@ -0,0 +1,147 @@ +""" +M1生成器 +""" + +# !/usr/bin/python +# coding=UTF-8 + +import threading +import time +from .snowflake import SnowFlake +from .options import IdGeneratorOptions + + +class SnowFlakeM1(SnowFlake): + """ + M1规则ID生成器配置 + """ + + def __init__(self, options: IdGeneratorOptions): + # 1.base_time + self.base_time = 1582136402000 + if options.base_time != 0: + self.base_time = int(options.base_time) + + # 2.worker_id_bit_length + self.worker_id_bit_length = 6 + if options.worker_id_bit_length != 0: + self.worker_id_bit_length = int(options.worker_id_bit_length) + + # 3.worker_id + self.worker_id = options.worker_id + + # 4.seq_bit_length + self.seq_bit_length = 6 + if options.seq_bit_length != 0: + self.seq_bit_length = int(options.seq_bit_length) + + # 5.max_seq_number + self.max_seq_number = int(options.max_seq_number) + if options.max_seq_number <= 0: + self.max_seq_number = (1 << self.seq_bit_length) - 1 + + # 6.min_seq_number + self.min_seq_number = int(options.min_seq_number) + + # 7.top_over_cost_count + self.top_over_cost_count = int(options.top_over_cost_count) + + # 8.Others + self.__timestamp_shift = self.worker_id_bit_length + self.seq_bit_length + self.__current_seq_number = self.min_seq_number + self.__last_time_tick: int = 0 + self.__turn_back_time_tick: int = 0 + self.__turn_back_index: int = 0 + self.__is_over_cost = False + self.___over_cost_count_in_one_term: int = 0 + self.__id_lock = threading.Lock() + + def __next_over_cost_id(self) -> int: + current_time_tick = self.__get_current_time_tick() + if current_time_tick > self.__last_time_tick: + self.__last_time_tick = current_time_tick + self.__current_seq_number = self.min_seq_number + self.__is_over_cost = False + self.___over_cost_count_in_one_term = 0 + return self.__calc_id(self.__last_time_tick) + + if self.___over_cost_count_in_one_term >= self.top_over_cost_count: + self.__last_time_tick = self.__get_next_time_tick() + self.__current_seq_number = self.min_seq_number + self.__is_over_cost = False + self.___over_cost_count_in_one_term = 0 + return self.__calc_id(self.__last_time_tick) + + if self.__current_seq_number > self.max_seq_number: + self.__last_time_tick += 1 + self.__current_seq_number = self.min_seq_number + self.__is_over_cost = True + self.___over_cost_count_in_one_term += 1 + return self.__calc_id(self.__last_time_tick) + + return self.__calc_id(self.__last_time_tick) + + def __next_normal_id(self) -> int: + current_time_tick = self.__get_current_time_tick() + if current_time_tick < self.__last_time_tick: + if self.__turn_back_time_tick < 1: + self.__turn_back_time_tick = self.__last_time_tick - 1 + self.__turn_back_index += 1 + # 每毫秒序列数的前5位是预留位, 0用于手工新值, 1-4是时间回拨次序 + # 支持4次回拨次序(避免回拨重叠导致ID重复), 可无限次回拨(次序循环使用)。 + if self.__turn_back_index > 4: + self.__turn_back_index = 1 + + return self.__calc_turn_back_id(self.__turn_back_time_tick) + + # 时间追平时, _TurnBackTimeTick清零 + self.__turn_back_time_tick = min(self.__turn_back_time_tick, 0) + + if current_time_tick > self.__last_time_tick: + self.__last_time_tick = current_time_tick + self.__current_seq_number = self.min_seq_number + return self.__calc_id(self.__last_time_tick) + + if self.__current_seq_number > self.max_seq_number: + self.__last_time_tick += 1 + self.__current_seq_number = self.min_seq_number + self.__is_over_cost = True + self.___over_cost_count_in_one_term = 1 + return self.__calc_id(self.__last_time_tick) + + return self.__calc_id(self.__last_time_tick) + + def __calc_id(self, use_time_tick) -> int: + self.__current_seq_number += 1 + return ( + (use_time_tick << self.__timestamp_shift) + + (self.worker_id << self.seq_bit_length) + + self.__current_seq_number + ) % int(1e64) + + def __calc_turn_back_id(self, use_time_tick) -> int: + self.__turn_back_time_tick -= 1 + return ( + (use_time_tick << self.__timestamp_shift) + + (self.worker_id << self.seq_bit_length) + + self.__turn_back_index + ) % int(1e64) + + def __get_current_time_tick(self) -> int: + return int((time.time_ns() / 1e6) - self.base_time) + + def __get_next_time_tick(self) -> int: + temp_time_ticker = self.__get_current_time_tick() + while temp_time_ticker <= self.__last_time_tick: + # 0.001 = 1 mili sec + time.sleep(0.001) + temp_time_ticker = self.__get_current_time_tick() + return temp_time_ticker + + def next_id(self) -> int: + with self.__id_lock: + if self.__is_over_cost: + nextid = self.__next_over_cost_id() + else: + nextid = self.__next_normal_id() + return nextid diff --git a/main.py b/main.py new file mode 100644 index 0000000..e01f3bb --- /dev/null +++ b/main.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI + +from api import register_routers +from middleware.blog_visit_middleware import blog_visit_middleware +from middleware.exceptions import global_exception_handler + +app = FastAPI(title="Blog Service") + +# 加载中间件 +app.middleware("http")(global_exception_handler) +app.middleware("http")(blog_visit_middleware) + +# 挂载API +register_routers(app) \ No newline at end of file diff --git a/middleware/blog_visit_middleware.py b/middleware/blog_visit_middleware.py new file mode 100644 index 0000000..64a671e --- /dev/null +++ b/middleware/blog_visit_middleware.py @@ -0,0 +1,41 @@ +import re +from fastapi import Request + +from models.blog import BlogVisit +from service import blog_service +from utils.blog_utils import get_user_agent_info, get_client_ip +from config.database import SessionLocal +from middleware.exceptions import AppException + + +async def blog_visit_middleware(request: Request, call_next): + # 检查路径是否匹配 /blog/content/{blog_id} + if match := re.match(r"^/blog/content/(\d+)$", request.url.path): + # 获取客户端信息 + ip = get_client_ip(request) + user_agent = request.headers.get("User-Agent", "") + os, browser = get_user_agent_info(user_agent) + blog_id = int(match.group(1)) + + # 创建访问记录 + blog_visit = BlogVisit( + ip=ip, + os=os, + browser=browser, + uri=request.url.path, + blog_id=blog_id + ) + + db = SessionLocal() + try: + blog_service.add_blog_visit(db, blog_visit) + db.commit() + except Exception as e: + db.rollback() + raise AppException(f"新增博客{blog_id}访问记录失败: {e}") + finally: + db.close() + + # 继续处理请求 + response = await call_next(request) + return response diff --git a/middleware/exceptions.py b/middleware/exceptions.py new file mode 100644 index 0000000..1fdbf50 --- /dev/null +++ b/middleware/exceptions.py @@ -0,0 +1,54 @@ +from fastapi import Request, HTTPException, status +from fastapi.responses import JSONResponse +from sqlalchemy.exc import SQLAlchemyError +from config.logging import logger + + +# 自定义异常类 +class AppException(Exception): + def __init__(self, message: str, details=None): + self.message = message + self.details = details + + +# 全局异常处理中间件 +async def global_exception_handler(request: Request, call_next): + try: + # 记录请求信息(可选) + logger.info(f"请求: {request.method} {request.url}") + if request.query_params: + logger.info(f"查询参数: {dict(request.query_params)}") + + response = await call_next(request) + + # 记录响应信息(可选) + if response.status_code >= 400: + logger.warning(f"响应: {response.status_code}") + + return response + + except AppException as e: + # 记录业务异常 + logger.error(f"业务异常: {e.message} - 详情: {e.details}") + return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, + content={"message": e.message, "details": e.details}) + + except SQLAlchemyError as e: + # 记录数据库异常 + #logger.critical(f"数据库异常: {str(e)}", exc_info=True) + return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content={"message": "数据库操作失败", "details": str(e)}) + + except Exception as e: + # 记录未知异常(带堆栈信息) + #logger.critical(f"未知异常: {str(e)}", exc_info=True) + return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + content={"code": 500, "message": "服务器内部错误", "details": str(e)}) + + +def get_credentials_exception() -> HTTPException: + return HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Could not validate credentials", + headers={"WWW-Authenticate": "Bearer"}, + ) diff --git a/models/base.py b/models/base.py new file mode 100644 index 0000000..c37d6e1 --- /dev/null +++ b/models/base.py @@ -0,0 +1,57 @@ +from sqlalchemy import Column, BigInteger, String, DateTime, event +from sqlalchemy.ext.declarative import declared_attr + +from config.auth import context_sub +from config.database import Base +from datetime import datetime + +from utils.common import camel_to_snake +from id_generator import options, generator + +# https://github.com/yitter/IdGenerator/tree/master/Python +options = options.IdGeneratorOptions(worker_id=23) +idgen = generator.DefaultIdGenerator() +idgen.set_id_generator(options) + + +# 第二层基类:包含ID +class IdBase(Base): + __abstract__ = True + + id = Column(BigInteger, primary_key=True, index=True) + + @declared_attr + def __tablename__(cls): + # 自动把数据库实体类名驼峰转为数据库表名下划线 + return camel_to_snake(cls.__name__) + + +# 自动填充id +@event.listens_for(IdBase, 'before_insert', propagate=True) +def before_insert_listener(mapper, connection, target): + if target.id is None: + target.id = idgen.next_id() + + +# 第二层基类:包含ID和审计字段 +class AuditBase(IdBase): + __abstract__ = True + + create_time = Column(DateTime, nullable=True, default=datetime.now) + create_by = Column(String(255), nullable=True) + update_time = Column(DateTime, nullable=True, default=datetime.now, onupdate=datetime.now) + update_by = Column(String(255), nullable=True) + + +@event.listens_for(AuditBase, 'before_insert', propagate=True) +def before_insert(mapper, connection, target): + value = context_sub.get(None) + if value is not None: + target.create_by = value + + +@event.listens_for(AuditBase, 'before_update', propagate=True) +def before_update(mapper, connection, target): + value = context_sub.get(None) + if value is not None: + target.update_by = value diff --git a/models/blog.py b/models/blog.py new file mode 100644 index 0000000..0d2fcf9 --- /dev/null +++ b/models/blog.py @@ -0,0 +1,99 @@ +from sqlalchemy import ( + BigInteger, + Boolean, + Column, + Integer, + DECIMAL, + SMALLINT, + String, + LargeBinary +) +from sqlalchemy.orm import relationship + +from models.base import AuditBase, IdBase + + +class Blog(AuditBase): + title = Column(String(255), nullable=True, comment="博客标题") + top_value = Column(Integer, nullable=True, comment="置顶值 越大越靠前") + is_great = Column(Boolean, nullable=True, comment="是否是精品 0否1是") + category_id = Column(BigInteger, nullable=True, comment="博客类别") + summary = Column(String(255), nullable=True, comment="博客内容概要") + content_id = Column(BigInteger, nullable=True, comment="博客内容") + word_count = Column(Integer, nullable=True, comment="字数统计") + read_duration = Column(DECIMAL(10, 2), nullable=True, comment="阅读时长") + + category = relationship( + "BlogCategory", + back_populates="blogs", + primaryjoin="foreign(Blog.category_id) == BlogCategory.id" + ) + + content = relationship( + "BlogContent", + back_populates="blog", + primaryjoin="foreign(Blog.content_id) == BlogContent.id" + ) + + visits = relationship( + "BlogVisit", + back_populates="blog", + primaryjoin="Blog.id == foreign(BlogVisit.blog_id)" + ) + + comments = relationship( + "BlogComment", + back_populates="blog", + primaryjoin="Blog.id == foreign(BlogComment.blog_id)" + ) + + +class BlogCategory(AuditBase): + name = Column(String(45), nullable=True, comment="类别名称") + + blogs = relationship( + "Blog", + back_populates="category", + primaryjoin="BlogCategory.id == foreign(Blog.category_id)" + ) + + +class BlogContent(IdBase): + content = Column(LargeBinary, comment="博客内容") + + blog = relationship( + "Blog", + back_populates="content", + primaryjoin="BlogContent.id == foreign(Blog.content_id)" + ) + + +class BlogVisit(AuditBase): + ip = Column(String(255), nullable=True, comment="ip地址") + os = Column(String(255), nullable=True, comment="操作系统") + browser = Column(String(255), nullable=True, comment="浏览器") + uri = Column(String(255), nullable=True, comment="路径") + blog_id = Column(BigInteger, nullable=True, comment="博客id") + + blog = relationship( + "Blog", + back_populates="visits", + primaryjoin="foreign(BlogVisit.blog_id) == Blog.id" + ) + + +class BlogComment(AuditBase): + blog_id = Column(BigInteger, comment="博客id") + parent_id = Column(BigInteger, comment="父评论id") + name = Column(String(255), comment="评论人昵称") + website = Column(String(255), nullable=True, comment="评论人网站") + ip_address = Column(String(45), nullable=True, comment="评论人ip") + user_agent = Column(String(255), nullable=True, comment="评论人浏览器信息") + content = Column(String(512), comment="评论内容") + is_approved = Column(SMALLINT, comment="是否通过") + + blog = relationship( + "Blog", + back_populates="comments", + primaryjoin="foreign(BlogComment.blog_id) == Blog.id" + ) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5fa9cc6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +fastapi~=0.115.12 sqlalchemy~=2.0.41 pydantic~=2.11.4 PyJWT~=2.10.1 passlib~=1.7.4 loguru~=0.7.3 pydantic-settings~=2.9.1 pymysql~=1.1.1 python-multipart~=0.0.20 uvicorn~=0.23.0 # pip download -r requirements.txt -d ./packages --only-binary=:all: --platform manylinux2014_x86_64 -i https://pypi.tuna.tsinghua.edu.cn/simple \ No newline at end of file diff --git a/schemas/blog.py b/schemas/blog.py new file mode 100644 index 0000000..eef6bcd --- /dev/null +++ b/schemas/blog.py @@ -0,0 +1,105 @@ +from typing import Optional + +from pydantic import BaseModel, Field +from datetime import datetime + + +class BlogQuery(BaseModel): + # 类别 + category: Optional[str] = None + # 标题 + title: Optional[str] = None + # 年份 + year: Optional[int] = None + + +class BlogBase(BaseModel): + title: str + topValue: int + isGreat: bool + category: str + content: Optional[str] = None + + +class BlogCreate(BlogBase): + pass + + +class BlogUpdate(BlogBase): + pass + + +class BlogResponse(BlogBase): + id: Optional[int] = None + summary: Optional[str] = None + wordCount: Optional[int] = None + readDuration: Optional[float] = None + visitCount: Optional[int] = None + createTime: Optional[datetime] = None + updateTime: Optional[datetime] = None + + class Config: + from_attributes = True + json_encoders = { + # 自定义 datetime 类型的序列化格式 + datetime: lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S') + } + + +class BlogCategoryResponse(BaseModel): + name: str + count: int + + class Config: + from_attributes = True + + +class BlogStatsResponse(BaseModel): + blogCount: int + categoryCount: int + wordCount: int + + +class BlogVisitResponse(BaseModel): + ip: str + os: str + browser: str + uri: str + title: Optional[str] = None + visitTime: datetime + + class Config: + from_attributes = True + json_encoders = { + datetime: lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S') + } + + +class BlogLatestResponse(BaseModel): + id: int + title: str + + class Config: + from_attributes = True + + +class BlogCommentCreate(BaseModel): + blogId: int + parentId: int + name: str + website: Optional[str] = None + content: str + + +class BlogCommentResponse(BlogCommentCreate): + id: int + ipAddress: str + userAgent: str + createTime: datetime + + class Config: + from_attributes = True + json_encoders = { + # 自定义 datetime 类型的序列化格式 + datetime: lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S') + } diff --git a/schemas/paginate_query.py b/schemas/paginate_query.py new file mode 100644 index 0000000..feadb7b --- /dev/null +++ b/schemas/paginate_query.py @@ -0,0 +1,27 @@ +from sqlalchemy import select, func +from sqlalchemy.orm import Session + +from schemas.pagination import PageResult + + +def paginate_query(db: Session, query, current_page: int = 1, page_size: int = 10) -> PageResult: + """通用分页查询函数""" + # 计算总记录数 + total = db.execute(select(func.count()).select_from(query.subquery())).scalar_one_or_none() or 0 + + # 计算总页数 + total_pages = (total + page_size - 1) // page_size if page_size != 0 else 0 + + # 执行分页查询 + results = db.execute(query.offset((current_page - 1) * page_size).limit(page_size)).all() + + # 转换为字典列表 + records = [row._asdict() if hasattr(row, "_asdict") else dict(row) for row in results] + + return PageResult( + current=current_page, + size=page_size, + total=total, + pages=total_pages, + records=records + ) diff --git a/schemas/pagination.py b/schemas/pagination.py new file mode 100644 index 0000000..5ebda67 --- /dev/null +++ b/schemas/pagination.py @@ -0,0 +1,42 @@ +from typing import List, TypeVar, Generic + +from pydantic import BaseModel, field_validator + + +class PaginationParams(BaseModel): + currentPage: int = 1 # 当前页码,从 1 开始 + pageSize: int = 10 # 每页数据量 + + class Config: + validate_assignment = True + + @field_validator("pageSize") + def limit_page_size(cls, v): + if v > 100: + raise ValueError("pageSize 最大为 100") + return v + + +T = TypeVar("T") + + +class PageResult(BaseModel, Generic[T]): + """通用分页结果模型""" + current: int = 1 # 当前页码(从 1 开始) + size: int = 10 # 每页大小 + total: int = 0 # 总记录数 + pages: int = 0 # 总页数 + records: List[T] = [] # 数据列表 + + @field_validator("size") + def validate_page_size(cls, v): + if v < 1: + raise ValueError("page_size 必须至少为 1") + if v > 1000: + raise ValueError("page_size 最大为 1000") + return v + + @property + def offset(self) -> int: + """计算偏移量""" + return (self.page - 1) * self.size \ No newline at end of file diff --git a/schemas/session.py b/schemas/session.py new file mode 100644 index 0000000..2300d1f --- /dev/null +++ b/schemas/session.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel + + +class SessionResponse(BaseModel): + access_token: str + token_type: str diff --git a/service/blog_service.py b/service/blog_service.py new file mode 100644 index 0000000..14cba26 --- /dev/null +++ b/service/blog_service.py @@ -0,0 +1,326 @@ +from typing import List + +from fastapi import Request +from sqlalchemy import select, func, desc, and_ +from sqlalchemy.orm import Session + +from models.blog import Blog, BlogCategory, BlogVisit, BlogContent, BlogComment +from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStatsResponse, \ + BlogLatestResponse, BlogCommentCreate, BlogCommentResponse, BlogVisitResponse, BlogCreate, BlogUpdate +from schemas.pagination import PageResult +from schemas.paginate_query import paginate_query +from middleware.exceptions import AppException +from utils.blog_utils import get_blog_summary, get_word_count, get_read_duration + + +def query_blog_by_page(db: Session, current_page: int = 1, page_size: int = 10) -> PageResult[BlogResponse]: + query = select( + Blog.id, + Blog.title, + Blog.top_value.label("topValue"), + Blog.is_great.label("isGreat"), + BlogCategory.name.label("category"), + Blog.summary, + Blog.word_count.label("wordCount"), + Blog.read_duration.label("readDuration"), + func.count(BlogVisit.id).label("visitCount"), + Blog.create_time.label("createTime"), + Blog.update_time.label("updateTime") + ).select_from(Blog).outerjoin( + BlogCategory, Blog.category_id == BlogCategory.id + ).outerjoin( + BlogVisit, Blog.id == BlogVisit.blog_id + ).group_by( + Blog.id, BlogCategory.name + ).order_by( + desc(Blog.top_value), desc(Blog.update_time) + ) + + return paginate_query(db, query, current_page, page_size) + + +def query_blog_by_condition(db: Session, blog_query: BlogQuery) -> List[BlogResponse]: + query = select( + Blog.id, + Blog.title, + Blog.top_value.label("topValue"), + Blog.is_great.label("isGreat"), + BlogCategory.name.label("category"), + Blog.summary, + BlogContent.content.label("content"), + Blog.word_count.label("wordCount"), + Blog.read_duration.label("readDuration"), + Blog.create_time.label("createTime"), + Blog.update_time.label("updateTime") + ).select_from(Blog).outerjoin( + BlogCategory, Blog.category_id == BlogCategory.id + ).outerjoin( + BlogContent, Blog.content_id == BlogContent.id + ) + + conditions = [] + + if blog_query.category: + conditions.append(BlogCategory.name == blog_query.category) + + if blog_query.title: + conditions.append(Blog.title.like(f"%{blog_query.title}%")) + + if blog_query.year: + conditions.append(func.extract('year', Blog.create_time) == blog_query.year) + + if conditions: + query = query.where(and_(*conditions)) + + query = query.order_by(desc(Blog.update_time)) + + results = db.execute(query).fetchall() + + return [BlogResponse.from_orm(result) for result in results] + + +def query_blog_by_id(db: Session, blog_id: int) -> BlogResponse: + query = db.query( + Blog.id.label("id"), + Blog.title.label("title"), + Blog.top_value.label("topValue"), + Blog.is_great.label("isGreat"), + BlogCategory.name.label("category"), + Blog.summary.label("summary"), + BlogContent.content.label("content"), + Blog.word_count.label("wordCount"), + Blog.read_duration.label("readDuration"), + func.count(BlogVisit.id).label("visitCount"), + Blog.create_time.label("createTime"), + Blog.update_time.label("updateTime") + ).select_from(Blog).outerjoin( + BlogCategory, Blog.category_id == BlogCategory.id + ).outerjoin( + BlogContent, Blog.content_id == BlogContent.id + ).outerjoin( + BlogVisit, Blog.id == BlogVisit.blog_id + ).filter(Blog.id == blog_id) + + blog = query.first() + if blog[0] is None: + raise AppException("博客不存在") + + return BlogResponse.from_orm(blog) + + +def add_blog(db: Session, blog: BlogCreate) -> bool: + word_count = get_word_count(blog.content) + + db_blog = Blog( + title=blog.title, + top_value=blog.topValue, + is_great=blog.isGreat, + category_id=add_blog_category(db, blog.category), + content_id=add_blog_content(db, blog.content), + summary=get_blog_summary(blog.content), + word_count=word_count, + read_duration=get_read_duration(word_count) + ) + + db.add(db_blog) + db.commit() + db.refresh(db_blog) + + return True + + +def add_blog_category(db: Session, category: str) -> int: + db_blog_category = db.query(BlogCategory).filter(BlogCategory.name == category).first() + if db_blog_category is None: + db_new_blog_category = BlogCategory(name=category) + db.add(db_new_blog_category) + db.commit() + category_id = db_new_blog_category.id + else: + category_id = db_blog_category.id + + return category_id + + +def add_blog_content(db: Session, content: str) -> int: + db_blog_content = BlogContent(content=content.encode('utf-8')) + db.add(db_blog_content) + db.commit() + + return db_blog_content.id + + +def update_blog(db: Session, blog_id: int, blog: BlogUpdate) -> bool: + db_blog = db.query(Blog).filter(Blog.id == blog_id).first() + if not db_blog: + raise AppException("博客不存在") + + update_data = blog.model_dump(exclude_unset=True) + + update_blog_content(db, db_blog.content_id, blog.content) + + db_blog.title = update_data["title"] + db_blog.top_value = update_data["topValue"] + db_blog.is_great = update_data["isGreat"] + db_blog.category_id = update_blog_category(db, blog.category) + + word_count = get_word_count(blog.content) + db_blog.summary = get_blog_summary(blog.content), + db_blog.word_count = word_count + db_blog.read_duration = get_read_duration(word_count) + + db.commit() + db.refresh(db_blog) + + return True + + +def update_blog_category(db: Session, category: str) -> int: + db_blog_category = db.query(BlogCategory).filter(BlogCategory.name == category).first() + + if db_blog_category is None: + return add_blog_category(db, category) + else: + return db_blog_category.id + + +def update_blog_content(db: Session, blog_content_id: int, blog_content: str) -> bool: + db_blog_content = db.query(BlogContent).filter(BlogContent.id == blog_content_id).first() + if not db_blog_content: + raise AppException("博客内容不存在") + + db_blog_content.content = blog_content.encode('utf-8') + + db.commit() + db.refresh(db_blog_content) + + return True + + +def delete_blog(db: Session, blog_id: int) -> bool: + db_blog = db.query(Blog).filter(Blog.id == blog_id).first() + if not db_blog: + raise AppException("博客不存在") + + delete_blog_content(db, db_blog.content_id) + + db.delete(db_blog) + db.commit() + + return True + + +def delete_blog_content(db: Session, blog_content_id: int) -> bool: + db_blog_content = db.query(BlogContent).filter(BlogContent.id == blog_content_id).first() + if not db_blog_content: + raise AppException("博客内容不存在") + + db.delete(db_blog_content) + db.commit() + + return True + + +def query_blog_category(db: Session) -> List[BlogCategoryResponse]: + query = select( + BlogCategory.name, + func.count(Blog.id).label("count") + ).select_from(Blog).outerjoin( + BlogCategory, Blog.category_id == BlogCategory.id + ).group_by( + BlogCategory.name + ) + + results = db.execute(query).fetchall() + + return [BlogCategoryResponse.from_orm(result) for result in results] + + +def query_blog_stats(db: Session) -> BlogStatsResponse: + return BlogStatsResponse( + blogCount=db.query(Blog).count(), + categoryCount=db.query(BlogCategory).count(), + wordCount=db.query(func.sum(Blog.word_count)).scalar() + ) + + +def query_blog_latest(db: Session) -> List[BlogLatestResponse]: + query = select( + Blog.id, + Blog.title + ).select_from(Blog).order_by(desc(Blog.update_time)).limit(5) + + results = db.execute(query).fetchall() + + return [BlogLatestResponse.from_orm(result) for result in results] + + +def add_blog_visit(db: Session, blog_visit: BlogVisit): + db.add(blog_visit) + db.commit() + db.refresh(blog_visit) + + +def query_blog_visit(db: Session, current_page: int = 1, page_size: int = 10) -> PageResult[BlogVisitResponse]: + query = select( + BlogVisit.ip, + BlogVisit.os, + BlogVisit.browser, + BlogVisit.uri, + Blog.title, + BlogVisit.create_time.label("visitTime") + ).select_from(BlogVisit).outerjoin( + Blog, Blog.id == BlogVisit.blog_id + ).order_by(desc(BlogVisit.create_time)) + + return paginate_query(db, query, current_page, page_size) + + +def query_blog_comment(db: Session, blog_id: int) -> List[BlogCommentResponse]: + query = select( + BlogComment.id, + BlogComment.blog_id.label("blogId"), + BlogComment.parent_id.label("parentId"), + BlogComment.name, + BlogComment.website, + BlogComment.ip_address.label("ipAddress"), + BlogComment.user_agent.label("userAgent"), + BlogComment.content, + BlogComment.is_approved.label("isApproved"), + BlogComment.create_time.label("createTime") + ).select_from(BlogComment).where(BlogComment.blog_id == blog_id) + results = db.execute(query).fetchall() + + return [BlogCommentResponse.from_orm(result) for result in results] + + +def add_blog_comment(db: Session, request: Request, blog_comment: BlogCommentCreate) -> bool: + blog = db.query(Blog).filter(Blog.id == blog_comment.blogId).first() + if not blog: + raise AppException("博客不存在") + + if blog_comment.parentId != 0: + parent_comment = db.query(BlogComment).filter( + BlogComment.id == blog_comment.parentId, + BlogComment.blog_id == blog_comment.blogId + ).first() + + if not parent_comment: + raise AppException("父评论不存在") + + db_comment = BlogComment( + blog_id=blog_comment.blogId, + parent_id=blog_comment.parentId, + name=blog_comment.name, + website=blog_comment.website, + content=blog_comment.content, + ip_address=request.client.host, + user_agent=request.headers.get("user-agent"), + is_approved=1 + ) + + db.add(db_comment) + db.commit() + db.refresh(db_comment) + + return True diff --git a/service/session_service.py b/service/session_service.py new file mode 100644 index 0000000..c15fcf2 --- /dev/null +++ b/service/session_service.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session + +from schemas.session import SessionResponse +from config.auth import create_token, create_payload +from middleware.exceptions import AppException + + +def create(db: Session, username: str, password: str) -> SessionResponse: + # 1. 校验账户是否存在 + if username != "admin": + raise AppException(f"该账户{username}不存在") + + # 2. 校验密码是否正确 + if password != "19940822Cxx": + raise AppException("密码错误") + + return SessionResponse( + access_token=create_token(create_payload(username)), + token_type="Bearer" + ) + + + diff --git a/sys.stdout b/sys.stdout new file mode 100644 index 0000000..18fd478 --- /dev/null +++ b/sys.stdout @@ -0,0 +1,816 @@ +2025-09-19 23:43:07.605 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-19 23:43:07.685 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-19 23:43:08.892 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-19 23:43:08.893 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-19 23:43:12.227 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-19 23:43:12.239 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/631305371107398 +2025-09-19 23:43:16.396 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-19 23:43:17.331 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-19 23:43:17.332 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-19 23:43:18.318 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-19 23:43:18.318 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-19 23:43:30.275 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-19 23:43:30.276 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 00:21:47.652 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-20 00:21:47.696 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on '1213@host.docker.internal' ([Errno 11003] getaddrinfo failed)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-20 00:21:48.841 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-20 00:21:48.841 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 00:21:48.843 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on '1213@host.docker.internal' ([Errno 11003] getaddrinfo failed)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-20 00:21:50.319 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-20 00:21:50.321 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-20 00:21:50.321 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 00:21:50.323 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on '1213@host.docker.internal' ([Errno 11003] getaddrinfo failed)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-20 00:21:50.323 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on '1213@host.docker.internal' ([Errno 11003] getaddrinfo failed)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-20 00:22:05.691 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 00:22:06.166 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-20 00:22:06.166 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 00:22:07.181 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 00:22:07.780 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-20 00:22:07.780 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-20 00:22:10.304 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 00:22:12.516 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-20 00:22:12.516 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 00:22:13.631 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-20 00:22:13.632 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-20 00:22:13.632 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 00:22:13.653 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-20 00:22:15.602 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 00:22:16.177 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-20 00:22:16.178 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-20 00:22:16.642 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 00:22:17.057 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-20 00:22:17.057 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-20 22:33:09.756 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:33:09.758 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:33:09.799 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'host.docker.internal' ([Errno 11001] getaddrinfo failed)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-20 22:33:12.603 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:33:12.603 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:33:12.605 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'host.docker.internal' ([Errno 11001] getaddrinfo failed)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-20 22:33:41.162 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:33:41.162 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:33:43.493 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 22:33:44.993 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-20 22:33:44.994 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-20 22:34:30.724 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:34:30.724 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:39:14.755 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:39:14.755 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:39:28.815 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:39:28.816 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:42:06.355 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:42:06.356 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:52:16.313 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:52:16.313 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 22:53:37.160 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 22:53:37.161 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 23:06:35.552 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 23:06:35.552 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 23:06:45.961 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 23:06:45.961 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 23:06:49.856 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 23:06:49.856 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 23:06:51.974 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 23:06:51.974 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-20 23:06:52.964 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-20 23:06:53.026 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-20 23:06:55.882 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 23:07:07.077 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 23:07:18.650 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 23:07:19.919 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?category=%E5%B7%A5%E4%BD%9C +2025-09-20 23:07:19.920 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'category': '工作'} +2025-09-20 23:07:21.930 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/591259203186757 +2025-09-20 23:07:21.963 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-20 23:07:24.205 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-20 23:07:24.206 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-20 23:07:27.337 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/685309473689669 +2025-09-20 23:07:27.349 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-20 23:07:30.487 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-20 23:07:31.135 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?category=%E5%B7%A5%E5%85%B7 +2025-09-20 23:07:31.135 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'category': '工具'} +2025-09-20 23:07:32.841 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=3 +2025-09-20 23:07:32.842 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '3'} +2025-09-21 10:06:18.830 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:06:18.830 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:06:19.337 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:06:19.337 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:09:08.958 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:09:08.959 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:09:08.959 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:09:09.003 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:09:13.084 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:09:13.088 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:09:13.088 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:09:13.116 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:09:17.146 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:09:17.148 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:09:17.148 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:09:17.167 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:10:27.567 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:10:27.568 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:10:27.568 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:10:27.600 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:10:29.691 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:10:29.691 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:10:29.693 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:10:29.716 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:10:33.337 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:10:34.566 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-21 10:10:34.566 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-21 10:10:36.306 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:10:36.306 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:11:07.366 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:11:07.367 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:11:07.367 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:11:07.399 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:11:09.161 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:11:09.161 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:11:09.161 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:11:09.183 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:11:58.374 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:11:58.378 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:12:01.408 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:12:01.409 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:12:01.410 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:12:01.433 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:12:10.773 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:12:10.776 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:12:10.777 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:12:10.798 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:12:11.940 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:12:37.216 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:12:37.220 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:12:37.246 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:12:38.146 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:12:38.146 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:12:39.172 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/undefined +2025-09-21 10:12:39.174 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 422 +2025-09-21 10:13:00.439 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:13:00.441 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:13:00.441 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:13:00.467 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:13:02.124 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:13:02.126 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:13:02.126 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:13:02.147 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:13:04.776 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-21 10:13:04.883 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/631305371107398 +2025-09-21 10:13:13.399 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:13:13.399 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:13:17.976 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:13:39.121 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:13:39.124 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:13:39.147 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:13:39.797 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?category=%E5%B7%A5%E4%BD%9C +2025-09-21 10:13:39.799 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'category': '工作'} +2025-09-21 10:13:41.071 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/591259203186757 +2025-09-21 10:13:41.130 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/591259203186757 +2025-09-21 10:13:42.954 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?year=2025 +2025-09-21 10:13:42.955 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'year': '2025'} +2025-09-21 10:13:44.119 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/694197446615109 +2025-09-21 10:13:44.135 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/694197446615109 +2025-09-21 10:13:47.845 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:13:47.845 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:13:57.030 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:13:57.031 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:13:57.031 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:13:57.068 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:14:09.541 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:14:09.544 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:14:09.544 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:14:09.569 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:14:17.410 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-21 10:14:17.412 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:14:17.413 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:14:17.437 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-21 10:14:19.225 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:14:20.091 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:14:20.091 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-21 10:14:21.729 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:14:23.107 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?category=%E5%B7%A5%E4%BD%9C +2025-09-21 10:14:23.107 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'category': '工作'} +2025-09-21 10:14:24.243 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-21 10:14:25.263 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/condition?category=SpringBoot +2025-09-21 10:14:25.263 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'category': 'SpringBoot'} +2025-09-21 10:14:26.588 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/685968269635653 +2025-09-21 10:14:26.611 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/685968269635653 +2025-09-21 10:14:32.814 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-21 10:14:32.814 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:10:32.528 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:10:32.538 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-22 15:11:20.975 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:11:20.979 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-22 15:12:52.569 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:12:52.572 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-22 15:14:34.715 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:14:34.715 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:14:34.722 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-22 15:14:36.797 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:14:36.802 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-22 15:14:37.098 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:14:37.098 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:14:37.103 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") +(Background on this error at: https://sqlalche.me/e/20/e3q8) +2025-09-22 15:15:18.304 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:15:18.835 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:15:18.836 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:16:30.165 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:16:30.166 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:16:30.291 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:16:30.292 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:16:45.745 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:16:45.745 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:17:55.127 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:17:55.127 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:17:59.863 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:17:59.863 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:01.178 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:01.178 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:09.547 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:09.548 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:10.775 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:10.775 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:11.597 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:18:13.368 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:13.368 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:14.576 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:18:14.606 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:18:21.277 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:18:21.286 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:18:32.435 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:18:32.477 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:18:34.315 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:34.315 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:35.850 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:18:35.861 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:18:36.801 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:36.801 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:37.910 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:18:37.922 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:18:54.032 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:18:54.032 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:18:55.791 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:18:55.823 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:19:07.698 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:19:07.711 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:19:09.027 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:19:09.027 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:19:10.200 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:19:49.933 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:19:49.933 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:19:51.055 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:19:51.055 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:29:07.461 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:29:07.461 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:29:07.462 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:29:09.248 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:29:09.248 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:29:09.249 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:29:11.191 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:29:11.747 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:29:11.747 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:29:11.748 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:29:44.643 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:29:45.150 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:29:45.150 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:29:45.151 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:30:49.103 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:30:49.752 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:30:49.753 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:30:49.754 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:30:54.846 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/ +2025-09-22 15:30:54.847 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:30:54.955 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/favicon.ico +2025-09-22 15:30:54.955 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:31:28.200 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:31:38.462 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:31:50.381 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:32:30.627 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:32:58.230 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:33:01.985 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/.well-known/appspecific/com.chrome.devtools.json +2025-09-22 15:33:01.986 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:33:06.065 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:33:06.087 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/.well-known/appspecific/com.chrome.devtools.json +2025-09-22 15:33:06.088 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:33:30.973 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 15:33:31.004 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/.well-known/appspecific/com.chrome.devtools.json +2025-09-22 15:33:31.005 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:33:31.649 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-22 15:33:40.922 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:33:40.922 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:36:26.310 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:36:26.310 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:39:34.526 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:39:34.526 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:42:07.925 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:42:07.926 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:45:58.186 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:45:58.187 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:46:55.130 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:46:55.131 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:47:55.921 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:47:55.922 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:49:55.638 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:49:55.638 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:50:42.343 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:50:42.343 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:54:01.182 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=10 +2025-09-22 15:54:01.182 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:54:34.738 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:54:35.231 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:54:35.231 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:54:35.232 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:54:45.865 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/visit?currentPage=1&pageSize=15 +2025-09-22 15:54:45.866 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:54:45.866 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-22 15:55:11.021 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 15:55:11.021 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:55:13.232 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 15:55:13.232 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:55:16.814 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=2&pageSize=15 +2025-09-22 15:55:16.814 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '15'} +2025-09-22 15:55:18.058 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=3&pageSize=15 +2025-09-22 15:55:18.058 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '3', 'pageSize': '15'} +2025-09-22 15:55:19.444 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=4&pageSize=15 +2025-09-22 15:55:19.444 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '4', 'pageSize': '15'} +2025-09-22 15:55:21.420 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 15:55:21.420 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:56:21.793 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:56:21.794 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:56:22.607 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 15:56:23.300 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 15:56:23.301 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 15:56:29.178 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:56:29.179 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:56:34.330 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 15:56:34.384 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:56:37.117 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 15:56:37.117 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 15:56:46.624 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 15:56:46.624 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 15:56:48.277 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/591259203186757 +2025-09-22 15:56:48.288 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 15:57:02.098 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 15:57:02.098 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 15:57:05.160 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/591259203186757 +2025-09-22 15:57:05.187 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:01:30.053 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 16:01:30.053 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 16:11:59.331 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/653526425653317 +2025-09-22 16:11:59.344 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:12:16.814 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/653526425653317 +2025-09-22 16:12:16.851 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:12:18.578 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 16:12:18.578 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 16:12:19.373 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 16:12:20.288 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 16:12:20.288 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 16:12:22.093 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 16:12:22.103 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:13:08.148 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 16:13:08.164 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:13:43.129 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 16:13:43.183 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:13:47.295 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:13:47.301 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:15:09.734 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:15:09.762 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:15:33.888 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:15:50.282 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:15:50.311 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:17:18.946 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:17:18.987 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:17:50.938 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:17:50.974 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:18:07.683 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:18:07.709 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:19:03.894 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:19:03.922 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:19:30.947 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:19:30.974 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:25:21.951 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:25:21.983 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:25:24.186 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 16:25:24.186 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 16:25:25.748 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 16:25:25.759 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:25:27.213 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:25:27.218 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:28:50.934 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:28:50.990 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:31:15.089 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:31:15.117 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:31:22.466 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 16:31:22.509 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:31:23.823 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:31:23.827 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:31:51.087 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:31:51.119 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:32:28.998 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:34:34.904 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:34:34.933 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: 'str' object has no attribute '_sa_instance_state' +2025-09-22 16:35:07.569 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:36:08.384 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 16:38:52.539 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 16:38:54.167 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 16:38:54.168 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 16:38:55.866 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 16:38:55.952 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 16:38:57.139 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:41:18.563 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-22 16:41:38.946 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 16:41:39.149 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-22 16:42:24.993 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 16:42:24.996 | CRITICAL | middleware.exceptions:global_exception_handler:38 - 数据库异常: Class 'schemas.blog.BlogCreate' is not mapped +2025-09-22 16:54:29.509 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 16:54:54.299 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 16:55:19.391 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 16:57:29.815 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 18:14:20.522 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/222 +2025-09-22 18:14:20.552 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客不存在 - 详情: None +2025-09-22 18:25:32.758 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/222 +2025-09-22 18:25:32.805 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客不存在 - 详情: None +2025-09-22 18:26:28.913 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:27:21.610 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-22 18:27:21.641 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:27:23.929 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:27:23.929 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:27:27.864 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:27:28.948 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:27:29.722 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:27:29.722 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:28:52.114 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:28:52.114 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:31:41.995 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:31:41.996 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:31:45.766 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:31:45.766 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:31:48.191 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:31:49.043 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:31:49.043 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:31:50.676 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:31:50.676 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:31:55.477 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:31:55.589 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:31:56.525 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:31:56.526 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:31:57.563 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:31:57.578 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:32:01.569 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:32:25.403 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:32:25.421 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:32:27.763 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:32:30.262 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:32:30.274 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:32:31.801 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:32:31.896 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:32:31.896 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:32:31.922 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:32:31.974 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:32:32.015 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:32:32.016 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:32:33.771 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:32:33.771 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:32:35.396 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:32:35.396 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:32:41.918 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:32:41.930 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:32:43.999 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:32:45.747 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:32:45.861 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:32:45.861 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:32:45.872 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:32:45.884 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:32:45.915 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:32:45.916 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:32:48.833 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:32:48.833 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:32:50.031 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:32:50.031 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:32:53.942 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:32:53.966 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:32:54.843 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:33:00.928 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:33:01.118 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:01.118 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:01.129 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:33:01.139 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:33:01.180 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:01.180 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:03.100 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:33:05.118 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:05.119 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:06.433 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:33:06.442 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:33:08.330 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:08.330 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:09.233 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:33:09.244 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:33:09.895 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:33:11.488 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:33:11.597 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:11.597 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:11.609 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:33:11.621 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:33:11.651 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:11.651 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:13.466 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:33:15.203 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:15.204 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:15.764 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:33:43.025 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:33:43.025 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:33:45.937 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:33:45.938 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 405 +2025-09-22 18:34:46.500 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:34:46.511 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:34:47.017 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:34:51.419 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:34:51.500 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:34:51.500 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:34:51.512 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:34:51.522 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:34:51.556 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:34:51.557 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:34:53.242 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:36:53.036 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:36:53.036 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:36:54.031 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 18:36:54.031 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 18:36:57.341 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:36:57.341 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:38:13.963 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:38:17.268 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:38:17.268 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:38:19.535 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:38:19.548 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:38:20.820 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:38:23.110 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:38:23.195 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:38:23.195 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:38:23.206 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:38:23.221 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:38:23.249 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:38:23.250 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:38:24.949 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:41:06.913 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:41:06.914 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:41:09.726 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:41:09.731 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: delete_blog_content() missing 1 required positional argument: 'blog_content_id' +2025-09-22 18:41:39.132 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-22 18:41:39.238 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-22 18:41:54.768 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:41:54.771 | CRITICAL | middleware.exceptions:global_exception_handler:44 - 未知异常: delete_blog_content() missing 1 required positional argument: 'blog_content_id' +2025-09-22 18:42:14.812 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:42:19.880 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:42:19.885 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客内容不存在 - 详情: None +2025-09-22 18:42:50.275 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:42:50.303 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客内容不存在 - 详情: None +2025-09-22 18:43:06.008 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:43:06.051 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客内容不存在 - 详情: None +2025-09-22 18:44:09.227 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:44:09.253 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客内容不存在 - 详情: None +2025-09-22 18:45:23.874 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:45:23.925 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客内容不存在 - 详情: None +2025-09-22 18:45:57.101 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:45:57.113 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:45:58.136 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:45:58.137 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:46:03.406 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722514116330950 +2025-09-22 18:46:03.449 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:46:04.490 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:46:04.490 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:46:20.664 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:46:20.664 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:46:22.438 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:46:22.443 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 博客内容不存在 - 详情: None +2025-09-22 18:46:56.020 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:47:07.468 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:47:41.733 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:50:54.925 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722514116330950 +2025-09-22 18:50:55.028 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:50:55.028 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:50:55.067 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:50:55.083 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:51:10.453 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:51:13.077 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 18:51:13.285 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:51:13.286 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:51:13.301 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:51:13.317 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:51:13.358 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:51:13.359 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:51:15.327 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:51:15.328 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:54:54.576 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:54:54.576 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:54:56.974 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:54:56.974 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:54:59.240 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722542064379334 +2025-09-22 18:54:59.455 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:54:59.455 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:54:59.466 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:54:59.466 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:54:59.494 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:54:59.527 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:55:00.853 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:55:00.853 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:55:02.437 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:02.437 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:07.394 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:55:08.960 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-22 18:55:09.151 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:09.151 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:09.164 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:55:09.176 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:55:09.215 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:09.216 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:12.434 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722543030515142 +2025-09-22 18:55:12.446 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:55:13.732 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:13.732 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:15.059 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722543030515142 +2025-09-22 18:55:15.072 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:55:15.748 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 18:55:21.292 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/722543030515142 +2025-09-22 18:55:21.465 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:21.466 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:21.477 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:55:21.488 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:55:21.524 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:21.524 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:23.208 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/722543030515142 +2025-09-22 18:55:23.219 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-22 18:55:24.389 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:24.390 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:28.920 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: DELETE http://127.0.0.1:8082/blog/722543030515142 +2025-09-22 18:55:29.157 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:29.157 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:55:29.182 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-22 18:55:29.192 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-22 18:55:30.441 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:55:30.441 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:55:31.669 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:55:31.669 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 18:56:17.221 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=2&pageSize=10 +2025-09-22 18:56:17.221 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '2', 'pageSize': '10'} +2025-09-22 18:56:19.131 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 18:56:19.131 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:04:46.072 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:04:46.073 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:05:04.232 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:05:04.232 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:06:27.903 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:06:29.614 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:06:30.762 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:06:30.763 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:06:31.344 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:06:31.873 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:06:31.873 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:06:33.165 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:06:33.165 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:07:01.746 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:07:01.747 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:07:14.066 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:07:14.066 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:07:17.578 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:07:17.578 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:07:20.284 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:07:29.679 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:07:29.679 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:07:43.055 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:07:43.055 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:07:43.499 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:07:59.605 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:07:59.605 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:08:00.326 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:08:01.072 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:08:01.072 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:08:37.540 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:08:37.541 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:08:41.634 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:08:41.634 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:08:42.352 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:08:46.044 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/visit?currentPage=1&pageSize=15 +2025-09-22 19:08:46.044 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '15'} +2025-09-22 19:08:46.882 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/category +2025-09-22 19:08:47.220 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:08:47.220 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:35:46.700 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:35:46.701 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-22 19:36:39.565 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-22 19:36:39.565 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 13:38:24.061 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/ +2025-09-23 13:38:24.072 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-23 13:38:24.176 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/favicon.ico +2025-09-23 13:38:24.176 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 404 +2025-09-23 13:38:28.402 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:38:50.471 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:38:51.104 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:38:55.964 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 13:38:55.964 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 13:38:55.964 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 13:40:23.368 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 13:40:23.369 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 13:40:32.054 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/blog +2025-09-23 13:40:32.056 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 13:46:14.026 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:46:14.554 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:46:19.941 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:46:20.022 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:46:24.491 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:46:24.553 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:49:32.889 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:49:32.991 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:52:53.666 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:52:53.766 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:53:00.113 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/docs +2025-09-23 13:53:00.173 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/openapi.json +2025-09-23 13:57:51.959 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 13:57:51.960 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 13:57:56.317 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 13:57:56.422 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 13:57:57.914 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 13:57:58.014 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 13:57:58.014 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 13:57:58.028 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-23 13:57:58.044 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-23 13:57:58.074 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 13:57:58.074 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 13:58:39.770 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 13:58:39.785 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 13:58:41.260 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 13:58:41.262 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 14:02:37.558 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session?name=estun&password=medical +2025-09-23 14:02:37.558 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'name': 'estun', 'password': 'medical'} +2025-09-23 14:02:37.560 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 422 +2025-09-23 14:03:42.464 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:03:42.466 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 422 +2025-09-23 14:06:05.092 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:06:05.095 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 该账户estun不存在 - 详情: None +2025-09-23 14:07:04.464 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:07:04.467 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 该账户admin不存在 - 详情: None +2025-09-23 14:07:53.591 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:07:53.596 | ERROR  | middleware.exceptions:global_exception_handler:32 - 业务异常: 该账户admin不存在 - 详情: None +2025-09-23 14:08:48.398 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:26:31.145 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:26:56.041 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:26:57.633 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:26:57.633 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:26:59.248 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 14:26:59.333 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 14:27:00.498 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 14:27:00.500 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 14:31:33.983 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:31:35.668 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:31:35.668 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:31:37.840 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 14:31:37.897 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 14:31:39.290 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 14:31:39.291 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 14:37:39.603 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:37:41.438 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:37:41.438 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:37:51.897 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 14:37:51.970 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 14:37:53.706 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 14:37:53.708 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 14:38:31.930 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:38:33.214 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:38:33.214 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:38:34.724 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 14:38:34.779 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 14:38:35.684 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 14:38:35.686 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 14:40:02.522 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 14:40:02.524 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 +2025-09-23 14:40:12.792 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 14:40:12.816 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 14:40:24.342 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: POST http://127.0.0.1:8082/session +2025-09-23 14:40:25.690 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:40:25.691 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:40:26.966 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/content/631305371107398 +2025-09-23 14:40:27.033 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/comment/0 +2025-09-23 14:40:28.104 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/631305371107398 +2025-09-23 14:40:28.201 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:40:28.201 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:40:28.215 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/stats +2025-09-23 14:40:28.230 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/latest +2025-09-23 14:40:28.263 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:40:28.263 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:41:06.532 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:41:06.533 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:41:58.649 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: GET http://127.0.0.1:8082/blog/page?currentPage=1&pageSize=10 +2025-09-23 14:41:58.649 | INFO  | middleware.exceptions:global_exception_handler:20 - 查询参数: {'currentPage': '1', 'pageSize': '10'} +2025-09-23 14:42:06.096 | INFO  | middleware.exceptions:global_exception_handler:18 - 请求: PUT http://127.0.0.1:8082/blog/21312 +2025-09-23 14:42:06.098 | WARNING  | middleware.exceptions:global_exception_handler:26 - 响应: 401 diff --git a/test_main.http b/test_main.http new file mode 100644 index 0000000..a2d81a9 --- /dev/null +++ b/test_main.http @@ -0,0 +1,11 @@ +# Test your FastAPI endpoints + +GET http://127.0.0.1:8000/ +Accept: application/json + +### + +GET http://127.0.0.1:8000/hello/User +Accept: application/json + +### diff --git a/utils/blog_utils.py b/utils/blog_utils.py new file mode 100644 index 0000000..4eeb515 --- /dev/null +++ b/utils/blog_utils.py @@ -0,0 +1,108 @@ +from fastapi import Request + +from models.blog import BlogVisit + +# 博客概要字数 +BLOG_SUMMARY_COUNT = 100 + +# 阅读速度 600 字/分钟 +READ_SPEED = 600.0 + +# 博客非统计字符 +EXCLUDE_CHARS = [' ', '\n', '\t'] + + +def get_word_count(text: str) -> int: + """ + 获取文本字数 + + :param text: 文本 + :return: 字数 + """ + count = 0 + + if not text: # 检查None或空字符串 + return count + + for char in text: + if char not in EXCLUDE_CHARS: + count += 1 + + return count + + +def get_read_duration(word_count: int) -> float: + """ + 获取阅读时长 单位:分钟 + + :param word_count: 文本字数 + :return: 阅读时长 + """ + return word_count / READ_SPEED + + +def get_blog_summary(content: str) -> str: + """ + 获取简要信息 + + :param content: 博客内容 + :return: 简要信息 + """ + if len(content) > BLOG_SUMMARY_COUNT: + return content[:BLOG_SUMMARY_COUNT] + return content + + +def get_client_ip(request): + """从请求中获取客户端IP地址""" + x_forwarded_for = request.headers.get("X-Forwarded-For") + if x_forwarded_for: + return x_forwarded_for.split(',')[0] + return request.client.host + + +def get_user_agent_info(user_agent: str): + """解析User-Agent获取操作系统和浏览器信息""" + # 使用正则表达式进行更精确的解析 + os = "Unknown" + browser = "Unknown" + + # 操作系统检测 + if "Windows NT" in user_agent: + os = "Windows" + elif "Macintosh" in user_agent: + os = "Mac OS" + elif "Linux" in user_agent: + os = "Linux" + elif "Android" in user_agent: + os = "Android" + elif "iPhone" in user_agent or "iPad" in user_agent: + os = "iOS" + + # 浏览器检测 + if "Chrome" in user_agent: + browser = "Chrome" + elif "Firefox" in user_agent: + browser = "Firefox" + elif "Safari" in user_agent and "Chrome" not in user_agent: + browser = "Safari" + elif "Edge" in user_agent: + browser = "Edge" + elif "MSIE" in user_agent or "Trident" in user_agent: + browser = "Internet Explorer" + + return os, browser + + +def get_blog_visit(request: Request, blog_id: int) -> BlogVisit: + ip = get_client_ip(request) + user_agent = request.headers.get("User-Agent", "") + os, browser = get_user_agent_info(user_agent) + + return BlogVisit( + ip=ip, + os=os, + browser=browser, + uri=request.url.path, + blog_id=blog_id + ) diff --git a/utils/common.py b/utils/common.py new file mode 100644 index 0000000..bb599fe --- /dev/null +++ b/utils/common.py @@ -0,0 +1,13 @@ +import re + + +def camel_to_snake(name: str) -> str: + """将驼峰命名转换为蛇形命名(CamelCase → snake_case)""" + name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) + return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower() + + +def snake_to_camel(name: str) -> str: + """将蛇形命名转换为驼峰命名(snake_case → CamelCase)""" + components = name.split('_') + return ''.join(x.title() for x in components)