Skip to content

Chizukuo/p-card-platform

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

偶像大师粉丝名片交互平台(Java Web 作业)

Java Build Servlet JSP Database Packaging Container License: CC BY-NC-ND 4.0

本项目是一个面向偶像大师(THE IDOLM@STER)社群的电子粉丝名片互动平台,聚焦“名片展示、分享与评论”三大核心能力。实现采用标准 Java Servlet + JSP 技术栈,配合 HikariCP 连接池、Logback 日志与多层架构(Controller/Filter/DAO/Model),强调安全、可扩展与清晰的数据流。

说明:本文档仅介绍实现与设计,不包含任何部署或运行步骤。


功能概览

  • 用户体系
    • 注册(昵称/用户名/密码,需勾选隐私政策)
    • 登录/退出(BCrypt 密码校验,支持登录后安全重定向)
    • 密码修改(旧密码验证 + 新密码哈希存储)
  • 名片管理
    • 仪表盘管理多张名片(创建/编辑/删除)
    • 名片展示页(唯一链接 uniqueLinkId)、短链 shortCode 跳转
    • 可见性:PUBLIC / LINK_ONLY / PRIVATE
    • 图片上传(大小/类型/魔数校验 + 自动判断横/竖版)
    • 自定义 SNS 列表(以 JSON 持久化)
  • 评论互动
    • 顶级评论与树形回复(显示相对时间,支持删除)
  • 首页浏览
    • 公共名片列表、搜索、分页
    • ?format=1 返回精简 JSON 以便前端动态加载
  • 管理后台
    • 用户/名片双列表分页检索与过滤
    • 用户封禁、删除、角色变更(含“至少保留一名管理员”“超级管理员 admin 规则”等安全约束)
    • 管理名片可见性并自动处理 shareToken/shortCode

技术栈与分层

  • Web:Java Servlet 4.0 + JSP(JSTL)
  • 持久层:JDBC + HikariCP(MySQL)
  • 日志:SLF4J + Logback(src/main/resources/logback.xml
  • JSON:Gson(轻量序列化/反序列化)
  • 密码:BCrypt(org.mindrot:jbcrypt
  • 结构:Controller(Servlet)/ Filter / DAO / Model / JSP View

目录结构(节选):

src/main/java/com/example/pcard/
  controller/  # 业务入口(Servlet)
  filter/      # 横切关注点(鉴权、限流、CF 集成、异常)
  dao/         # 数据访问
  model/       # 领域模型
  util/        # 工具(DB/校验/时区/存储)
src/main/webapp/
  *.jsp, /css, /js, /uploads, /WEB-INF/web.xml
src/main/resources/
  db.properties(可选), logback.xml

路由与页面(实现)

  • 首页与搜索
    • GET /HomeServlet):
      • 查询参数:q(关键词,可空)、limit(默认 12)、offset(默认 0)
      • format=1 时返回 JSON 数组(字段:id, uniqueLinkId, producerName, idolName, region, cardFrontPath)
      • 页面:index.jsp
  • 账户
    • GET /login(登录页:login.jsp);POST /login(校验 + 会话)
      • 支持 redirect 参数(仅允许相对路径,防开放重定向)
    • GET /register(注册页:register.jsp);POST /register
    • GET /logout(销毁会话)
    • POST /userAction?action=changePassword(修改密码)
  • 仪表盘与名片
    • GET /dashboarddashboard.jsp):加载当前用户全部名片,可通过 cardId 精确选中或 create=1 进入创建模式
    • POST /cardAction
      • action=create|update|delete
      • 图片字段:cardFrontcardBack(5MB,扩展名与魔数双校验:png/jpeg/gif/webp)
      • 表单字段:producerNameregionidolNamevisibilitycustomSnsName[]customSnsValue[]
      • 规则:
        • LINK_ONLY 自动补全 shareToken
        • PUBLIC/LINK_ONLY 自动生成 7 位 shortCode(Base62,碰撞最多重试 5 次)
        • 根据图片自动写入 imageOrientation(HORIZONTAL/ VERTICAL)
  • 浏览名片与短链
    • GET /card/{uniqueLinkId}ViewCardServletviewCard.jsp
      • 可见性检查:
        • PUBLIC:所有人可见
        • LINK_ONLY:需匹配 ?token= 或为拥有者/管理员
        • PRIVATE:仅拥有者/管理员
    • GET /s/{shortCode}ShortLinkServlet):302 跳转至 /card/{uniqueLinkId},如存在 shareToken 则追加 ?token=
  • 评论互动
    • POST /commentAction
      • action=add|reply|delete,参数包含 cardIdcardLinkcontent,回复时含 parentIdreplyToUsername/Nickname
      • 删除权限:管理员 | 名片所有者 | 评论作者
  • 管理后台
    • GET /adminadmin.jsp):
      • 用户筛选:userQrole(user/admin/all)、status(active/banned/all)
      • 名片筛选:cardQvisibility(PUBLIC/LINK_ONLY/PRIVATE/all)
      • 分页:uPagecPage(每页固定 10)
    • POST /admin
      • action=updateUserStatus|deleteUser|updateUserRole|setCardVisibility
      • 角色/人员安全约束:
        • 至少保留一名管理员
        • 超级管理员用户名固定为 admin:禁止自降级;普通管理员无权升/降他人

