新闻详情

新闻详情

首页 / 资讯中心 / 详情

JSP+SQL宠物诊所系统实战:从环境搭建到二次开发

发布时间:2026/10/1 13:12:27来源:尧图网络
JSP+SQL宠物诊所系统实战:从环境搭建到二次开发
简介这是一套面向计算机专业学生与Java Web初学者、课程设计或毕业设计场景的宠物诊所管理系统完整资料包基于JSP与SQL数据库实现覆盖需求分析、架构设计、数据库建模到前端界面开发全流程。压缩包共446个文件约2.55MB以java源码、jsp页面、class编译文件为主另含jar依赖、xml配置、SQL脚本及文章说明文档分别承担业务逻辑、界面展示、数据库连接与建表初始化等职责。系统采用MVC模式包含宠物资料、主人信息、就诊记录、药品库存等模块通过外键关联保证数据一致性并配有Servlet控制器与JavaBeans封装业务对象。已有334人学习下载读者可据此掌握JSP动态网页与SQL交互的完整实现思路对照源码理解分层结构、数据库表设计与增删改查逻辑适合作为Web开发入门练手或二次开发参考。1. 从一份 .rar 说起JSP SQL 做宠物诊所系统今天还值不值得动手宠物诊所的日常其实很琐碎前台要给新来的猫狗建档医生要查历史病历和疫苗记录药房要扣库存老板月底想看营收。这些动作背后就是一张张表——宠物、主人、医生、挂号、处方、药品。把这套流程塞进一个 Web 系统最经典的入门方案就是 JSP 配 SQL 数据库。你手上如果正好有一个「基于 JSP 和 SQL 数据库的宠物诊所系统」的压缩包里面通常躺着三样东西一堆 .jsp 页面、一份建库 SQL 脚本、一份说明文档。很多人第一反应是「JSP 都过时了还学它干嘛」但真到要交课程设计、要理解 MVC 之前的分层长什么样、要快速搭一个能跑的内网小工具时JSP 反而是门槛最低的那条路。这篇不吹不黑就按一个能落地的顺序把环境、建库、页面、排错、打包讲清楚让你拿到源码能跑起来也能自己改出第二个模块。2. 环境与工程结构把 JSP 项目在 IDEA 里跑起来2.1 为什么是 Tomcat JDK8 MySQL 这套老组合JSP 本质是 Servlet 的语法糖它必须跑在 Servlet 容器里最常见的就是 Tomcat。选版本这件事有血泪经验JDK 别上太新JDK8 或 JDK11 最稳因为很多老项目的web.xml还是 2.5/3.0 的写法Servlet 注解和javax.*包名在 JDK17 之后配合老 Tomcat 容易出玄学问题。Tomcat 选 8.5 或 9.0这两个版本对javax.servlet支持完整10 以后换成了jakarta.*老代码直接编译不过。数据库这边宠物诊所系统数据量小MySQL 5.7 或 8.0 都行。要注意的是 8.0 的驱动类名变成了com.mysql.cj.jdbc.Driver连接串还要带时区和 SSL 参数否则控制台会刷一堆警告。下面这套组合是我一般会用的组件推荐版本说明JDK8 或 11避免javax包缺失Tomcat8.5 / 9.0支持javax.servletMySQL5.7 / 8.08.0 注意驱动与连接串驱动 jarmysql-connector-java 8.0.x放WEB-INF/libIDEIDEA新建项目时选 Web 模板2.2 在 IDEA 里新建 JSP 项目的完整步骤热词里「idea 新建 jsp 项目」被搜了很多次说明卡在这一步的人不少。IDEA 社区版没有直接的 Java Web 模板得手动配。步骤是新建 Java 项目 → 在项目结构里加 Web Facet → 指定web目录和web.xml→ 配置 Tomcat 运行。下面用命令和配置片段把关键动作固定下来。# 1. 建目录骨架也可以让 IDEA 生成这里给出标准结构 mkdir -p petclinic/src/main/java mkdir -p petclinic/src/main/webapp/WEB-INF/lib mkdir -p petclinic/src/main/webapp/WEB-INF/classes # 2. 把驱动 jar 丢进 lib cp mysql-connector-java-8.0.28.jar petclinic/src/main/webapp/WEB-INF/lib/ # 3. 确认 web.xml 存在没有就手写一个 3.0 版本头!-- webapp/WEB-INF/web.xml 最小可用版本 -- ?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_0.xsd version3.0 welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list /web-app逻辑说明WEB-INF/lib是 Tomcat 自动加载 jar 的位置驱动放这里就不用额外配 classpath。web.xml的welcome-file决定访问根路径时默认打开哪个页面宠物诊所系统一般先跳登录页。参数上version3.0对应 Servlet 3.0支持注解方式写 Servlet如果你拿到的源码用的是WebServlet这个头必须对上否则注解不生效。2.3 数据库连接怎么配才不写死新手最容易犯的错是把账号密码硬编码在每个 JSP 里改一次数据库要翻十几个文件。正确做法是抽一个工具类用DriverManager或连接池统一拿连接。下面这个DBUtil是常见写法// src/main/java/com/clinic/util/DBUtil.java package com.clinic.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { // 8.0 驱动类名5.7 用 com.mysql.jdbc.Driver private static final String DRIVER com.mysql.cj.jdbc.Driver; // useSSLfalse 关掉 SSL 警告serverTimezone 必带否则时间错乱 private static final String URL jdbc:mysql://localhost:3306/pet_clinic?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PWD your_password; static { try { Class.forName(DRIVER); // 加载驱动只需一次 } catch (ClassNotFoundException e) { throw new RuntimeException(驱动加载失败检查 jar 是否在 WEB-INF/lib, e); } } public static Connection getConn() throws SQLException { return DriverManager.getConnection(URL, USER, PWD); } }逻辑说明静态代码块保证驱动只加载一次getConn()每次返回新连接。参数里serverTimezoneAsia/Shanghai是 8.0 的硬性要求不写会报时区异常characterEncodingutf8防止中文宠物名变问号。生产环境应该换成连接池比如 Druid 或 HikariCP但课程设计级别用DriverManager足够先跑通再优化。3. 建库与 SQL 脚本宠物诊所系统的表怎么设计3.1 从业务动作反推五张核心表拿到 SQL 脚本先别急着执行看懂表关系比跑通更重要。宠物诊所的核心动作是「主人带宠物来看病」所以至少要有主人表、宠物表、医生表、挂号/就诊记录表、药品表。下面这张关系表帮你快速对齐表名作用关键外键owner宠物主人信息无pet宠物档案owner_id → ownerdoctor医生信息无visit就诊/挂号记录pet_id、doctor_idmedicine药品库存无设计时有个细节宠物和主人是一对多一个主人可能养好几只所以pet表里放owner_id而不是在owner里存宠物列表。就诊记录同理一次就诊对应一只宠物和一位医生。3.2 建表 SQL 与增删改查语句下面给出核心建表脚本字段类型按实际业务选别全用varchar(255)图省事。-- 建库字符集用 utf8mb4 支持 emoji 宠物名 CREATE DATABASE pet_clinic DEFAULT CHARACTER SET utf8mb4; USE pet_clinic; CREATE TABLE owner ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, phone VARCHAR(20) NOT NULL, address VARCHAR(200) ); CREATE TABLE pet ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, species VARCHAR(20), -- 猫/狗/其他 age INT, owner_id INT, FOREIGN KEY (owner_id) REFERENCES owner(id) ); CREATE TABLE doctor ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, title VARCHAR(50) -- 职称 ); CREATE TABLE visit ( id INT PRIMARY KEY AUTO_INCREMENT, pet_id INT, doctor_id INT, visit_time DATETIME DEFAULT CURRENT_TIMESTAMP, diagnosis VARCHAR(500), fee DECIMAL(10,2), FOREIGN KEY (pet_id) REFERENCES pet(id), FOREIGN KEY (doctor_id) REFERENCES doctor(id) ); CREATE TABLE medicine ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, stock INT DEFAULT 0, price DECIMAL(10,2) );逻辑说明AUTO_INCREMENT让主键自增省去手动编号DECIMAL(10,2)存金额比FLOAT精确费用计算不会出现 0.30000000004 这种鬼东西外键约束保证不会出现「宠物挂在不存在的主人名下」。执行顺序必须先建owner再建pet否则外键找不到引用表。日常操作就是增删改查下面几条是系统里出现频率最高的-- 新增一只宠物 INSERT INTO pet (name, species, age, owner_id) VALUES (豆豆, 狗, 3, 1); -- 查询某主人的所有宠物连表 SELECT p.name, p.species, o.name AS owner_name FROM pet p JOIN owner o ON p.owner_id o.id WHERE o.id 1; -- 更新药品库存就诊扣减 UPDATE medicine SET stock stock - 1 WHERE id 5 AND stock 0; -- 删除一条就诊记录 DELETE FROM visit WHERE id 10;参数说明UPDATE里加AND stock 0是防止库存扣成负数这是并发场景下的基本防护JOIN查询比在 JSP 里循环查库效率高得多别一个主人查一次宠物表。3.3 慢 SQL 与注入两个必须提前防的坑热词里「慢 sql 优化」和「sql 注入」都出现了说明这是真实痛点。宠物诊所数据量小慢 SQL 一般不是性能问题而是没建索引。比如按手机号查主人phone字段没索引就会全表扫。加一句CREATE INDEX idx_phone ON owner(phone);就能解决。SQL 注入更危险。如果 JSP 里写成SELECT * FROM owner WHERE name name 别人输入 OR 11就能绕过登录。正确做法是全程用PreparedStatement// 错误示范字符串拼接等于给注入开门 // String sql SELECT * FROM owner WHERE name name ; // 正确做法占位符 setXxx String sql SELECT * FROM owner WHERE name ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, name); // 参数从 1 开始编号 ResultSet rs ps.executeQuery();逻辑说明PreparedStatement会把参数当数据而不是 SQL 语法处理 OR 11只会被当成一个普通字符串去匹配注入失效。参数编号从 1 开始别写成 0否则报Parameter index out of range。4. JSP 页面与 Servlet 协作把增删改查接到浏览器上4.1 JSP 里怎么写 Java 才不失控JSP 允许在% %里写 Java但这正是它被诟病的地方——业务逻辑和页面混在一起改一个查询要翻 HTML。合理的边界是JSP 只负责展示和收集表单真正的数据库操作放到 Servlet 或 JavaBean 里。下面是一个宠物列表页的典型写法% page contentTypetext/html;charsetUTF-8 languagejava % % page importjava.util.List % % page importcom.clinic.entity.Pet % html headtitle宠物列表/title/head body table border1 trthID/thth名字/thth种类/thth年龄/th/tr % // 数据由 Servlet 通过 request 传进来JSP 只做遍历展示 ListPet pets (ListPet) request.getAttribute(pets); if (pets ! null) { for (Pet p : pets) { % tr td% p.getId() %/td td% p.getName() %/td td% p.getSpecies() %/td td% p.getAge() %/td /tr % } } % /table /body /html逻辑说明request.getAttribute(pets)拿的是 Servlet 转发过来的数据JSP 不碰数据库。% %是输出表达式等价于out.print()。注意ListPet的泛型在 JSP 里要正确 import否则编译报错。这种「Servlet 查数据 → 转发 JSP 展示」的模式就是 MVC 的雏形理解它对后面学框架很有帮助。4.2 一个完整的 Servlet处理新增宠物请求Servlet 负责接收表单、调数据库、决定跳哪个页面。下面这个AddPetServlet覆盖了完整流程// src/main/java/com/clinic/servlet/AddPetServlet.java package com.clinic.servlet; import com.clinic.util.DBUtil; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; WebServlet(/addPet) public class AddPetServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { // 1. 设置编码否则中文宠物名乱码 req.setCharacterEncoding(UTF-8); String name req.getParameter(name); String species req.getParameter(species); int age Integer.parseInt(req.getParameter(age)); int ownerId Integer.parseInt(req.getParameter(ownerId)); // 2. 入库 String sql INSERT INTO pet (name, species, age, owner_id) VALUES (?,?,?,?); try (Connection conn DBUtil.getConn(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, name); ps.setString(2, species); ps.setInt(3, age); ps.setInt(4, ownerId); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } // 3. 重定向回列表页避免刷新重复提交 resp.sendRedirect(petList); } }逻辑说明WebServlet(/addPet)把 URL 映射到这个类前提是web.xml版本 ≥ 3.0。req.setCharacterEncoding(UTF-8)必须在getParameter之前调用顺序反了不生效。try-with-resources自动关闭连接和语句比手动finally干净。最后用sendRedirect而不是forward是为了防止用户刷新页面时重复插入数据这是表单提交的经典处理方式。4.3 分页查询数据一多就必须加宠物列表刚开始只有几条等测试数据加到几百条页面就会又长又慢。分页的核心是 SQL 的LIMIT-- 第 pageNo 页每页 pageSize 条 SELECT * FROM pet ORDER BY id DESC LIMIT ?, ?; -- 参数1 (pageNo - 1) * pageSize参数2 pageSizeint pageNo Integer.parseInt(req.getParameter(pageNo) null ? 1 : req.getParameter(pageNo)); int pageSize 10; int offset (pageNo - 1) * pageSize; ps.setInt(1, offset); ps.setInt(2, pageSize);参数说明offset是跳过的行数pageSize是每页条数。MySQL 的LIMIT第一个参数是偏移量别和 Oracle 的ROWNUM写法搞混。页面上再放「上一页/下一页」链接把pageNo拼进 URL 即可。5. 避坑与排查JSP SQL 项目最容易翻车的五个地方5.1 中文乱码现象、原因、解决现象表单提交的宠物名在数据库里变成???或乱码。原因有三层JSP 页面编码、请求编码、数据库连接编码任何一层没设对都会乱。解决JSP 顶部写% page contentTypetext/html;charsetUTF-8 %Servlet 里req.setCharacterEncoding(UTF-8)连接串带characterEncodingutf8数据库和表用utf8mb4。四处对齐乱码基本消失。5.2 ClassNotFoundException: com.mysql.cj.jdbc.Driver现象启动后第一次查库就抛驱动找不到。原因驱动 jar 没放进WEB-INF/lib或者放进了但 IDEA 没把它加入 Artifact。解决确认 jar 在WEB-INF/lib下然后在 IDEA 的 Project Structure → Artifacts 里检查WEB-INF/lib是否被包含进输出。改完重新部署别只重启 Tomcat。5.3 时区异常 ServerTimezone 报错现象连接 8.0 数据库时报The server time zone value ?D1ú±ê×?ê±?? is unrecognized。原因连接串没指定时区驱动拿系统时区去匹配失败。解决URL 里加serverTimezoneAsia/Shanghai。这是 8.0 驱动特有的坑5.7 一般不会遇到。5.4 404Servlet 映射不生效现象表单提交后跳 404控制台没有报错。原因web.xml版本低于 3.0WebServlet注解被忽略或者 URL 拼写和注解不一致。解决把web.xml头改成 3.0 以上或者干脆在web.xml里手动配servlet和servlet-mapping。访问路径区分大小写/addPet和/addpet是两个地址。5.5 连接未关闭导致 Tomcat 越跑越慢现象系统用一会儿就卡重启 Tomcat 又好了。原因JSP 或 Servlet 里拿了连接没关连接池耗尽。解决所有Connection、PreparedStatement、ResultSet都用 try-with-resources 包起来或者放finally里关。检查时可以在 MySQL 里执行SHOW PROCESSLIST;看是不是有一堆 Sleep 状态的连接堆着。6. 打包部署与二次开发把 .rar 变成能交付的系统6.1 打成 war 包丢进 Tomcat热词里「传统 jsp 项目打包 war」是刚需。IDEA 里在 Project Structure → Artifacts 新建 Web Application: Archive把编译输出和WEB-INF/lib都勾上Build 之后在out/artifacts下拿到 war 包。命令行方式更直接# 在 webapp 目录下打包注意包含 WEB-INF cd petclinic/src/main/webapp jar -cvf petclinic.war . # 复制到 Tomcat 部署目录 cp petclinic.war $TOMCAT_HOME/webapps/ # 启动后访问 http://localhost:8080/petclinic/逻辑说明jar -cvf的c是创建、v是显示过程、f是指定文件名。打包时必须在webapp目录内执行保证WEB-INF在 war 根目录下否则 Tomcat 解压后找不到类和库。war 包名会成为访问路径的一部分所以别用中文或空格。6.2 二次开发加一个「疫苗记录」模块拿到源码后想加功能按这个顺序改最省事先加表再加实体类再加 Servlet最后加 JSP。以疫苗记录为例CREATE TABLE vaccine ( id INT PRIMARY KEY AUTO_INCREMENT, pet_id INT, vaccine_name VARCHAR(100), inject_date DATE, FOREIGN KEY (pet_id) REFERENCES pet(id) );然后照着AddPetServlet写一个AddVaccineServlet照着petList.jsp写vaccineList.jsp。实体类字段和表字段一一对应getter/setter 用 IDE 生成。这样改下来一个模块半小时能跑通比从头搭快得多。6.3 验证系统是否真的可用交付前我会跑一遍清单登录能进、新增主人成功、新增宠物挂到主人名下、挂号能选到宠物和医生、药品库存扣减正确、分页翻页正常、中文不乱码、刷新不重复提交。这几条过了系统就算能交付。数据库层面用SELECT COUNT(*)核对几条关键表的记录数和页面显示对得上就说明查询逻辑没错。6.4 一个我常犯的教训早些年我图快把数据库密码直接写在 JSP 里结果换环境时改了七八个文件还是漏了一个排查了一下午。后来养成习惯所有配置抽到一个DBUtil或db.properties改一处全局生效。JSP 这套技术虽然老但「配置集中、逻辑分层、参数化查询」这三条原则放到今天任何框架里都成立。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

