实战指南:深度剖析Servlet+JSP+JDBC技术栈下的用户CRUD操作

本博客总结基于MVC(JSP+Servlet+JDBC)操作用户信息的CRUD(增删改查功能)的完整小项目。包括图片上传和回显,模糊查询,过滤器的登录校验和设置全局字符集以及监听器统计在线用户人数等额外功能,因为代码较多,我只解释思路和重点代码分析,其余代码我会放在资源中

完整项目结构分析

 创建一个JavaWeb项目,配置pom.xml和web.xml

pom.xml

需要注意:这里的smartupload组件的依赖包,是我手动导入本地仓库的,在中央仓库时不存在这个jar包的,直接导是导不进来的,可以查看我的smartupload相关的博客,有jar包提供和使用方式(这个组件的目的是为了简化文件上传和下载的操作,虽然已经停止更新,但是依然好用)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>servlet_CRUD_9_18</artifactId><packaging>war</packaging><version>1.0-SNAPSHOT</version><name>servlet_CRUD_9_18 Maven Webapp</name><url>http://maven.apache.org</url><dependencies><!--junit单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--jdbc连接mysql数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><!--servlet--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>provided</scope></dependency><!--jstl--><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!--smartUpload--><dependency><groupId>smartupload</groupId><artifactId>smartupload</artifactId><version>1.0</version><scope>system</scope><systemPath>D:/maven/maven-3.9.9/repository/smartuplaod/smartupload/1.0/smartupload.jar</systemPath></dependency></dependencies><build><finalName>servlet_crud</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.3.2</version></plugin><plugin><groupId>org.eclipse.jetty</groupId><artifactId>jetty-maven-plugin</artifactId><version>9.3.14.v20161028</version></plugin><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8080</port><path>/servlet_crud</path><uriEncoding>UTF-8</uriEncoding><server>tomcat7</server></configuration></plugin></plugins></build>
</project>

web.xml

将web.xml的头声明,更新到3.0以上的目的是为了使用注解的方式映射servlet中的路径,进一步提供开发效率

<?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><display-name>Archetype Created Web Application</display-name></web-app>

第二步:创建数据库表(用户表t_user)和对应的实体类User

用户表t_user

字段代表的含义:

用户id:用户的唯一标识

用户名

用户密码

用户照片:保存的是照片名字+后缀 

 

实体类User

引入了lombok注解,简化开发,省略了getter/setter方法的书写和全参无参构造的书写

package entity;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class User implements Serializable {private Integer userId;private String userName;private String password;private String userPic;public User(Integer userId, String userName, String password) {this.userId = userId;this.userName = userName;this.password = password;}public User(String userName, String password, String userPic) {this.userName = userName;this.password = password;this.userPic = userPic;}
}

第三步:导入操作数据库的JDBC工具类DBUtil和分页工具类PageUtil

DBUtil

package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class DBUtil {private final static String DRIVER="com.mysql.cj.jdbc.Driver";private final static String URL="jdbc:mysql://localhost:3306/csx_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull";private final static String DBNAME="root";private final static String DBPASS="root";public static Connection getConn(){Connection conn=null;try {Class.forName(DRIVER);conn= DriverManager.getConnection(URL,DBNAME,DBPASS);}catch (Exception e){e.printStackTrace();}return conn;}public static void closeAll(Connection conn, Statement st, ResultSet rs){try {if (rs!=null){rs.close();}if (st!=null){st.close();}if (conn!=null){conn.close();}}catch (Exception e){e.printStackTrace();}}}

PageUtil

分页工具类的目的是计算出总页数,并且固定了每页显示的条数

package util;public class PageUtil {public final static int PAGE_SIZE=3;   //每页显示的条数/*** 计算出总页数* @param count* @param pageSize* @return*/public static int getTotalPages(int count,int pageSize){return count%pageSize==0?count/pageSize:count/pageSize+1;}
}

第四步:分析项目需求的SQL支持,书写DAO

因为需要完成若干需求,因此每个SQL都是有对应的意义的,我将逐个分析

 UserDao

为了实现分页功能(分页查询用户数据),我们需要分页查询用户列表的sql和查询用户总数的sql