数据模型与数据库

  • users
    • id, username(unique), nickname, password(BCrypt), role(user/admin), status(active/banned)
  • cards
    • id, user_id(FK), producer_name, region, idol_name
    • card_front_path, card_back_path, image_orientation(HORIZONTAL|VERTICAL)
    • unique_link_id(unique), short_code, share_token
    • custom_sns(JSON), visibility(PUBLIC|LINK_ONLY|PRIVATE)
    • created_at, updated_at
  • comments(支持嵌套回复)
    • id, card_id(FK), user_id(FK), username, nickname, content
    • parent_id(自引用 FK), reply_to_username, reply_to_nickname
    • created_at, updated_at

完整建表与种子数据见 database/init.sql(包含默认管理员 admin/admin 的密码哈希,首次登录后应修改)。


环境变量配置

本应用支持以下环境变量进行配置。优先级为:环境变量 > db.properties 配置文件 > 默认值

数据库配置(必需)

环境变量 配置文件键 默认值 说明
DB_URL db.url MySQL 连接字符串,格式:jdbc:mysql://host:port/db?params
DB_USERNAME db.username 数据库用户名
DB_PASSWORD db.password 数据库密码
DB_DRIVER db.driver com.mysql.cj.jdbc.Driver JDBC 驱动类名

数据库连接池配置(可选,性能优化)

环境变量 配置文件键 默认值 说明
DB_POOL_MAX_SIZE db.pool.maximumPoolSize 20 连接池最大连接数
DB_POOL_MIN_IDLE db.pool.minimumIdle 5 连接池最小空闲连接数
DB_POOL_CONN_TIMEOUT db.pool.connectionTimeout 20000 获取连接超时时间(毫秒)
DB_POOL_IDLE_TIMEOUT db.pool.idleTimeout 300000 连接空闲超时时间(毫秒)
DB_POOL_MAX_LIFETIME db.pool.maxLifetime 1200000 连接最大生命周期(毫秒)
DB_POOL_LEAK_DETECTION db.pool.leakDetectionThreshold 60000 连接泄漏检测阈值(毫秒,60秒未归还则告警)
DB_POOL_VALIDATION_TIMEOUT db.pool.validationTimeout 5000 连接验证超时时间(毫秒)

连接池大小建议

  • 开发环境:DB_POOL_MAX_SIZE=10, DB_POOL_MIN_IDLE=2
  • 测试环境:DB_POOL_MAX_SIZE=15, DB_POOL_MIN_IDLE=5
  • 生产环境:DB_POOL_MAX_SIZE=30, DB_POOL_MIN_IDLE=10
  • 公式参考:最大连接数 = CPU核心数 × 2 + 磁盘数

时区配置(可选)

环境变量 配置文件键 默认值 说明
APP_TIMEZONE app.timezone Asia/Shanghai 应用时区,支持格式:Asia/ShanghaiUTCAmerica/New_York

Cloudflare Turnstile 验证配置(可选)

环境变量 默认值 说明
CF_TURNSTILE_SITE_KEY Cloudflare Turnstile 站点密钥(用于前端)
CF_TURNSTILE_SECRET Cloudflare Turnstile 秘钥(用于服务端验证)
CF_TURNSTILE_COOLDOWN_MS 600000(10分钟) 触发 Turnstile 验证后的冷却时间(毫秒)
CF_TURNSTILE_TRIGGER_DEFAULT 60 默认端点触发 Turnstile 的请求阈值
CF_TURNSTILE_TRIGGER_LOGIN 5 登录端点触发 Turnstile 的请求阈值
CF_TURNSTILE_TRIGGER_REGISTER 3 注册端点触发 Turnstile 的请求阈值
CF_TURNSTILE_TRIGGER_API 40 API 端点触发 Turnstile 的请求阈值