2026网络安全前景如何?零基础入门到进阶实战路线全解析 2026/10/1 15:22:48

2026网络安全前景如何?零基础入门到进阶实战路线全解析

最近又有人问我:2026年了,学网络安全还有前途吗?这个问题我每年都会被问几十遍,而且问的人一年比一年焦虑。零基础想入门,怕方向学错;在职想转行,怕35岁被优化;刚入行的新人&#xf…

阅读更多 →
中间人攻击流量分析实战:john-in-the-middle解题全解析 2026/10/1 15:22:48

中间人攻击流量分析实战:john-in-the-middle解题全解析

在BUUCTF的Misc分类里,“john-in-the-middle”算是我刷题过程中印象比较深的一道题。题目名字看起来像个谜语,但实际上只要你读懂了这个名字,解题思路就已经出来一大半了。这篇文章我就从读题开始,把这道题的完整分析过程、工具链…

阅读更多 →
构建网络安全知识体系:从核心概念到实战落地 2026/10/1 15:22:48

构建网络安全知识体系:从核心概念到实战落地

安全这行最不缺的就是资料,最缺的是一张能把资料串起来的地图。我见过太多人从“网络安全的体系有哪些”这个问题开始,然后被等保条款、CIA三元组、零信任架构、SIEM、SOAR、威胁情报、红蓝对抗这些名词淹没,最后收藏夹越来越厚,脑…

阅读更多 →
安卓日历添加与修改实战:用 TaoToken 统一 Key 打通 CalendarContract 配置 2026/10/1 15:22:41

安卓日历添加与修改实战:用 TaoToken 统一 Key 打通 CalendarContract 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
MF308C Openlinux 关于文档 2026/10/1 15:22:41

MF308C Openlinux 关于文档

阅读更多 →
Java迭代器ListIterator的误区:用TaoToken统一Key实测双向遍历与并发修改异常 2026/10/1 15:22:41

Java迭代器ListIterator的误区:用TaoToken统一Key实测双向遍历与并发修改异常

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