资讯详情

JSP+MySQL+B/S结构动漫视频网站搭建:从数据库设计到权限管理

📅 2026/9/17 19:49:57 | 华诺云谱 👁 阅读
JSP+MySQL+B/S结构动漫视频网站搭建:从数据库设计到权限管理
简介面向具备一定Java和Web开发基础、希望掌握完整Web项目开发流程的开发者和系统设计人员这套基于JSP、MySQL、MyEclipse与Tomcat的动漫网站设计与开发资料提供了一份结构完整的毕业设计论文。系统采用B/S结构围绕动漫类别管理、动漫信息管理、动漫上传下载、会员信息管理和动漫资讯管理等核心模块展开内容涵盖了需求分析、总体设计、数据库与界面设计、关键代码实现以及系统测试等环节能够清晰展示一个动漫信息视频网站从需求梳理到运行验证的全过程也便于用于个人学习、课程设计或企业个性化动漫信息网站开发参考。资源包共1个文件为816KB的docx文档论文包含摘要、目录、章节说明、功能模块解析和测试结论可直接按章节阅读并复用。目前已有71人学习适合需要参考JSPMySQL项目完整流程、快速理解Tomcat环境下B/S结构Web开发要点的读者。1. 为什么选 JSP B/S 结构来搭动漫信息视频网2020 年前后的 Web 项目里最容易被毕业设计和外包接单盯上的就是JSP MySQL 做内容站这类需求。这个动漫信息视频网就是标准模板前台用 JSP 拼 HTML后台用 Servlet 处理请求数据库放 MySQL 5.x容器用 Tomcat整体是 B/S 结构。很多人会嫌 JSP 老但把它拆完你会发现Servlet 生命周期、Session 鉴权、JDBC 访问、SQL 表设计这一条线被完整串了起来拿去应付 Java 基础面试或系统开发课设都够用。对需要快速交付一个可运行动漫信息站的场景它比前后端分离更省事也更容易让接手的人看懂权限边界。2. 数据库设计与权限模型动漫分类、会员、资讯如何落表这类网站的核心难点不在页面而在谁能干什么、数据怎么关联。管理员和会员两套账号决定了后台和前台必须分开做权限校验。需求里提到的动漫类别管理、动漫信息管理、动漫上传下载、会员信息管理、动漫资讯管理最终都要映射成表结构。只有先把表定下来JSP 页面上的增删改查才不会返工。2.1 用例到表结构的映射普通用户能浏览首页、查动漫、看资讯、注册会员、在线观看管理员能写分类、传视频、发资讯、删会员。把这两个用例展开最小表集合是五张管理员表、会员表、动漫分类表、动漫信息表、动漫资讯表。动漫信息表里需要视频路径字段分类表和动漫信息表是一对多关系会员表与信息表只保留创建者 id不直接做外键级联避免误删账号把内容一起带掉。表名对应模块权限边界t_admin后台登录、会话保持仅管理员角色可访问 /admin 下资源t_member前台会员注册、登录会员只能操作自己的信息t_category动漫类别管理管理员写前台只读t_anime动漫信息、上传下载管理员写会员只读和播放t_news动漫资讯管理管理员写前台只读这样划分之后后台管理页面只负责写 t_anime 和 t_news前台页面不出现任何 delete/update 链接能省掉一半越权测试。2.2 五张核心表的建表 SQL2.2.1 管理员表与密码处理CREATE TABLE t_admin ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(64) NOT NULL COMMENT 存 MD5必要时加盐, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8;登录时先按 username 查询再比对 password。password 字段用 64 位是因为 MD5 长度为 32SHA-256 为 64想升级成加盐 SHA-256 也不用改表结构。create_time 用 DATETIME 而不是 TIMESTAMP避免 2038 年问题虽然动漫站短期用不到但表结构定下来后再改字段成本高尽量留足。2.2.2 会员表与状态位CREATE TABLE t_member ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, nickname VARCHAR(50), gender TINYINT DEFAULT 1 COMMENT 1男 2女, email VARCHAR(100), phone VARCHAR(20), status TINYINT DEFAULT 1 COMMENT 1正常 0锁定, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8;status 字段用来做封号或防恶意注册。管理员删除会员时如果不希望保留历史记录可以物理 DELETE如果想保留上传内容和操作日志就 UPDATE status0 做软删除。下面的管理员实现以物理删除加关联检查为例软删除只需要把 DELETE 换成状态更新。2.2.3 分类表和动漫信息表一对多与外键策略CREATE TABLE t_category ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL UNIQUE, sort_order INT DEFAULT 0 COMMENT 控制前台显示顺序, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8; CREATE TABLE t_anime ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, category_id INT NOT NULL, video_url VARCHAR(255) COMMENT 上传后的视频访问路径, cover_url VARCHAR(255) COMMENT 封面图, intro TEXT, upload_user VARCHAR(50), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_category (category_id), CONSTRAINT fk_anime_category FOREIGN KEY (category_id) REFERENCES t_category(id) ON DELETE RESTRICT ) ENGINEInnoDB DEFAULT CHARSETutf8;外键用 ON DELETE RESTRICT意思是只要某个分类下还有动漫记录就不允许直接删除分类。管理员端删除分类时会先 count 该分类下的动漫数量数量大于 0 就提示该分类下还有动漫不能删。如果是 MyISAM 引擎外键约束不生效所以表引擎必须选 InnoDB。2.2.4 资讯表CREATE TABLE t_news ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200) NOT NULL, content TEXT, author VARCHAR(50), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8;资讯表没有外键因为资讯的编辑可能是管理员手动发布的不一定和会员表强关联。作者字段直接存字符串比存 user_id 更适合内容发布场景避免会员注销后作者变成 NULL。2.3 字符集与字段类型选型的三个注意点MySQL 5.x 默认字符集经常是 latin1建库时没指定 charset 的话中文插入后就是问号。这个项目里所有表的 DEFAULT CHARSET 都写成 utf8如果你是 5.5.3 以上版本且需要存 emoji 表情建议统一用 utf8mb4字段长度基本不用重算。视频路径和封面路径用 VARCHAR(255)不需要整条 BLOB剧情简介或资讯正文这种长文本用 TEXT避免单行数据过大。排序字段 sort_order 用 INT 默认 0前台 order by sort_order asc, id desc就能把推荐分类顶到前面。这三条看着零散实际是系统测试阶段最容易返工的地方字符集错了页面乱码路径字段太短导致上传文件后 URL 被截断外键没加导致删分类时产生孤儿数据。下面这句数据库连接串是这类项目最常用的模板jdbc:mysql://localhost:3306/anime_db?useUnicodetruecharacterEncodingUTF-8useSSLfalseuseUnicodetrue 和 characterEncodingUTF-8 要成对出现只写其中一个Tomcat 下的 MySQL 驱动可能仍按系统默认编码读取。useSSLfalse 是为跳过本地开发时的 SSL 握手告警部署到公网时再按需调整证书配置。3. 管理员端实现分类管理、动漫上传、会员删除的 JSP 落地后台的第一道门槛不是页面而是会话。JSP 项目常见做法是用 HttpSession 保存登录标志再抽一个过滤器统一校验。如果不做拦截任何知道后台 URL 的人都能直接访问 JSP 文件。下面按登录、分类、上传、删除四个模块拆实现每个模块都能直接对应到后台菜单。3.1 登录校验与 Session 跳转3.1.1 登录 Servlet 核心代码protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); AdminDAO dao new AdminDAO(); Admin admin dao.findByUsernameAndPassword(username, password); if (admin ! null) { HttpSession session request.getSession(); session.setAttribute(admin, admin); response.sendRedirect(request.getContextPath() /admin/index.jsp); } else { request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(/admin/login.jsp).forward(request, response); } }这段代码做三件事先设置请求编码避免中文用户名乱码再通过 AdminDAO 查询数据库最后根据结果决定重定向还是转发到登录页。成功用 sendRedirect失败用 forward刷新登录页不会重复提交表单。密码比对应放进 SQL 的 WHERE 里不要先查出列表再到 Java 里循环比对。3.1.2 用 Filter 拦截未登录请求public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpSession session request.getSession(false); if (session ! null session.getAttribute(admin) ! null) { chain.doFilter(req, resp); } else { ((HttpServletResponse) resp).sendRedirect(request.getContextPath() /admin/login.jsp); } }过滤器只对/admin/*路径生效配置时在 web.xml 里写url-pattern/admin/*/url-pattern。注意 getSession(false) 不会主动创建 session没有登录过的请求直接拿 null避免给每个爬虫请求都种一个 session 对象。3.2 分类管理列表渲染与删除保护后台分类页最常见的是 JSP 里嵌 Java 脚本片段简单直接。列表页用一个 DAO 方法 findAll 返回 List 然后在页面里循环select namecategoryId % ListCategory list categoryDAO.findAll(); for (Category c : list) { % option value%c.getId()%%c.getName()%/option % } % /select这个下拉框在新增动漫页也会用到所以不要写在某个页面的硬编码里而是抽成公用 fragment。删除分类时先执行SELECT COUNT(*) FROM t_anime WHERE category_id ?返回 0 才允许 DELETE否则提示该分类下还有动漫记录。后台常见请求映射如下操作路径请求 URL方法说明分类列表/admin/category/list.jspGET按 sort_order 排序新增分类/admin/category/add.jspPOST名称唯一校验删除分类/admin/category/delete.jsp?idGET/POST先 count 再删动漫列表/admin/anime/list.jspGET分页加载动漫上传/admin/anime/add.jspPOST multipart文件落盘路径入库会员管理/admin/member/list.jspGET支持按用户名搜索3.3 动漫上传文件落盘、路径入库JSP 项目处理上传Tomcat 8 以后可以用 Servlet 3.0 的 Part 接口但接手的旧项目里 commons-fileupload 出现频率更高。这段用 commons-fileupload 写一个最小实现DiskFileItemFactory factory new DiskFileItemFactory(); ServletFileUpload upload new ServletFileUpload(factory); upload.setFileSizeMax(1024 * 1024 * 200); // 单个视频 200MB ListFileItem items upload.parseRequest(request); for (FileItem item : items) { if (!item.isFormField()) { String fileName System.currentTimeMillis() _ item.getName(); String dir getServletContext().getRealPath(/upload/video); File saved new File(dir, fileName); item.write(saved); anime.setVideoUrl(upload/video/ fileName); } else { // 处理 title/categoryId 等普通字段 } }setFileSizeMax 控制单文件大小超出会抛 FileUploadBase.FileSizeLimitExceededException页面要捕获并提示视频超过 200MB。文件名加上 System.currentTimeMillis() 前缀防止两个用户上传同名文件互相覆盖。getRealPath 返回 webapp 下的物理路径部署到 Linux 后要注意 /upload 目录的写权限否则 item.write 会抛 FileNotFoundException。视频文件不建议直接存数据库BLOB 会让备份和查询都很慢。3.4 会员删除先查关联再删会员删除模块的需求是管理员可以删会员但不能让动漫表里 upload_user 变成悬空值。常见做法是物理删除前先检查String sql SELECT COUNT(*) FROM t_anime WHERE upload_user ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, username); ResultSet rs ps.executeQuery(); if (rs.next() rs.getInt(1) 0) { // 提示该会员名下还有动漫请先转移或删除对应内容 } else { String deleteSql DELETE FROM t_member WHERE id ?; // 执行删除 }这里的 count 查询和 delete 需要放在同一个事务里避免两个请求中间插入新数据。如果会员系统有收藏或评论功能还要额外检查关联表这套项目里最小的表集合只涉及动漫上传记录所以只查 t_anime 就够了。删除成功后如果前台 session 中还有该 member 对象要在对应控制器里 invalidate防止页面继续带着旧身份操作。4. 普通用户端与视频播放查询、注册、在线观看的实现细节前台页面的坑比后台更隐蔽首页列表要用 LEFT JOIN 带出分类名搜索框不能直接拼 SQL分页要算总条数在线播放要防止路径暴露。下面按首页、查询、注册、播放四个场景拆实现。4.1 首页列表一次 LEFT JOIN 查全动漫首页通常展示推荐分类 最新动漫如果先查分类再在 JSP 里循环查动漫会积累出 N1 次数据库请求。改成一次关联查询SELECT a.id, a.title, a.video_url, a.cover_url, a.create_time, c.name AS category_name FROM t_anime a LEFT JOIN t_category c ON a.category_id c.id ORDER BY a.create_time DESC LIMIT 8;LEFT JOIN 保证即使某条数据的 category_id 被删除动漫列表页也能显示标题只是分类名为 NULL。LIMIT 8 用来控制首页数据量避免一次性渲染几百条记录。对应 JSP 页面用 while(rs.next()) 输出卡片分类名为空时显示未分类。4.2 动漫查询参数化 LIKE 与分页4.2.1 模糊查询的写法查询页必须有搜索框常见需求是按动漫名模糊匹配。错误示范是字符串拼接WHERE title LIKE % keyword %会造成 SQL 注入。正确做法是用 PreparedStatementString sql SELECT id, title, cover_url, create_time FROM t_anime WHERE title LIKE ? ORDER BY create_time DESC LIMIT ?, ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, % keyword %); ps.setInt(2, (pageNo - 1) * pageSize); ps.setInt(3, pageSize);LIKE 后面的通配符放在参数里而不是拼进 SQL参数化后即使 keyword 里有单引号也不会破坏语句结构。MySQL 的 LIMIT 从 0 开始所以第 pageNo 页的起始行是 (pageNo-1)*pageSize。4.2.2 分页参数计算分页条需要总条数、总页数、当前页、上一页/下一页四个值。总条数用SELECT COUNT(*) FROM t_anime WHERE title LIKE ?总页数等于(totalCount pageSize - 1) / pageSize页面上把当前页参数用 hidden input 提交避免搜索关键词丢失。分页参数在 JSP 里的常用命名参数名类型说明pageNoint当前页码从 1 开始pageSizeint每页条数建议 12/20totalCountint总条数COUNT 查询得到totalPageint总页数向上取整keywordString搜索关键词回显到输入框4.3 会员注册前端正则与后端防重4.3.1 JavaScript 校验注册页面对用户名、邮箱做即时校验减少无效请求到后台。一个常见规则是用户名只能由字母、数字和下划线组成长度为 4-20 位function checkUsername() { var username document.getElementById(username).value; var reg /^[a-zA-Z0-9_]{4,20}$/; if (!reg.test(username)) { document.getElementById(usernameError).innerText 用户名需4-20位字母数字或下划线; return false; } return true; }正则里的 {4,20} 表示长度限制前端校验只是体验优化后端 DAO 必须再查一次 username 是否重复。不要依赖前端正则做安全边界抓包工具可以直接绕过浏览器。4.3.2 后端唯一性检查public boolean isUsernameExists(String username) { String sql SELECT id FROM t_member WHERE username ?; try (PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); try (ResultSet rs ps.executeQuery()) { return rs.next(); } } catch (SQLException e) { log.error(check username error, e); return true; // 查不到时宁可提示已存在也不放行空库错误 } }注意 try-with-resources 写法JSP 项目里最常见的内存泄漏就是 Connection/Statement/ResultSet 没有在 finally 里关闭。如果用的是 JDBC 直连建议至少把连接获取封装成工具类避免每个 DAO 重新写一遍 DriverManager.getConnection。4.4 在线播放HTML5 video 与路径映射动漫视频在线播放不一定要引入 Flash 插件HTML5 的video标签在 Chrome/Edge 下可以直接播 mp4。上传目录要放在 webapp 下video_url 存相对路径页面这样输出video src${pageContext.request.contextPath}/${anime.videoUrl} controls preloadmetadata width720/videocontrols 显示播放控件preloadmetadata 让页面只加载视频头部信息不预先下载整个文件首页列表加载多个视频卡片时不会卡顿。加${pageContext.request.contextPath}是为了项目以子路径部署时浏览器能正确拼出视频地址。如果视频是 flv 或 rmvb 格式HTML5 原生播不了需要转码成 mp4 或用播放器插件这是这类项目上线前最常见的技术选型分叉点想要省事就要求后台只传 mp4想要格式全就得接 ffmpeg 转码服务。对于毕设和企业内部信息站直接限制 mp4 是最稳妥的方案。5. 乱码、连接池与部署JSP 动漫站上线的三个检查点项目本地能跑不代表部署到另一台机器能跑换机器后集中爆发的问题通常是中文乱码、数据库连接用完、驱动缺失。按下面三个检查点过一遍能省掉大半部署时间。5.1 中文乱码的四层处理位置配置说明JSP 页面% page contentTypetext/html;charsetUTF-8 %页面响应编码请求参数request.setCharacterEncoding(UTF-8)POST 请求在取参数前设置JDBC URLuseUnicodetruecharacterEncodingUTF-8数据库读写编码Tomcat GET 请求URIEncodingUTF-8server.xml 中 Connector 属性代码里通常会在 Filter 中统一设置请求和响应编码比在每个 Servlet 里重复写要干净request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8);如果只配了这层而数据库连接串没配 characterEncodingMySQL 5 仍可能按 latin1 写入页面显示???。检查时先看数据库字段的 COLLATION再看 JDBC 连接串最后看 JSP 头部按顺序排查。5.2 把 JDBC 直连换成 Tomcat 连接池直接在 DAO 里DriverManager.getConnection的问题是没有连接复用动漫首页一次访问要查分类和最新动漫并发一上来很快会报Too many connections。用 Tomcat 自带连接池可以在 context.xml 里配置Resource namejdbc/animeDB authContainer typejavax.sql.DataSource maxTotal20 maxIdle8 maxWaitMillis10000 usernameroot password123456 driverClassNamecom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/anime_db?useUnicodetrueamp;characterEncodingUTF-8amp;useSSLfalse/代码里通过 JNDI 拿到 DataSourceContext ctx new InitialContext(); DataSource ds (DataSource) ctx.lookup(java:comp/env/jdbc/animeDB); Connection conn ds.getConnection();maxTotal20 表示最大连接数maxWaitMillis10000 是等待超时时间连接池满且超时后抛出异常。url 里在 XML 中必须写成amp;写成单会导致 Tomcat 解析 context.xml 失败。这个改动能把页面响应时间明显降下来是系统测试时最容易看到效果的优化。5.3 部署自检清单检查项操作期望结果Java 环境变量java -version输出 1.7 或 1.8MySQL 字符集show variables like character_set_serverutf8 或 utf8mb4驱动包mysql-connector-java-x.x.x.jar放在 WEB-INF/lib启动无 ClassNotFoundException视频上传目录${catalina.base}/webapps/项目名/upload有写权限后台 Session不登录访问 /admin/list.jsp被 Filter 重定向到登录页按表格顺序检查完后启动 Tomcat观察 catalina.out 日志看到INFO: Server startup后先访问 /admin/login 验证拦截再访问首页验证中文分类名是否正常显示。如果搜索页带关键词后分页点击失效检查分页链接是否携带 keyword 参数并把 hidden input 放在form内部提交。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。