对应接口方法:

  /*** 查看用户总条数* @return*/int selectUsersCount();/*** 分页查询用户列表* @param pageIndex 当前页* @param pageSize 每页显示的条数* @param keyword 模糊搜索关键字* @return*/List<User> selectUserListByPage(int pageIndex, int pageSize, String keyword);

对应的方法实现:我使用的是原生的jdbc实现,这里暂不展示源码,我会提供完整代码

为了实现新增用户功能需求,需要新增sql支持

对应接口方法: 

  /*** 新增用户* @param user* @return*/public int insertUser(User user);

为了实现展示用户数据的需求,需要查询指定用户信息的sql支持

对应的接口方法:

    /*** 根据id查询指定用户信息* @param userId* @return*/public User selectUserByUserId(int userId);

 为了实现删除用户信息的需求,需要删除sql的支持

对应的接口方法:

    /*** 根据id删除用户信息* @param userId* @return*/public int deleteUserByUserId(int userId);

 为了实现更新用户信息的功能需求,需要修改的sql支持

对应的接口方法:

 /*** 修改用户数据* @param user* @return*/public int updateUser(User user);

 想要完成在线用户统计的功能需求,需要根据用户名和密码查看指定用户是否存在的sql支持

对应的接口方法:

 /*** 根据用户名和密码查看指定用户是否存在* @param username* @param password* @return*/public int selectUserByuserNameAndpassword(String username,String password);

 注意:这里都没有展示对应的接口方法的实现类中的方法。因为实现类中使用的连接数据库的技术可以随意替换,但是完成需求需要的sql支持是不变的,所以在实现功能时,优先考虑需求,然后才考虑用什么技术实现,本项目我使用的是原生的jdbc+封装的工具类实现sql,还可以使用JDBCTemplate和Mybats

 第五步:分析项目需求,书写前端页面

在webapp目录下,存放着当前项目所需要的html,jsp和图片资源等。

基本思路

  • 创建upfiles文件夹存放我们上传的图片资源
  • 创建front文件夹,里面存放的html,和jsp需要登录后才能查看(需要过滤器支持)
  • 在根目录下的login.jsp和onLineUser.jsp分别是登录首页和统计在线用户人数的页面,它们是不需要拦截的

 第六步:创建servlet接收前端发送的请求,并进行处理

整个项目的实现思路是:

  1. 拆分各个功能,一一进行实现
  2. 分析各个功能所需的sql支持,书写DAO
  3. 书写前端页面,展示数据发送请求
  4. 书写对应的servlet类处理请求,完成逻辑(转发请求或页面跳转)

 第七步:创建过滤器,完成字符集统一和登录校验

EncodingFilter

统一字符集为UTF-8

package filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebFilter("/*")
public class EncodingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request =(HttpServletRequest) servletRequest;HttpServletResponse response =(HttpServletResponse) servletResponse;request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {}}

LoginFilter

package filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;@WebFilter(urlPatterns = {"/front/*","/userPage"})
public class LoginFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {//获取sessionHttpServletRequest request =(HttpServletRequest) servletRequest;HttpSession session = request.getSession();//从session中取出登录的时候存的登录信息String username = (String)session.getAttribute("username");//如果不为空,就放行if (username!=null){filterChain.doFilter(servletRequest,servletResponse);}else {request.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);}}@Overridepublic void destroy() {}
}

第八步:创建监听器,监听session,目的是为了统计在线用户数

OnLineUserListener

package listener;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
import java.util.ArrayList;
import java.util.List;@WebListener
public class OnLineUserListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {ServletContext application;@Overridepublic void contextInitialized(ServletContextEvent servletContextEvent) {List<String> onLineUsers =new ArrayList<>();application = servletContextEvent.getServletContext();application.setAttribute("onLineUsers",onLineUsers);}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {}@Overridepublic void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {HttpSession session =httpSessionBindingEvent.getSession();String username =(String) session.getAttribute("username");List<String> onLineUsers=(List<String>) application.getAttribute("onLineUsers");onLineUsers.add(username);}@Overridepublic void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {}@Overridepublic void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {}@Overridepublic void sessionCreated(HttpSessionEvent httpSessionEvent) {}@Overridepublic void sessionDestroyed(HttpSessionEvent httpSessionEvent) {HttpSession session= httpSessionEvent.getSession();String username= (String) session.getAttribute("username");List<String> onLineUsers= (List<String>) application.getAttribute("onLineUsers");onLineUsers.remove(username);}
}

 项目演示