文件上传与存储配置(可选)

基础上传配置

环境变量 默认值 说明
UPLOAD_DIR /uploads 本地文件上传目录(绝对或相对路径)
USE_EXTERNAL_STORAGE false 是否使用外部云存储(true/false
STORAGE_TYPE local 存储类型:localosss3azuregcs
CDN_URL CDN URL 前缀,若配置则使用 CDN 加速访问(示例:https://cdn.example.com/static

阿里云 OSS 配置(当 STORAGE_TYPE=oss 时)

环境变量 说明
OSS_ENDPOINT OSS 服务端点(示例:oss-cn-hangzhou.aliyuncs.com
OSS_ACCESS_KEY_ID 阿里云 Access Key ID
OSS_ACCESS_KEY_SECRET 阿里云 Access Key Secret
OSS_BUCKET_NAME OSS bucket 名称

AWS S3 配置(当 STORAGE_TYPE=s3 时)

环境变量 说明
S3_REGION AWS 区域代码(示例:us-east-1eu-west-1
S3_ACCESS_KEY AWS Access Key ID
S3_SECRET_KEY AWS Secret Access Key
S3_BUCKET_NAME S3 bucket 名称

Google Cloud Storage 配置(当 STORAGE_TYPE=gcs 时)

环境变量 说明
GCS_BUCKET_NAME GCS bucket 名称(必需)
GCS_PROJECT_ID GCS 项目 ID(可选)

Azure Blob Storage 配置(当 STORAGE_TYPE=azure 时)

环境变量 说明
AZURE_STORAGE_CONNECTION_STRING Azure 存储连接字符串
AZURE_CONTAINER_NAME Azure Blob 容器名称

环境变量使用示例

本地开发环境(使用 db.properties)

无需设置环境变量,通过 src/main/resources/db.properties 配置数据库连接

Docker 容器部署

docker run -e DB_URL="jdbc:mysql://mysql:3306/p_card_db?useSSL=false&serverTimezone=Asia/Shanghai" \
           -e DB_USERNAME="root" \
           -e DB_PASSWORD="your_password" \
           -e DB_POOL_MAX_SIZE="20" \
           -e DB_POOL_MIN_IDLE="5" \
           -e APP_TIMEZONE="Asia/Shanghai" \
           -e CF_TURNSTILE_SITE_KEY="your_site_key" \
           -e CF_TURNSTILE_SECRET="your_secret" \
           p-card-platform:latest

Google Cloud Run 部署(使用 GCS)

gcloud run deploy p-card-platform \
  --set-env-vars DB_URL="jdbc:mysql://sql-instance:3306/p_card_db?useSSL=false" \
  --set-env-vars DB_USERNAME="root" \
  --set-env-vars DB_PASSWORD="your_password" \
  --set-env-vars DB_POOL_MAX_SIZE="30" \
  --set-env-vars DB_POOL_MIN_IDLE="10" \
  --set-env-vars USE_EXTERNAL_STORAGE="true" \
  --set-env-vars STORAGE_TYPE="gcs" \
  --set-env-vars GCS_BUCKET_NAME="p-card-uploads" \
  --set-env-vars CF_TURNSTILE_SITE_KEY="your_site_key" \
  --set-env-vars CF_TURNSTILE_SECRET="your_secret"

Kubernetes 部署(使用 secrets)

apiVersion: v1
kind: Secret
metadata:
  name: p-card-secrets
type: Opaque
stringData:
  DB_URL: "jdbc:mysql://mysql.default:3306/p_card_db"
  DB_USERNAME: "root"
  DB_PASSWORD: "your_password"
  CF_TURNSTILE_SECRET: "your_secret"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: p-card-platform
spec:
  template:
    spec:
      containers:
      - name: p-card-platform
        image: p-card-platform:latest
        envFrom:
        - secretRef:
            name: p-card-secrets
        env:
        - name: APP_TIMEZONE
          value: "Asia/Shanghai"
        - name: DB_POOL_MAX_SIZE
          value: "30"
        - name: DB_POOL_MIN_IDLE
          value: "10"
        - name: STORAGE_TYPE
          value: "gcs"
        - name: GCS_BUCKET_NAME
          value: "p-card-uploads"
        resources:
          limits:
            memory: "1Gi"
            cpu: "1000m"
          requests:
            memory: "512Mi"
            cpu: "500m"

性能监控建议:在生产环境建议配置资源限制,并监控连接池使用率、缓存命中率等指标


文件上传与存储

  • 上传校验
    • 大小上限:5MB
    • 扩展名白名单:png/jpg/jpeg/gif/webp
    • 魔数(文件头)二次验证:PNG/JPEG/GIF/WEBP
  • 保存路径
    • 优先使用环境变量 UPLOAD_DIR,否则默认 /uploads
    • 返回路径:
      • 若配置了 GCS_BUCKET_NAMEUSE_EXTERNAL_STORAGE=true,返回公开 URL(https://storage.googleapis.com/{bucket}/uploads/{file}
      • 否则返回站点相对路径 uploads/{file}
  • 额外适配(可选):util/CloudStorageUtil 提供抽象适配 OSS/S3/Azure/GCS/CDN,但当前上传主流程在 CardServlet#saveUploadedFile 中直接落盘并按需拼接外链

过滤器与安全策略

  • CharacterEncodingFilter(web.xml)
    • 统一请求/响应 UTF-8 编码
  • CloudflareFilter(@WebFilter, global)
    • 识别 Cloudflare 头(真实 IP、国家、Ray、Bot 分数)并注入 request 属性
    • 对受保护路径(/login /register /card /comment /admin)在低 Bot 分数时拦截
  • RateLimitFilter(@WebFilter, global)
    • 1 分钟滑动窗口限流(默认 1000;登录 50;注册 30;接口 500)
    • 跳过静态资源;超限返回 HTTP 429 + Retry-After
  • AuthRefreshFilter(web.xml)
    • 每次请求刷新会话中的用户信息(来自 DB)
    • 封禁用户强制登出并重定向登录页
    • 阻止直接访问 admin.jsp
  • ExceptionHandlingFilter(@WebFilter, global)
    • 捕获未处理异常,统一日志并返回 500 错误

安全细节:

  • 密码存储使用 BCrypt(注册、改密、登录校验)
  • 登录重定向仅允许相对路径,防止开放重定向
  • 可见性判定在服务端强校验(ViewCardServlet
  • DAO 全面使用参数化查询,防 SQL 注入
  • 输入清洗与长度限制见 ValidationUtil

配置、连接池与时区

  • 数据库连接与连接池
    • DbUtil 基于 HikariCP,支持从 db.properties 或环境变量读取配置
    • 连接初始化设置 SET time_zone = '+08:00',配合 TimeZoneUtil 统一应用时区(默认 Asia/Shanghai)
    • 性能优化:已启用预编译语句缓存(250个)、批量操作优化、ResultSet元数据缓存等特性
    • 连接泄漏检测:60秒未归还的连接将触发告警日志
  • 缓存系统
    • CacheUtil:内存LRU缓存,默认TTL 5分钟,最大1000条目
    • ChineseConverter:简繁体转换结果缓存,最多500条/类型
  • 日志
    • logback.xml 定义控制台与滚动文件输出,区分普通日志与错误日志
    • 异步日志:采用异步Appender(队列512/256),消除I/O阻塞

前端与页面要点

  • JSP 视图:index.jsplogin.jspregister.jspdashboard.jspadmin.jspviewCard.jsp
  • 组件:WEB-INF/comment-recursive.jsp 用于评论树递归渲染
  • 静态资源:/css/style.css/js/script.js/uploads/*
  • 动态加载:主页支持 ?format=1 JSON 流,便于无限滚动/批量加载

异常与状态码(行为)

  • 403:无权访问(例如非管理员访问后台、名片权限不足)
  • 404:资源不存在(名片/短链)
  • 429:触发应用层限流(RateLimitFilter)
  • 500:未捕获异常(ExceptionHandlingFilter 兜底)

典型交互(实现契约)

  • 列表 JSON(首页)
    • GET /?q={keyword}&limit=12&offset=0&format=1
    • 返回:[{ id, uniqueLinkId, producerName, idolName, region, cardFrontPath }]
  • 短链跳转
    • GET /s/{shortCode} → 302 → /card/{uniqueLinkId}[?token=...]
  • 评论新增
    • POST /commentAction,表单:action=addcardIdcardLinkcontent
  • 修改可见性(后台)
    • POST /admin,表单:action=setCardVisibilitycardIdvisibility

About

基于 Java Servlet 4.0 + JSP 2.3 开发的偶像大师(THE IDOLM@STER)电子粉丝名片互动平台。支持名片创建与多维管理、短链分享、树形评论互动及完善的管理后台,采用 HikariCP、Logback、BCrypt 等技术栈。

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors