【javaweb开发系统期末不及格的自救指南】

文章详述了一个基于javaweb的在线课程申请与审批系统的开发过程,涵盖了从需求分析、数据库设计、JDBC连接、DAO和Service层实现、Servlet及JSP编写,再到TypeScript和CSS的运用。系统采用了MVC设计模式,实现了学生选课、教师审批的功能,并对关键步骤如数据库表创建、用户管理、审批流程等进行了详细说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前期准备

学生选课,老师审批,要求数据库存储

需求分析

1.在线课程申请模块功能:
1.1学生登录功能
已有账号学生可以在线登录到申请系统中。
用户账户数据可预先存储到数据库中。
1.2在线申请功能
学生登录后,在可选课程列表中,选择要申请的课程。
每次申请只能选择一门课程,不可重复申请。
课程详细数据可预先存储到数据库中。
1.3已申请课程,审批进度查询功能
审批过程中的申请可以进行进度查询。
审批状态有:申请已提交、审批中、审批成功、申请驳回。
审批结束后,也就是审批状态为成功或者驳回,学生可以点击确认,完成本次申请。
1.4已申请课程审批记录查询功能
学生可查询本人已申请的全部记录,包括审批通过和驳回的记录。
2.在线审批模块功能:
2.1课程申请审批功能
已有教师角色账号的教师可登录审批功能。
如果已提交的申请不符合申请条件,可以驳回。
2.2已审批申请查询功能
教师可查询已审批的申请,查询结果可模糊查询。
3.额外功能:
系统后台:系统用户管理。
适应通用性,系统应采用MVC设计模式。

知识储备

JDBC:
是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问,它是由一组用Java语言编写的类和接口组成的。
TOMCAT:
实现了 jsp/servlet 规范,是一个轻量级服务器,开源免费
MVC模型:
M(model,模型):通常用于封装数据模型(实体类)。
V(view,视图):通常用于展示数据。动态展示用 JSP 页面,静态数据展示用 HTML。JSP 擅长显示界面,不擅长处理程序逻辑。在 Web 开发中多用于展示动态界面。
C(controller,控制器):通常用于处理请求和响应。一般指的是 Servlet。Servlet 擅长处理业务逻辑,不擅长输出显示界面。在 Web 开发中多用于控制程序逻辑(流程)。

设计模式

设计模式

编程实现

创建数据库

我这里是用Navicat Premium 16创建的webhome数据库,根据需求,简单创建了course、enroll、users三个表。表里的字段有啥要根据需求来,比如users是用户表,那用户名、密码必须得有;考虑到学生和老师都用自己的真实姓名,那就加上一个real_name;为了区分不同的用户,需要有role值来区分。当然这些数据都是varchar 255 ,整个int其实也行,就是转换起来麻烦多,不是很友好。
在这里插入图片描述users表如下所示。
在这里插入图片描述
包含管理员、学生、老师三个角色,通过role值来区分。
在这里插入图片描述
这里的大长串u_id是随机生成的,我后面jsp中使用java自带的uuid工具类的randomUUID方法来生成。
在这里插入图片描述
course表包含了instructor,这个是课程主讲教师,而manager相当于教务处老师,主管课程教学的。但是后面我并没有将这两个属性的关系搞清楚,所以这个manager属性在这里是没用的。
在这里插入图片描述
enroll表是course和users表的关系集合,表示学生与课程申请审批关系。在这里有提交申请(submitted)、申请通过(approved)和申请驳回(refused)三种状态。
在这里插入图片描述我在bean包里做了类型转换,目的是在界面上输出中文。在这里插入图片描述

javabean封装数据

其实就是创建三个实体类:Course、Enrollment、User。这里我导入了lombok包,用注释@Data代表所有数据的getter和setter方法。@All@No大长串分别是全参构造方法和无参构造方法。简化了代码书写。
这些类的属性名可以跟数据库里的字段名不一样,但是得一一对应,自己清楚哪个属性对应哪个字段。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

JDBC连接数据库

为了方便数据库操作,这里设计了Global类来专门驱动连接数据库,这个类有两个方法,分别是getConnnection和closeConnnection,用来连接和关闭数据库连接。
这其中String url = “jdbc:mysql://localhost:3306/webHome?characterEncoding=utf-8&serverTimezone=GMT%2B8”;代码中的webHome是我的数据库名称,你可以替换成自己的数据库名称。两个“root”是我的mysql用户名和密码,需要替换成自己的。
在这里插入图片描述