整个项目的逻辑就是,先写sql,然后写页面,最后在写servlet将sql和页面联系在一起

 登录

用户信息展示页面

包含了以下功能:

  • 顶部的模糊搜索功能
  • 新增用户功能
  • 点击用户信息展示用户详细信息的功能
  • 修改用户功能
  • 删除用户功能
  • 以及底部的分页查看功能

 项目源码已上传,个人原创资源共享,感谢支持,有问题可以问我!

资源名称(我的资源查看):基于Servlet+JSP+JDBC的完整的用户信息操作-CRUD项目总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147533.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

UnLua实现继承

一、在蓝图中实现继承 1、创建父类&#xff0c;并绑定Lua脚本 2、创建子类蓝图&#xff0c;如果先创建的子类&#xff0c;可以修改父类继承 注意&#xff0c;提示选择继承父类的接口&#xff01; 二、在Lua中实现继承 1、在父类Lua脚本中实现函数 BP_CharacterBase.lua func…

构建数字化生态系统:打造数字化转型中开放协作平台的最佳实践和关键实施技巧

在数字化转型浪潮中&#xff0c;企业如何确保成功实施至关重要。除了技术上的革新&#xff0c;企业还必须在战略执行、架构优化以及合规性管理等方面掌握最佳实践。随着云计算、大数据、人工智能等新兴技术的迅速发展&#xff0c;企业通过正确的实施技巧不仅能提升业务效率&…

Qemu开发ARM篇-3、qemu运行uboot演示

文章目录 1、运行uboot2、qemu常用命令 在上一篇Qemu开发ARM篇-2、uboot交叉编译文章中&#xff0c;我们搭建了交叉编译工具链&#xff0c;并成功进行了uboot的交叉编译&#xff0c;在该篇中&#xff0c;我们将演示如何利用qemu运行上一篇中交叉编译的uboot程序。 1、运行uboo…

