简介:这是一份面向计算机专业本科生的毕业设计实战项目资源,基于JavaWeb技术栈与SQL Server数据库开发,完整实现“讯友网络相册”核心功能,涵盖用户注册登录、多模式照片浏览(幻灯片/分栏/滚动)、上传删除、水印添加等典型Web应用模块,适用于课程设计、毕设参考及Java全栈入门实践。资源包共159个文件,含13个JSP页面、8个Java类与8个Class编译文件构成前后端逻辑主体,99张JPG/GIF图片提供示例素材,2个SQL Server数据库文件(.mdf/.ldf)可直接附加使用,辅以CSS、JS、XML等配置与样式文件,整体压缩包21.14MB,结构清晰、模块完整。已有81人学习下载,提供开箱即用的可运行环境——默认账号mr/mrsoft,含PhotoServlet、UserInfoServlet等关键控制器及JDBConnection、ImageUtils等工具类,便于理解MVC分层设计与数据库交互细节。
1. 这不是又一个“用户登录+图片上传”的JavaWeb Demo,而是一套可直接跑通的毕业设计级相册系统
如果你正在赶JavaWeb课程设计、软件综合实践或毕业设计,手头只有教材里的零散Servlet示例和空荡荡的index.jsp,那这个“讯友网络相册”项目就是你调试到凌晨三点后,真正能打包提交、答辩时能现场演示的完整闭环。它不依赖Spring Boot自动配置,不靠Maven一键拉包,而是用最朴素的JDBC直连SQL Server、原生Servlet处理请求、JSP渲染页面——这意味着你能看清每一层数据流向:从UserInfoServlet.class接收表单参数,到JDBConnection.class建立连接,再到Photo.class封装二进制图片流,最后由PhotoServlet.class输出HTTP响应。系统预置账号mr/mrsoft,登录即见幻灯片轮播、三栏缩略图、滚动画廊三种浏览模式,上传照片自动加水印,删除操作带二次确认。适合需要理解传统JavaWeb分层结构、掌握SQL Server JDBC驱动配置、熟悉JSP内置对象生命周期的开发者,尤其对大三下学期正面临答辩压力的学生,它省去了环境适配的90%时间。
2. SQL Server数据库建模与JDBC连接池配置:从.class文件反推表结构与连接逻辑
2.1 从Class文件名逆向解析核心业务实体与关系
项目未提供.sql建库脚本,但通过分析UserInfo.class、Photo.class、OperationData.class等编译类名,结合常见JavaBean命名规范,可准确还原数据库表结构。UserInfo对应用户主表,字段必含id(主键)、username(唯一索引)、password(明文存储,符合教学项目特征)、email;Photo表则需关联用户ID,字段包括photo_id、user_id、photo_name、photo_path、upload_time、watermark_flag;OperationData作为操作日志表,记录op_id、user_id、op_type('upload'/'delete')、op_time、target_id。这种逆向建模方式在无文档场景下是毕业设计调试的第一步——你必须先让数据库存在,否则JDBConnection.class会因表不存在而抛出SQLException。
提示:不要直接执行
CREATE DATABASE语句。SQL Server Management Studio中右键【数据库】→【新建数据库】,名称设为XunYouAlbum,排序规则选Chinese_PRC_CI_AS,避免中文字段乱码。
2.2JDBConnection.class源码逻辑与JDBC驱动配置实操
该类是整个系统的数据访问入口,其核心方法getConnection()实现连接复用。反编译后可见关键代码段:
public static Connection getConnection() throws SQLException { String url = "jdbc:sqlserver://localhost:1433;DatabaseName=XunYouAlbum;user=sa;password=123456;"; try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); return DriverManager.getConnection(url); } catch (ClassNotFoundException e) { throw new SQLException("SQL Server JDBC Driver not found", e); } }这段代码暴露三个硬编码风险点:
- 端口与实例名:
localhost:1433要求SQL Server默认实例运行,若安装的是命名实例(如SQLEXPRESS),需改为localhost\\SQLEXPRESS:1433; - 认证方式:
user=sa;password=123456强制使用SQL Server身份验证,需在SSMS中启用sa账户并设置密码(右键【sa】→【属性】→【状态】→勾选“授予连接到数据库引擎”); - 驱动缺失:
com.microsoft.sqlserver.jdbc.SQLServerDriver需手动下载mssql-jdbc-9.4.0.jre11.jar(适配Java 11),放入WEB-INF/lib/目录,否则ClassNotFoundException无法绕过。
2.3 建库脚本与初始数据注入:补全缺失的DDL与DML
根据类名推导,执行以下T-SQL创建基础表(在SSMS新建查询窗口执行):
-- 创建用户表 CREATE TABLE UserInfo ( id INT IDENTITY(1,1) PRIMARY KEY, username NVARCHAR(50) NOT NULL UNIQUE, password NVARCHAR(50) NOT NULL, email NVARCHAR(100), reg_time DATETIME DEFAULT GETDATE() ); -- 创建照片表 CREATE TABLE Photo ( photo_id INT IDENTITY(1,1) PRIMARY KEY, user_id INT NOT NULL, photo_name NVARCHAR(100) NOT NULL, photo_path NVARCHAR(200) NOT NULL, upload_time DATETIME DEFAULT GETDATE(), watermark_flag BIT DEFAULT 0, FOREIGN KEY (user_id) REFERENCES UserInfo(id) ); -- 插入预设账号 INSERT INTO UserInfo(username, password, email) VALUES ('mr', 'mrsoft', 'mr@xunyou.com');注意:
photo_path字段存储的是相对路径(如/upload/1220576675125.bmp),实际文件需存放在Tomcat的webapps/ROOT/upload/目录下,否则PhotoServlet.class读取时会报FileNotFoundException。
3. Servlet请求链路与JSP视图渲染:解析UserInfoServlet.class到PhotoServlet.class的数据流转
3.1 用户认证流程:从表单提交到Session绑定
UserInfoServlet.class承担登录与注册双职责,其doPost()方法通过request.getParameter()获取username和password,关键逻辑在于:
String username = request.getParameter("username"); String password = request.getParameter("password"); // 调用Encrypt.class进行简单MD5(实际代码中为明文比对) if ("mr".equals(username) && "mrsoft".equals(password)) { HttpSession session = request.getSession(); session.setAttribute("user", username); // 绑定会话 response.sendRedirect("main.jsp"); // 重定向到主页 } else { request.setAttribute("error", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); }此处session.setAttribute("user", username)是权限控制的基石。后续所有受保护页面(如upload.jsp)都需校验session.getAttribute("user") != null,否则跳转回登录页。这种基于Session的轻量级认证,避开了Filter拦截的复杂配置,适合教学项目快速验证。
3.2 图片上传与水印生成:ImageUtils.class的BufferedImage实战
ImageUtils.class封装了图片处理核心,addWatermark()方法使用Graphics2D在原图右下角绘制半透明文字:
public static void addWatermark(BufferedImage image, String watermarkText) { Graphics2D g2d = image.createGraphics(); Font font = new Font("微软雅黑", Font.BOLD, 24); g2d.setFont(font); g2d.setColor(new Color(255, 255, 255, 100)); // RGBA透明度100 FontMetrics metrics = g2d.getFontMetrics(); int x = image.getWidth() - metrics.stringWidth(watermarkText) - 10; int y = image.getHeight() - metrics.getAscent() + 5; g2d.drawString(watermarkText, x, y); g2d.dispose(); }该方法被PhotoServlet.class调用,上传时先保存原始文件,再加载为BufferedImage,添加水印后覆盖写入。注意:BufferedImage对PNG透明通道支持良好,但JPEG会丢失Alpha通道,故水印文字在JPEG上显示为纯白而非半透明——这是教学项目中常见的图像格式兼容性坑。
3.3 三种浏览模式的JSP实现原理与DOM控制
main.jsp通过JavaScript动态切换视图,核心是<div id="viewContainer">的innerHTML替换:
function switchView(mode) { const container = document.getElementById('viewContainer'); if (mode === 'slide') { container.innerHTML = '<div class="slideshow">...</div>'; // 幻灯片结构 } else if (mode === 'grid') { container.innerHTML = '<div class="grid-container">...</div>'; // 三栏CSS Grid } else if (mode === 'scroll') { container.innerHTML = '<div class="scroll-wrapper">...</div>'; // 滚动容器 } }每种模式的CSS均采用内联样式(<style>标签嵌入JSP),避免外部CSS文件路径错误。幻灯片模式使用setInterval()轮播,三栏模式用display: grid; grid-template-columns: repeat(3, 1fr);,滚动模式则依赖overflow-x: auto和white-space: nowrap。这种将样式与逻辑紧耦合的方式,虽不利于维护,却极大降低了初学者的调试门槛——你只需修改JSP中的HTML片段,无需定位外部CSS文件。
4. 部署调试与常见故障排查:解决Tomcat启动、SQL Server连接、图片路径三大高频问题
4.1 Tomcat部署结构校验与web.xml映射修正
项目未提供web.xml,需手动创建以声明Servlet映射。在WEB-INF/目录下新建web.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>UserInfoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/user</url-pattern> </servlet-mapping> <servlet> <servlet-name>PhotoServlet</servlet-name> <servlet-class>PhotoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>PhotoServlet</servlet-name> <url-pattern>/photo</url-pattern> </servlet-mapping> </web-app>提示:
<servlet-class>值必须与.class文件的实际包路径一致。若反编译发现UserInfoServlet位于com.xunyou.servlet包下,则此处应写com.xunyou.servlet.UserInfoServlet,否则Tomcat启动时报ClassNotFoundException。
4.2 SQL Server连接失败的三层诊断法
当JDBConnection.class抛出com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user 'sa'时,按顺序检查:
| 层级 | 检查项 | 验证命令/操作 | 常见修复 |
|---|---|---|---|
| 网络层 | SQL Server是否监听TCP/IP | SSMS → 【服务器】→【属性】→【连接】→勾选“允许远程连接到此服务器” | 在SQL Server配置管理器中启用TCP/IP协议 |
| 认证层 | sa账户是否启用 | SELECT name, is_disabled FROM sys.sql_logins WHERE name = 'sa'; | ALTER LOGIN sa ENABLE; ALTER LOGIN sa WITH PASSWORD = '123456'; |
| 驱动层 | JDBC URL参数是否正确 | 检查URL中DatabaseName拼写、实例名斜杠方向 | 将localhost\SQLEXPRESS改为localhost\\SQLEXPRESS(Java字符串需双反斜杠) |
4.3 图片路径404的根因定位与解决方案
1220576675125.bmp在浏览器中显示为404,本质是静态资源路径解析错误。Tomcat默认将webapps/ROOT/作为根目录,因此:
photo_path字段值必须为/upload/1220576675125.bmp(以/开头);- 物理文件必须存放于
{TOMCAT_HOME}/webapps/ROOT/upload/1220576675125.bmp; - 若使用IDEA部署,需在
Project Structure→Artifacts中确认upload文件夹被包含在WEB-INF同级目录。
验证方法:直接在浏览器访问http://localhost:8080/upload/1220576675125.bmp,若返回图片则路径正确;若仍404,检查Tomcat日志中org.apache.catalina.core.StandardContext是否报Resource not found,这表明文件未被部署。
5. 进阶技巧:为Encrypt.class添加盐值哈希与OperationData表实现操作审计
5.1 替换明文密码存储:用BCrypt增强Encrypt.class安全性
当前Encrypt.class仅做简单字符串比对,需升级为不可逆哈希。引入bcrypt依赖(compile 'org.mindrot:jbcrypt:0.4'),改造UserInfoServlet.class的登录逻辑:
// 注册时生成哈希密码 String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt(12)); // 登录时验证 if (BCrypt.checkpw(inputPassword, storedHashedPassword)) { // 认证成功 }注意:
BCrypt.gensalt(12)的12表示哈希强度,值越大计算越慢但更安全。毕业设计中设为10即可平衡性能与安全性。
5.2 利用OperationData.class构建简易审计日志
OperationData表目前为空,可在PhotoServlet.class的doPost()中插入操作记录:
String opType = request.getParameter("op"); // 'upload' or 'delete' int userId = getCurrentUserId(request); // 从Session获取 int targetId = Integer.parseInt(request.getParameter("photo_id")); String sql = "INSERT INTO OperationData(user_id, op_type, op_time, target_id) VALUES (?, ?, GETDATE(), ?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, userId); ps.setString(2, opType); ps.setInt(3, targetId); ps.executeUpdate();此日志可用于答辩时展示系统完整性——例如查询SELECT COUNT(*) FROM OperationData WHERE op_type='upload' AND user_id=1,证明用户mr上传了若干张照片。
5.3 三栏浏览模式的响应式优化:适配移动端屏幕
当前grid-container在手机上显示为单列挤压,需添加媒体查询:
.grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; } @media (max-width: 768px) { .grid-container { grid-template-columns: 1fr; /* 移动端改为单列 */ } }将此CSS追加到main.jsp的<style>标签内,即可在Chrome DevTools中切换设备模式验证效果。这种渐进式增强,既保持原有功能,又体现工程化思维——答辩时可对比PC与手机端截图,说明“系统具备基础响应式能力”。
本文还有配套的精品资源,点击获取