Dao接口与DaoImpl具体方法实现

以courseDao接口为例,这里列出了六个方法getAll和query是返回查询列表,justQuery是返回单一查询目标,add、update、del方法分别是增改删功能。
在这里插入图片描述
以courseDaoImpl类为例,courseDaoImpl类继承courseDao接口,在这里将需要写mysql语句来操作mysql数据库数据。
getAll方法:是通过调用query方法实现的,query方法的参数是sql语句"select * from course",这是因为要返回所有列表。
在这里插入图片描述
query方法:先建立Course类。在方法内部,创建了一个空的 ArrayList 对象 list,用于存储查询结果。使用 Global.getConnection() 获取数据库连接,并通过 createStatement() 方法创建一个 Statement 对象 statement,用于执行 SQL 语句。通过 executeQuery() 方法执行给定的 SQL 查询,将结果存储在 ResultSet 对象 resultSet 中。在循环中,通过调用 next() 方法,逐行遍历查询结果。对于每一行,根据 ResultSet 中的列索引,使用 getString() 方法获取具体的列值,并创建一个 Course 对象。将每个 Course 对象添加到先前创建的 list 中。循环结束后,关闭 resultSet 和 statement 对象,释放资源。调用 Global.closeConnection() 关闭数据库连接。如果在执行过程中遇到异常,使用 e.printStackTrace() 方法打印异常信息。最后返回存储结果的 list 对象。
在这里插入图片描述
add方法:它接收一个 Course 对象作为参数,代表要添加的课程信息。在方法内部,创建一个布尔类型的变量 flag,用于表示添加操作是否成功。创建一个 SQL 插入语句,将课程信息插入到名为 course 的表中。语句中的占位符 ? 表示待插入的值。使用 Global.getConnection() 获取数据库连接,并通过 prepareStatement() 方法创建一个 PreparedStatement 象 preparedStatement,用于执行带有参数的 SQL 语句。使用 setString() 方法为 preparedStatement 对象设置参数值。通过调用 course 对象的相应方法,获取要插入的课程属性值,例如课程ID、课程名称、讲师、主管和时间表,并将其传递给对应的索引位置。通过调用 execute() 方法执行 SQL 语句。将执行结果赋给 flag 变量,表示添加操作是否成功。关闭 preparedStatement 和数据库连接,释放资源。如果在执行过程中遇到异常,使用 e.printStackTrace() 方法打印异常信息。最后,返回 flag 变量,表示添加操作的结果。
在这里插入图片描述
update方法:它接收一个 Course 对象作为参数,代表要更新的课程信息。在方法内部,创建一个布尔类型的变量 flag,用于表示更新操作是否成功。创建一个 SQL 更新语句,通过 update 关键字指定要更新的表名为 course,并使用占位符 ? 表示待更新的值。使用 Global.getConnection() 获取数据库连接,并通过 prepareStatement() 方法创建一PreparedStatement 对象 preparedStatement,用于执行带有参数的 SQL 语句。使用 setString() 方法为preparedStatement 对象设置参数值。通过调用 course 对象的相应方法,获取要更新的课程属性值,例如课程名称、讲师、主管和时间表,并将其传递给对应的索引位置。通过调用 execute() 方法执行 SQL 语句。将执行结果赋给 flag 变量,表示更新操作是否成功。关闭 preparedStatement 和数据库连接,释放资源。如果在执行过程中遇到异常,使用 e.printStackTrace() 方法打印异常信息。最后,返回 flag 变量,表示更新操作的结果。
在这里插入图片描述
delete方法:它接收一个 Course 对象作为参数,代表要删除的课程。在方法内部,创建一个布尔类型的变量 flag,用于表示删除操作是否成功。创建一个 SQL 删除语句,通过 delete from 关键字指定要删除的表名为 course,并使用占位符 ? 表示待删除的条件。使用 Global.getConnection() 获取数据库连接,并通过 prepareStatement() 方法创建一个PreparedStatement 对象 preparedStatement,用于执行带有参数的 SQL 语句。使用 setString() 方法为 preparedStatement 对象设置参数值。通过调用 course 对象的 getUuid() 方法,获取要删除课程的唯一标识,并将其传递给占位符的位置。通过调用 execute() 方法执行 SQL 语句。将执行结果赋给 flag 变量,表示删除操作是否成功。关闭 preparedStatement 和数据库连接,释放资源。如果在执行过程中遇到异常,使用 e.printStackTrace() 方法打印异常信息。最后,返回 flag 变量,表示删除操作的结果。
在这里插入图片描述

