在数字化时代,个人记忆的保存方式正经历着从物理介质到数字载体的深刻变革。传统的纸质日记面临着易损毁、检索困难、存储空间有限等诸多挑战。为应对这些痛点,采用JSP与Servlet技术栈构建了一套名为“忆迹空间”的在线日记管理系统。该系统基于经典的MVC架构模式,通过分层设计实现了数据操作、业务逻辑与用户界面的有效分离,为用户提供了一个安全、便捷的私人记录空间。
系统采用三层架构设计,Servlet作为控制器层负责接收和响应所有HTTP请求,进行身份验证、参数校验和业务调度。JSP页面构成视图层,专注于数据展示和用户交互。核心业务逻辑和数据操作封装在JavaBean模型层中,通过JDBC与MySQL数据库进行交互。这种架构确保了代码的可维护性和可扩展性,同时保证了系统的高效运行。
数据库设计采用了三张核心表结构,分别管理用户信息、日记内容和日记分类。用户表(user)采用自增主键设计,包含用户名、密码(经MD5加密存储)、性别等基础字段,确保每个用户的唯一性。日记表(diary)通过外键与用户表关联,包含标题、内容、发布日期等关键信息,支持私人标记功能以实现隐私保护。分类表(sort)采用独立的ID管理,允许用户对日记进行个性化分类管理。
在用户认证方面,系统实现了安全的登录机制。通过预编译的PreparedStatement执行SQL查询,有效防止SQL注入攻击。用户密码采用MD5加密存储,确保即使数据库泄露也不会直接暴露用户密码。
// 用户登录验证核心代码
public User login(String username, String password) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
User user = null;
try {
conn = DBUtil.getConnection();
String sql = "SELECT * FROM user WHERE username=? AND password=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, MD5Util.encode(password));
rs = pstmt.executeQuery();
if(rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setSex(rs.getString("sex"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, pstmt, rs);
}
return user;
}

日记管理模块支持完整的CRUD操作。用户可创建新日记,系统自动记录创建时间并支持内容格式化。日记列表分页显示,支持按日期、分类和关键词搜索,大大提升了日记检索的效率。
// 日记分页查询实现
public PageBean<Diary> findDiaryByPage(int currentPage, int pageSize, int userId) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
PageBean<Diary> pb = new PageBean<>();
try {
conn = DBUtil.getConnection();
String sql = "SELECT COUNT(*) FROM diary WHERE user_id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, userId);
rs = pstmt.executeQuery();
if(rs.next()) {
int totalCount = rs.getInt(1);
pb.setTotalCount(totalCount);
pb.setCurrentPage(currentPage);
pb.setPageSize(pageSize);
int totalPage = (int) Math.ceil(totalCount * 1.0 / pageSize);
pb.setTotalPage(totalPage);
int start = (currentPage - 1) * pageSize;
sql = "SELECT * FROM diary WHERE user_id=? ORDER BY create_time DESC LIMIT ?,?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, userId);
pstmt.setInt(2, start);
pstmt.setInt(3, pageSize);
rs = pstmt.executeQuery();
List<Diary> list = new ArrayList<>();
while(rs.next()) {
Diary diary = new Diary();
diary.setId(rs.getInt("id"));
diary.setTitle(rs.getString("title"));
diary.setContent(rs.getString("content"));
diary.setCreateTime(rs.getTimestamp("create_time"));
list.add(diary);
}
pb.setList(list);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, pstmt, rs);
}
return pb;
}

分类管理功能允许用户自定义日记分类体系。系统采用独立的分类表设计,支持分类的增删改查操作,每个分类通过用户ID与特定用户关联,确保数据隔离。
// 分类管理核心逻辑
public class SortService {
public boolean addSort(Sort sort) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBUtil.getConnection();
String sql = "INSERT INTO sort(name, user_id) VALUES(?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, sort.getName());
pstmt.setInt(2, sort.getUserId());
int result = pstmt.executeUpdate();
return result > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
} finally {
DBUtil.close(conn, pstmt, null);
}
}
public List<Sort> findSortByUserId(int userId) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Sort> list = new ArrayList<>();
try {
conn = DBUtil.getConnection();
String sql = "SELECT * FROM sort WHERE user_id=? ORDER BY id DESC";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, userId);
rs = pstmt.executeQuery();
while(rs.next()) {
Sort sort = new Sort();
sort.setId(rs.getInt("id"));
sort.setName(rs.getString("name"));
sort.setUserId(rs.getInt("user_id"));
list.add(sort);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, pstmt, rs);
}
return list;
}
}