计算机毕业设计之:基于微信小程序的学生考勤系统的设计与实现(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Redis——redispluspls库hash及zset类型相关接口使用

文章目录 hash类型相关接口hset和hgethexistshdelhkeys 和 hvalshmset和hmget zset类型相关接口zadd和zrangezcard 和 zremzscore和zrank hash类型相关接口 hset和hget std::cout<<"hset 和 hget"<<std::endl;redis.flushall();redis.hset("key&qu…

Java 分布式锁:原理与实践

在分布式系统中&#xff0c;多个节点同时操作共享资源的情况非常普遍。为了保证数据的一致性&#xff0c;分布式锁 应运而生。分布式锁 是一种跨多个服务器的互斥锁&#xff0c;用于协调分布式环境下的资源访问。 本文将介绍 Java 实现分布式锁 的几种常见方式&#xff0c;并结…

OpenAI API: How to catch all 5xx errors in Python?

题意&#xff1a;OpenAI API&#xff1a;如何在 Python 中捕获所有 5xx 错误&#xff1f; 问题背景&#xff1a; I want to catch all 5xx errors (e.g., 500) that OpenAI API sends so that I can retry before giving up and reporting an exception. 我想捕获 OpenAI API…

浙大数据结构:05-树8 File Transfer

数据结构MOOC PTA习题 这道题考察并查集的操作&#xff0c;合并以及找根结点 机翻&#xff1a; 1、条件准备 node是数组存放1-N结点的根节点的&#xff0c;n为总结点数 #include <iostream> using namespace std;const int N 1e4 5; int node[N]; int n; 先初始化…

<<编码>> 第 16 章 存储器组织(3)--3-8 译码器 示例电路

3-8 译码器 info::操作说明 “写入” 开关先断开(Q 为低电平, 表示不写入) S2-S1-S0 设置一个二进制数, 选中 Q0~Q7 其中一个作为 Q 的输出 “数据输入” 端置入要保存的数(0或1) 闭合 “写入” 开关, 对应的一位锁存器中的 W 为高电平, 表示可以写入, “数据输入” 的值最终…

嵌入式常用GUI介绍

目录 前言一、GuiLite二、LVGL三、SimpleGUI四、MiniGUI五、emWin六、TouchGFX七、uGUI八、GFX九、Embedded Wizard十、CrankSoftware十一、PEG Graphics Software十二、Guiliani十三、MPLAB Harmony Graphics Suite 前言 图形用户界面&#xff08;Graphical User Interface&am…

关系数据库设计之Armstrong公理详解

~犬&#x1f4f0;余~ “我欲贱而贵&#xff0c;愚而智&#xff0c;贫而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯学乎” 一、Armstrong公理简介 Armstrong公理是一组在关系数据库理论中用于推导属性依赖的基本规则。这些公理是以著名计算机科学家威廉阿姆斯特朗&…

优化内存工具 | RAM Saver Pro v24.9 便携版

RAM Saver是一款专业的RAM优化工具&#xff0c;旨在提高计算机的性能和运行速度。它通过多种优化技术&#xff0c;如内存碎片整理、CPU和主板缓存效率提升、恢复内存等&#xff0c;为应用程序提供更多的内存资源&#xff0c;从而使系统运行更加流畅。适合所有需要优化内存使用和…

EMT-LTR--学习任务间关系的多目标多任务优化

EMT-LTR–学习任务间关系的多目标多任务优化 title&#xff1a; Learning Task Relationships in Evolutionary Multitasking for Multiobjective Continuous Optimization author&#xff1a; Zefeng Chen, Yuren Zhou, Xiaoyu He, and Jun Zhang. journal&#xff1a; IEE…

银河麒麟V10系统崩溃后的处理

银河麒麟V10系统崩溃后的处理 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 当银河麒麟桌面操作系统V10崩溃无法启动时&#xff0c;直接使用备份还原工具不可行。此时&#xff0c;应采取以下步骤&#xff1a; 进入救援模式或LiveCD&#x…

攻防世界---->Windows_Reverse1

学习笔记。 前言&#xff1a;不会&#xff0c;代码越简洁&#xff0c;越难受 T ^ T 下载 查壳。 UPX脱壳。 此题脱壳后的程序&#xff0c;是不能运行的。 网上wp&#xff0c;说是因为作者采用了ASLR(地址随机化) 解决方法&#xff1a;一&#xff1a;用XP运行调试。 方法二&a…

0基础跟德姆(dom)一起学AI 数据处理和统计分析05-Pandas数分入门

* DataFrame读写文件 * DataFrame加载部分数据 * DataFrame分组聚合计算 * DataFrame常用排序方式 * DataFrame案例-链家数据分析 --- 1.DataFrame-保存数据到文件 * 格式 python df对象.to_数据格式(路径) # 例如: df.to_csv(data/abc.csv) * 代码演示 > 如…

Deepin man 没有关于printf 的手册页条目

问题 man 3 printf&#xff1a;在第 3 节中没有关于 printf 的手册页条目。 解决方法&#xff1a;安装manpages发开库。 搜索包 apt search manpages安装 sudo apt install manpages-dev若没有manpages-dev&#xff0c;安装manpages-posix-dev&#xff0c;应该也可以&#x…

【成品论文】2024年华为杯研赛E题25页高质量成品论文(后续会更新

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片链接&#xff0c;那是获取资料的入口&#xff01; 点击链接加入【2024华为杯研赛资料汇总】&#xff1a;https://qm.qq.com/q/Mxv2XNWxUc https://qm.qq.com/q/Mxv2XNWxUc 高速公路应急车道紧急启用模型…

深度学习02-pytorch-03-张量的数值计算

张量&#xff08;Tensor&#xff09;是多维数组的通用化概念&#xff0c;它可以表示标量&#xff08;0维&#xff09;、向量&#xff08;1维&#xff09;、矩阵&#xff08;2维&#xff09;以及更高维度的数据。在深度学习和数值计算中&#xff0c;张量是基础数据结构&#xff…

基于python的api扫描器系统的设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…