Service接口和ServiceImpl具体方法实现

Dao接口的方法很通用,如果需要具体实现业务逻辑,还需要编写Service接口。
以CourseService接口为例,这里有queryAll,queryUnSelected,querySelected,queryByID,queryLikeField,add,edit,del共9种方法(其中queryByID参数不同)。为了丰富查询功能,我编写了查询所有列表、查询已选课的列表、查询未选课的列表、根据ID查询、模糊查询;而增删改方法类似。
在这里插入图片描述
以CourseServiceImpl方法的模糊查询queryLikeField为例,这里的参数是两个String,前一个是数据库的字段名,后一个是模糊查询值。
在这里插入图片描述
之后的add、edit、del方法也都是调用Dao接口方法。
在这里插入图片描述
在这里是采用单例设计模式。
在这里插入图片描述
以查询未选课的列表方法queryUnSelected为例,编写sql语句。
在这里插入图片描述
以UserService接口为例,相比于CourseService接口,多了一个verifyLogin方法。在UserServiceImpl类中编写verifyLogin函数体。首先是编写sql语句,通过query方法查到数据库中符合条件的User,并用列表储存。这里做了一个判断,如果列表为空,就创建一个新User,而这个新User是没有赋值的,后期判断UserID为null,就会返回用户名或密码错误;如果列表不为空,就返回查询列表第一个(get(0)即得到第一个)。
在这里插入图片描述

Servlet编写

AddCourseServlet、EditCourseServlet使用了doPost方法,把数据放到request body中传递参数。
在这里插入图片描述在这里插入图片描述
delCourseServlet类采用doGet方法,获取课程ID并删除。
在这里插入图片描述
在用户业务逻辑控制器中,LoginServlet采用doPost方法,提交数据到服务器。再进入verifyLogin方法判断数据库中是否有该用户数据,如果有就重定向到main.jsp中。
在这里插入图片描述

JSP编写

login.jsp如下所示,采用img上传svg图片,form表单展示用户名和密码,并用input存储用户输入的值。
在这里插入图片描述
在这里插入图片描述
正确登录后我们进入main.jsp中。main.jsp中使用多个container容器装载课程、审批、用户界面,并按照权限展示。权限为2代表学生,系统只显示课程列表和申请记录两个容器;权限为1代表老师,能看到课程列表、课程审批、审批记录三个容器(其实申请记录和审批记录是一个容器,按需求来说这是不应该的。并且如果要展示审批流,这是有待改进的地方);权限为0代表管理员,能看到用户展示容器;以上三者均可以看到退出登录按钮。(用容器替代不同jsp,简化了一些,但真正的审批系统吞吐量大,不可以采用这种方式的)
在这里插入图片描述
以学生身份登录,用户名“zhangsan”,密码“zs”,看到课程列表和申请记录两个容器。
在这里插入图片描述
在这里插入图片描述
以老师身份登录,用户名“lisi”,密码“ls”,看到课程列表、课程审批和审批记录三个容器。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以管理员身份登录,用户名“admin”,密码“admin”,看到用户展示一个容器。在这里插入图片描述
以用户信息容器为例,主要是table表格的运用。
在这里插入图片描述
在这里插入图片描述

TypeScript和CSS

以userlist.ts为例,del1、edit1、add1函数用来响应main.jsp的onclick操作。在这里插入图片描述
以style1.css为例,这个是规定界面颜色和格式。
在这里插入图片描述

最后总结

我觉得这次做的不错的地方就是Global类将数据库连接和关闭整合,减少了代码冗余。并且在里面创建了很多静态变量,方便直接调用。然后就是service调用dao,终于有点层层调用的严密感了。针对本次系统编码实现,最主要的是与数据库的增删改查;但是前端的东西又不能放弃,否则就不是web界面了。但是前后端的配合需要下很大功夫,总体来说做成这样已经超出我的逾期了。慢慢加油吧!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值