系统的实体模型设计充分体现了面向对象的原则。User类封装用户基本信息,Diary类包含日记的核心属性和关联关系,Sort类管理分类信息。每个实体类都实现了标准的JavaBean规范,确保数据在各个层之间的顺畅传递。
// 日记实体类设计
public class Diary {
private Integer id;
private String title;
private String content;
private Timestamp createTime;
private Integer userId;
private Integer sortId;
private String isPrivate;
// 构造方法
public Diary() {}
public Diary(String title, String content, Timestamp createTime,
Integer userId, Integer sortId, String isPrivate) {
this.title = title;
this.content = content;
this.createTime = createTime;
this.userId = userId;
this.sortId = sortId;
this.isPrivate = isPrivate;
}
// Getter和Setter方法
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public Timestamp getCreateTime() { return createTime; }
public void setCreateTime(Timestamp createTime) { this.createTime = createTime; }
public Integer getUserId() { return userId; }
public void setUserId(Integer userId) { this.userId = userId; }
public Integer getSortId() { return sortId; }
public void setSortId(Integer sortId) { this.sortId = sortId; }
public String getIsPrivate() { return isPrivate; }
public void setIsPrivate(String isPrivate) { this.isPrivate = isPrivate; }
}
数据持久层采用JDBC连接池技术优化数据库访问性能。通过DBUtil类封装数据库连接和资源释放的逻辑,确保数据库连接的高效利用和避免内存泄漏。
// 数据库工具类实现
public class DBUtil {
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/diary_db?useSSL=false";
private static final String USERNAME = "root";
private static final String PASSWORD = "123456";
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

系统在安全性方面实施了多重防护措施。除了SQL注入防护外,还实现了会话管理机制,通过HttpSession跟踪用户登录状态,未登录用户无法访问核心功能页面。
// 登录过滤器实现
@WebFilter("/*")
public class LoginFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String uri = request.getRequestURI();
if(uri.contains("/login.jsp") || uri.contains("/login") ||
uri.contains("/css/") || uri.contains("/js/") ||
uri.contains("/fonts/") || uri.contains("/index.jsp")) {
chain.doFilter(req, resp);
} else {
Object user = request.getSession().getAttribute("user");
if(user != null) {
chain.doFilter(req, resp);
} else {
response.sendRedirect(request.getContextPath() + "/login.jsp");
}
}
}
}
系统的前端界面采用响应式设计,确保在不同设备上都能获得良好的用户体验。通过CSS媒体查询技术实现布局自适应,结合JavaScript增强交互效果,为用户提供流畅的操作体验。
未来优化方向包括引入全文搜索引擎提升日记检索效率,实现日记内容的情感分析功能,增加多端同步支持,开发数据导出和备份机制,以及引入Markdown编辑器提升日记编辑体验。这些功能将进一步提升系统的实用性和用户体验。
在技术架构层面,考虑引入Spring框架替代原生Servlet以提升开发效率,使用MyBatis简化数据持久层操作,采用Redis缓存热点数据提升系统性能。同时,前端可考虑采用Vue.js等现代框架重构界面,实现前后端分离架构。
数据安全方面计划增强密码加密强度,采用bcrypt等更安全的哈希算法,增加登录失败次数限制防止暴力破解,实施HTTPS加密传输敏感数据,并添加操作日志记录功能以便审计追踪。
系统扩展性设计允许未来轻松集成第三方服务,如天气信息自动记录、地理位置标记、图片和附件上传等功能。通过模块化设计和清晰的接口定义,确保新功能的平滑集成和系统的长期可维护性。