/laboratory_system

我和一位全栈大佬的本科毕业设计-学院的实验课选课及实验室管理系统

Primary LanguageJavaApache License 2.0Apache-2.0

laboratory_system

我和一位全栈大佬的本科毕业设计-学院的实验课选课及实验室管理系统
前端作者(其实全栈大佬):codingSSnail(1076841285@qq.com)
后端作者:jump-boy(hi_jumpboy@163.com)

项目简介

该项目设计是物电学院实验室选课系统的Web前后端设计,实现同学根据个人时间安排自主选课的功能,同时教师可以根据选课情况,进行 管理,如某个时间段的实验课选课学生人数过少可以另外更改开课时间或者做其他修改,这样为教师和学生都带来很大的便利,同时系统 还需要实现平台化打分,如为每个学生打总成绩时,平台会为教师提供参考成绩以及平时课堂情况,代替以往的手写填表式打分。另外平 台更加的自动化,如随堂打分,系统会自动的根据时间去进行判断,筛选出当前实验课信息以及学生信息。平台在为教师和学生带来便利 的同时,还为管理员提供了更大的权限,查看课程信息,成绩,学生选课情况等,使得管理员在第一时间可以清楚学院的课程管理情况, 同时系统还增加了实验室管理的功能,管理员在拥有更高权限的同时,可以起到更好的管理作用,为学院管理做出贡献。而课题设计正是 为实现这些功能以解决问题,同时保证系统可靠运行而进行的。

系统设计上采用了分层架构的**,前后端之间的通信采用了 Http+JSON 的形式进行数据的交互。前端部分主要以 HTML 和 AngularJS 为核心进行开发,系统通过前端来控制页面间的路由。后端通过 Java 语言的代码编写,原生 Servlet 进行开发。 整个项目搭建在阿里 云上,服务器主机使用 ECS ,Tomcat 做服务器,数据库使用 RDS MySQL 。

  • 项目还是挂在阿里云上,项目链接给各位观爷奉上(PS:因为项目的首页静态资源比较大,而贫穷又限制了我,云主机的带宽只有1M, 所以观爷们首次访问首页会比较慢,请耐心等待。。后续会考虑优化,进行静态文件压缩,或者依赖的一些静态包使用 CDN 加速)
    点击访问项目网站
    账号:123456 密码:123456 请选择 学生 进行登录
    注意:该项目样式暂时只兼容适配火狐浏览器,其他浏览器可能存在显示问题

  • 项目部署
    将项目war包clone到本地后,直接放入tomcat的webapp目录下,然后startup tomcat,最后通过localhost:8080/laboratory_system即可 访问,要想直接不加项目名访问,可配置虚拟映射,参考下文,另外,注意根据自己的情况,请修改scripts目录下的services.js文件中的配置:修改位置如下:

app.factory('netConnector', ['$http',function($http) {
			var server = "http://127.0.0.1:8090";
			var service = {};
			service.get = function(api, params) {
				return $http({
					method: 'GET',
					url: server + api,
					params: params
				});
			};

修改var server值为自己的应用地址。 同时需要配置c3p0-config.xml中的数据库信息,修改为自己的数据库信息:

        <property name="jdbcUrl">jdbc:mysql://localhost:3306/laboratory_system</property>
        <property name="user">root</property>
	<property name="password">root</property>

项目设计以及实现上的几个点
1、后端功能的开发:利用 Session、 ServletContext、 Listener 以及 Filter 等特性来实现同一时刻的单客户端登录限制;通过定时 任务 Quartz 和多线程调用阿里云短信接口来完成定时短信提醒功能;通过 CROS 解决跨域请求问题;
2、基础服务组件工具类的设计:设计 C3P0Util 来完成数据库连接池的功能,通过注册 JSON 转换器来完成时间转换处理,设计 MD5Util 来完成用户密码的加密,设计 ThreadLocal 工具类通过同一线程获取同一连接的思路来保证事务操作的安全;
3、简易算法的设计:通过实现简单算法,来完成系统的自动化计算功能,如年级、当前上课周次的计算等;
4、数据库的设计与开发:分析数据结构来完成相应表的设计,同时设计触发器来完成相应功能的实现,如关联数据的清除;
5、我和前端大佬在接口的协作上是通过 RAP2 来制定接口文档。
RAP2接口文档展示

项目展示

超管权限界面
开学时间展示
角色管理展示
添加课程展示
课程管理展示

项目详述

总体架构设计

本文所研究的系统在设计开发上采用了前后端分离的设计模式,前端部分主要以 HTML 和 AngularJS 为核心进行开发,而后端部分主要以 Java 进行功能开发和 MySQl 做数据库管理。前后端数据交互则采用 Http 协议+ JSON,前后端在开发的同时通过共同维护的接口文档作为参 照规范,接口文档中定义了后端接口和前后端JSON数据格式。系统的总体架构图如下图所示:
总体架构图

  • 后端架构设计
    该课题研究的是系统后端设计,设计语言主要采用 Java 为主,使用 JDK 1.6,API 遵循 Java EE 规范,项目部署在阿里云上,服务器 使用 Tomcat 7.0,数据库使用 RDS MySQL ,负载均衡使用 Nginx+Tomcat 集群来应对高并发,前后端数据交互采用 Http协议+JSON。 为了保证功能逻辑清晰,代码的质量和可重用性,使用了 MVC(Model View Controller)的设计架构模式,M:Model 模型,JavaBean 实体类。V:JSON 数据和 View 视图渲染。C:Controller 控制器,这里指 Servlet 和接口 url。在代码组织结构上使用了分层**,即 表现层(Web层)、业务层和数据访问层。这样分层可以达到强内聚和弱耦合,架构如下图所示:
    后端架构设计图

  • 模块设计
    在进行系统的功能设计时,需要清楚系统的每个功能内容,需要进行模块化分析,将功能分成多个互相独立的模块。在设计过程中,避免 模块之间的冗余,提取出公共的部分进行了设计,包含一些工具类库文件的设计,如数据源连接池、线程池、 MD5 加密以及时间格式转换 器等。最后项目通过 Http 头字段进行控制,解决了资源跨域问题。以下为各模块设计:
    1、登录模块
    用户输入学号和密码,选择登录的角色类型(管理员,教师或学生),点击登录按钮,系统根据输入内容进行校验并进行友好提示。登录 界面中包含重置按钮,用于输入框内容的快速清空。
    技术特点:服务器与数据库进行数据交互,完成信息校验。
    2、主页模块
    用户登录系统后,将显示主页内容。主页用于展示出近期的所有公告,显示公告的标题,用户可以点击查看具体某个公告的详情内容,并 且提供了附件下载,可以下载公告中含有的文件。
    技术特点:服务器从数据库中获取公告内容,前端对其中的附件数据进行解析。
    3、公告模块
    管理员和教师登录系统后,可以进行添加公告操作,以及标题和内容的编写,并且可以进行文件(附件)的上传。
    技术特点:前端对附件进行 BASE64 解析编码处理,服务器再进行数据库存储。
    4、开学时间模块
    管理员登录系统后,系统自动判断是否已经含有开学时间信息,并且提示管理员,若没有,则管理员可以通过日历模板选择日期,输入开 学时间。同时系统具有一定的防误措施,即避免因管理员输入开始时间信息有误而给后续系统功能带来影响,提供了以管理员第一次输入 时的时间为起始,限定开学时间修改期限为24小时,在有效修改时长内,管理员可以反复修改时间,直到最终确认。
    技术特点:数据库通过事件调用特定存储过程实现定期内容清除。
    5、角色管理模块
    通过角色管理进行系统用户的管理,可以展示出所有的系统用户的信息。
    添加角色:管理员可以进行角色的添加,为系统添加新用户。可以单个添加,也可批量添加(通过Excel文件的形式导入)。删除角色: 管理员可以对某个角色进行删除,可用于对旧信息的删除。
    技术特点:可以进行单次数据插入操作或者批量数据插入操作。
    6、课程管理模块
    管理员和教师可以浏览课程,添加课程,修改课程和删除课程等,系统展示可以展示出课程的具体信息,并且还可以查看到选修该课程的 学生信息,这里可以进行适当的干预,从已选学生中移除某个学生,系统还会显示出实时的已选人数。当然,利用角色权限,管理员和教 师的课程管理会有所不同。
    技术特点:通过数据库数据校验,实现添加课程时的冲突检查。
    7、开始选课模块
    学生可以进行课程的选修,根据个人情况去选择上课时间合适的课程。系统会根据课程设定的上限人数去避免选修人数溢出,学生在选修 的同时可以看到实时的已选人数,以供判断。同时,系统可以帮助学生去筛选出符合每个学生的课程,筛选条件有修读学期,专业范围等。


技术特点:通过数据条件筛选,实现自动根据学生专业和年级筛选出适合每个学生的课程。
8、查看课表模块
管理员,教师和学生可以查看课表。系统会根据用户权限,为不同用户展示出不同的课表信息。
技术特点:对数据进行不同的处理,尤其对时间和星期周次的数据进行处理。
9、随堂打分模块
教师可以完成随堂考核。系统会根据当前时间,帮助教师从其课程中筛选出此时正在教授的课程,展示出上课的所有学生信息。教师可以 根据学生的课堂表现,来在课程结束前,为学生打分。
技术特点:通过系统当前时间,计算出当前周次和星期,将周次、星期和时间作为条件从数据库中筛选出符合的课堂信息。
10、成绩管理模块
管理员和教师可以看到学生的平时表现和目前总成绩。同时教师可以为自己每门课程的每个学生打总成绩,系统为教师提供了参考,如展 出了每个学生的请假次数,旷课次数,和参考分数(平时分求平均)等,使得教师所打总成绩及更加准确。系统还提供了按学年分类的功 能,系统会帮助教师筛选出当前年级所带的课程信息,然后教师再进行打分操作,这样避免了信息的复杂以及诸多不便。
技术特点:通过数据库多表查询和一系列的库方法对数据进行均值计算和聚合计算等,将最终数据返回前端,其中数据可以为教师在打成 绩时提供判断。
11、查看成绩模块
管理员,教师和学生可以查看成绩,可以看到所有成绩,并且可以看到某一个成绩的具体明细,这里明细所展示的是该学生该课程的平时 情况,如平时分,上课地点,时间等。学生还可以按学期筛选出每个学期的成绩。
技术特点:多条件的数据库分类查询。
12、个人信息模块
管理员,教师和学生可以进行个人基本资料的修改和查看,包含照片,名字,性别,学历,手机号等,学生还需要填写班级,专业等。
技术特点:通过简易算法实现用学生班级计算出学生当前年级学期信息。
13、修改密码模块
管理员,教师和学生可以进行密码的修改,为了用户账号的安全,需要进行原密码输入,系统进行校验,若有误则无法修改,正确则新密 码修改成功。
技术特点:密码存储使用了摘要算法 MD5 进行加密。
14、短信提醒模块
系统会为每位用户进行实时的短信提醒服务,用户只需要在个人信息中完善自己信息,填写正确的手机号码,系统便会为该用户服务。短 信提醒目前所做到的是,课程提醒,对于学生来说,进行上课提醒,如开课前的一个小时对学生进行一次提醒,避免学生因个人疏忽而忘 记上课。
技术特点:通过阿里云短信平台实现短信发送功能,使用定时任务调度框架Quartz实现定时查询和定时发送功能,在发送功能设计中采用 并发调用短信接口实现同时发送的功能。
下图为整个实验课选课及实验室管理系统的模块设计图:
![系统模块设计图](https://github.com/Jump-Boy/laboratory_system/blob/master/illustration/系统模块设计图.png)

数据库设计及实现

  • 细化表结构及数据库实施
    在细化表结构时,需满足数据库三大范式,并根据概念设计,结合实际功能开发所需,使得数据库性能达到更优,数据表结构更加合 理。
    因为功能设计所需,需要使用到MySQL中的触发器、存储过程和事件。
    创建触发器:
    触发器是MySQL中的一种对象语法,它不是由程序去调用,而是通过一种监听触发的机制实现的,应用适用于需要系统自动执行而非手动执 行,且随时执行的一种场景。所以某些功能需要使用触发器指定的语法格式去创建相应的触发器去实现。如当教师或管理员删除某课程时, 系统将自动删除该课程的相关选修信息,即从选修表中清除选修该课的所有学生。在进行这类功能设计时,需要注意,因为表中存在主外 键关系,所以必须先删除外键信息才能删除主键信息,将触发器执行时间设置为 BEFORE 。
    创建存储过程:
    存储过程是一种 SQL 语句的集合,不同于单条SQL语句的执行,它可以一次性地执行多条 SQL 语句,它需要程序去调用。它可以结合条件 判断,加入逻辑结构,然后再执行相应的 SQL 。
    为了确保管理员每学期开学前输入开学时间,需要定时提醒管理员,该功能的实现需要去查询开学时间表,如果没有时间信息则提醒输入, 若有则不提醒。所以系统需要自动的定期与2月份和8月份删除数据库中的开学时间信息。这里通过 MySQL 事件调用存储过程的方式去实现 该功能。在存储过程中写入 IF 判断,如果开学日期月份等于 2 或 8 则执行删除语句。
    创建事件:
    事件为一种在预定时间执行的 SQL 对象,是一种应用于数据库中的定时任务。
    为了定时调用存储过程来实现开学时间定期提醒功能,这里使用了事件机制,通过创建事件,设定开始执行时间,在时间中调用存储过程 ,只要MySQL服务启动且满足执行要求,就会执行事件。
  • 数据库表结构关系
    通过实际分析,创建了多表关联,多表独立的结构模式。下图为创建所有表后的关系图:
    表结构关系图 图中可以看出大部分数据表之间存在关联,这种关联关系包括一对一,一对多或是多对一。对于一对一的关联,如用户信息表与用户图片 表之间通过 id 实现主外键的一对一关系。对于一对多或者多对一的关系,如学生表与学生图片表、学生选课表、学生成绩表之间通过学 生的学号 id 实现关联。通过关联所要达到的目的就是在满足数据库范式的基础上,使得整个数据系统更加稳健与牢固,并且保证表中每 一条数据记录与另一个表中字段都有很好的参照关系。这种关系会使得数据更加严谨合理。

公共模块详细设计

公共模块指的是所有模块中公共的部分,大多模块设计中有公共的逻辑代码,在这里进行阐述。
因为该系统设计中前后端的衔接采用的是 Http+JSON 的方式。其中数据传输采用的 JSON 传输,数据格式符合标准的 JSON API。而请求 主要有两种方式,GET 和 POST 。对于 POST 请求,因为采用 JSON ,所以 Servlet 不能通过获取参数去解析请求正文,而应该通过请求 获取 IO 流的方式读取。然后将读取到内容转成字符串后再解析成 JSON 格式,最后通过 JSON API 去获取相应的字段值,去执行后续逻 辑代码。对于服务器来说,返回给前端数据也是通过 JSON ,将结果以 JSON 标准格式写入响应中,然后前端页面处理响应。
因为整个项目搭在多个节点上(同一主机只是端口不同),使用 Nginx 进行代理,所以存在着跨域问题(跨域构成的因素),所以需要 解决跨域问题。通过在后端处理,在过滤器中进行设置,设置 Http 响应头字段“Access-Control-Allow-Origin”和 “Access-Control-Allow-Headers”可以解决跨域请求问题,否则浏览器会拦截跨域请求。当然跨域过程中,还存在 cookie 跨域问题, 也就是浏览器会拦截跨域的 cookie ,这样就会导致服务器无法通过 SESSIONID 获取相应的 session ,所以需要解决 cookie 跨域问 题。从两个方面解决,一前端设置每次发送跨域 cookie ,二就是在过滤器中设置响应头“Access-Control-Allow-Credentials”为 “true” 。
对于Dao层的开发来说,最重要的就是其中的SQL语句,它影响着整个业务逻辑的处理速度。同时因为数据库表的结构,往往需要多个表之 间的关系,写出高效且负责的 SQL 语句。下面的各模块将不再阐述每个 SQL 语句的编写,而主要阐述逻辑代码处理的核心**。
因为开发数据库,在业务代码中使用 Java EE 中的 JDBC 进行 SQL 操作,所以存在 Java 的数据类型与数据库中的数据类型相互转换问 题。这里需要严格控制类型,否则在 JDBC 操作时,程序会跑错,或出现数据异常等问题。
在所有模块中为了降低代码的冗余,使用自定义库的方式,自定义了一些工具类,这样只需在需要的地方进行调用即可。下面为具体的工 具类设计:

  • 数据源工具类
    数据源工具类(数据库连接池)使用数据库连接池,目的是解决建立数据库连接导致耗费资源和时间过多的问题,通过连接池提高性能, 从初始化后的池中取出连接,而不是一味的建立连接。 C3P0 为常用的数据源,它提供了很好的连接池封装。需要添加 Jar 包和相应的 配置文件(C3P0-config.xml)。
  • 线程池管理工具类
    因为需要事务管理(事务是 MySQL 的一种特性,是一组操作,要么这组操作都成功,要么都失败,具有隔离级别,可以控制事务,即开 启事务,提交和回滚,这样当数据库操作有误时,就可以利用事务,来保证操作安全),而这里采用了 DBUtils(封装了JDBC的操作), 在使用事务时,需往 QueryRunner.query() 方法中传入 connnection 参数,同一事务中的多条 sql 需保证传入同一 connection 参数, 而 serviceImpl 中写 connection 不太合适,所以将获取 connenction 的过程封装到util包下的该类中,此类时通过 ThreadLocal , 这种控制线程局部变量的方式以保证同一线程获取到同一变量 connection。
  • MD5加密工具类
    为了保证数据库中数据存储的安全性,这里对用户的密码信息进行加密存储,在将密码存储到数据库之前或者密码校验之前,需要先加密。 加密方式采用 MD5 加密( MD5 加密算法即信息摘要算法,它提供了对消息的完整保护,是一种不可逆的加密方式)。所以为了实现密码 加密,便于代码实现,在 util 包下,创建了一个 MD5 加密工具类。
  • JSON 时间格式转换器
    在当管理员点击“角色管理”按钮后,将显示所有角色的账号,姓名、角色类型和创建时间等信息,其中创建时间显示格式为“yyyy-MM-dd HH:mm:ss”。利用 JSON-lib 可以将 Java 对象转成 JSON,但是对于时间的转换,JSON-lib 会把时间转换成并非我们理想的时间格式。 所以需要手动干预转换,一种是在 extjs 中处理,一种是在后端设计中干预,这里该课题采用第二种,JSONConfig 注册时间字段处理器 的方式格式化时间,需要编写时间转换器。

各模块详细设计

对于每个模块的功能开发设计,尽管功能各不相同,但从数据流和逻辑流程来看,都可以分为三大类,一:从数据库读取数据,经过数据 处理,最后将数据返回前端;二:服务器接受前端发送的数据,经过数据处理,最后将数据写入数据库。三:服务器接收到前端发起的请求, 对数据库数据进行删除操作。
对于数据读取类功能,如获取开学时间、展示所有角色、展示所有课程和成绩展示等,这类功能都是前端发起请求,然后服务器接收到请求后, 去调用相应的接口,然后通过 SQL 语句进行数据库查询,对结果集中的数据进行处理,最后将数据以 JSON 格式返回前端页面。只不过每 个功能不同的是,对于数据的具体处理是不一样的。对于获取开学时间功能来说,需要对从数据库中读取出的时间进行时间格式化处理, 才能返回给前端。对于展示所有课程来说,需要将某些字段合并,或者处理,如上课时间。为了逻辑代码的简便实现,该课题设计的数据 库中,对于上课时间分别以开始周次、结束周次、开始时间和结束时间字段存储。为了满足页面上课时间的展示,需要对时间字段合并和 格式化,先对开始时间和结束时间进行格式化,因为存储类型为TIME,所有需要过滤掉秒数,所以通过 TIME_FORMAT(startTime,'%H:%i') 这样的SQL语法进行格式化为“08:00”的显示,然后再进行字段拼接,使用 CONCAT()函数拼接字段值,最终上课时间显示格式为 “1~10周”和“星期一 08:00~10:00”。对于成绩展示来说,需要使用 AVG()函数计算平时成绩的平均分作为参考成绩,还需使用 COUNT()函数计算每个学生的请假次数和旷课次数,对最终的结果集进行封装处理,写入响应,返回前端页面。当然,除过数据处理上的 不同,还存在某些功能需要从服务器缓存中取出 id 或者角色类型,如展示课程信息功能,需要取出 id 值以便数据库查询时做条件筛选。
对于数据写入类功能来说,如添加课程、修改个人信息、设置开学时间等,这类功能都是通过前端将需要写入的数据以请求正文的方式发 送到服务器,servlet 在对数据进行处理,然后将处理后的数据插入到数据库中,最后返回判断标志给前端页面。每个功能不同的地方在于, 数据的处理。对于设置开学时间,需要对时间字符串进行格式转换。对于添加课程,需要对正文中获取的字段值进行分割处理,然后插入 数据库中。
对于删除数据类功能来说,如删除角色、删除课程等,这类功能都是前端将需要删除信息的 id 发送到服务器,数据库通过id进行删除操作。 最后返回前端判断标志,是否删除成功。
对于逻辑流程复杂或者不同的模块,这里进行详细的阐述:

  • 登录模块
    该模块包含登录等相关功能。
    登录:
    当用户在登录页面中输入内容后,服务器从接收到的请求中获取到的账号、密码和角色类型,然后判断角色类型,不同的角色类型,会调 用不同接口,最后执行相应的SQL语句,完成账号和密码的校验,再将校验结果封装 JSON,写入到响应中,返回给前端页面。注意还需要 将账号和角色类型写入 session 中,这样在登录系统成功后,就无需前端每次请求在带上 id 和 userType。
  • 主页公告模块
    公告展示:
    当用户成功登录系统同时,前端会向服务器发送 GET 请求,servlet通过调用相应的接口,执行特定的 select 语句,然后对结果集进行处理, 根据是否有文件名,给判断标志赋值,用于前端下载按钮是否显示的判断依据,最后将公告名、是否有附件判断标志和创建时间封装 JSON, 写入响应中。
    添加公告:
    当用户填写完公告内容后,服务器接收到 POST 请求后,获取公告内容和附件文件,会通过接口调用,进行逻辑处理,执行 insert 语句 ,将公告内容存入数据库中,当然为了减小数据库的压力,附件被存储在服务器上,当然会根据文件的类型进行分类存储(如word文档会 被存储到“/word”下,excel文档会被存储到“/excel”下),同时用附件名、文件类型和上传时间经过简单算法的处理保证每条公告的 附件文件名唯一,然后数据库中只存储附件的文件名,而不存储整个文件,这样会使得性能更优。
    公告详情及附件下载:
    服务器接收到请求后,解析出id,通过调用公告接口,执行方法,进行 select 操作,对结果集中的文件名进行处理,经过简单算法处理, 得到用户上传文件时原本的文件名,然后再封装成指定的 JSON 数据,然后写入响应中,返回给前端。当用户点击附件下载时,前端页面 将该条公告的 id 通过 POST 请求发送到服务器,servlet 得到id后,调用方法从数据库中查询出该附件对应的附件文件名,然后对得到 的处理后的文件名进行处理,得到文件类型和真正的文件名,判断出文件路径,然后通过文件路径传参构造文件字节流,然后通过字节流 读取文件内容到字节数组中,然后将字节数组写入响应中,返回给浏览器。注意,在获取文件字节流之前,需要设置“content-disposition” http头来使得浏览器以下载的方式打开文件。该 http 头字段,是 MIME 协议的扩展。MIME 是一种电子邮件的技术规范。当浏览器接收到 该头时,会激活文件下载提示框,下载框中的有“名称”、“类型”、“打开”和“保存”等,名称会自动填充为头字段中指定的文件名。 采用这种方式下载文件,需要用户选择“保存”还是“打开”等,当点击“保存”时,浏览器会将响应给浏览器的缓存中的文件内容下载。 需要保证用户没有禁止浏览器缓存,否则功能无法正常使用。
  • 开始选课模块
    课程展示:
    前端向服务器发送GET请求,servlet从 session 中得到当前学生的id,然后调用接口方法,执行 select 语句,注意 select 语句通过多 表查询和条件判断,通过修读学期和专业范围与学生的年级和专业匹配,筛选出符合学生的所有课程。专业范围的判断是通过判断学生的 专业字段值是否包含在课程的专业范围值内,即确定一个字符串是否包含在某个字符串中。实现这个功能,通过 SQL 中 LOCATE()函数, 该函数可以返回一个字符串在某个字符串中第一次出现的位置,若不在,则返回0,所以通过 LOCATE(?, majorScope)!=0 进行条件筛选。 同时该 SQL 中还需要使用聚合函数如 COUNT()用来显示出当前该课程已选人数。
    选课:
    前端页面将课程 id 以 POST 请求发送到服务器,servlet 获取当前学生 id 并且从请求正文中获取课程 id,然后调用相应接口,先通过 课程 id 进行 select,查询出该课程的上限人数和已选人数,如果当前已选人数小于上限人数,则执行 insert 操作,在学生选课表中 插入一条记录,最后根据返回值,初始化判断标志写入响应,返回前端判断标志。
  • 随堂打分模块
    随堂信息展示:
    前端页面向服务器发送 GET 请求,servlet 业务逻辑处理,调用接口查询出开学时间,然后根据当前系统时间和开学时间判断出当前周次 和星期,然后调用接口,执行 select 语句,where 条件为当前周次、星期和时间,筛选出符合周次,星期和时间的课程所有已选学生的 信息和平时成绩记录 id,将结果集封装 JSON 写入响应中,返回给前端。(在筛选出课程时,需要初始化平时成绩表,保证表中有每个 学生的记录)注意若角色类型为 manager,则直接返回 failure。
    下图为计算周次和星期的简易算法逻辑: 周次和星期计算的简易算法逻辑 随堂打分:
    前端页面通过 POST 请求,将分数和平时成绩记录 id 发送到服务器,servlet 获取到后,通过判断平时分来初始化请假和旷课参数 (-1代表旷课,0代表请假,正数代表已签到),然后调用接口,执行 insert 语句,将请假、旷课和平时分插入到数据库平时成绩表中。

* 个人信息模块
个人信息展示:
前端页面发送 GET 请求,servlet 从 session 中得到当前用户的 id 和角色类型,判断角色类型,然后调用相应接口,执行 select 语句 ,需要两表联合查询,分别查询出个人信息和图片,最后处理结果集封装 JSON 写入响应。
修改个人信息:
前端通过 POST 请求将修改后的个人信息和通过 BASE64 解析图片后的字符串发送到服务器。servlet 获取到个人信息和图片字符串后, 最后调用接口,将个人信息和图片信息 update 进数据库中(在更新学生提交的个人信息时,还需要根据班级计算出他的当前年级学期), 根据返回值判断操作是否成功,返回判断标志给前端。
下图为当前学期计算的简易算法逻辑:
![学生当前学期计算的简易算法逻辑](https://github.com/Jump-Boy/laboratory_system/blob/master/illustration/学生当前学期计算的简易算法逻辑.png) 注意在个人信息中,用户图片的存储是数据库中存储大量二进制数据,前端将用户上传的图片通过 BASE64 解码,解析成字符串,然后将 字符串传给服务器,数据库中以二进制文本存储,所以 servlet 需要将接收到的字符串转成字节数组,然后构造传参一个 SerialBlob 对象, 最终将该对象插入数据库,当然 JDBC 驱动会将该对象转成字节数组在存入数据库。当需要取出图片信息时,通过JDBC的方法取出二进制数据, 然后传参构造 SerialBlob 对象,然后获取字节数组,最后将字节数组转成字符串,返回给前端,前端在通过 BASE64 编码,转成图片。
* 修改密码模块
修改密码:
前端通过POST请求将原密码和新密码发送服务器,servlet 从 session 中取出用户 id,再通过调用接口,对原密码校验,将 select 出 的密码与用户输入的原密码比较,若正确,再将新密码 insert 进数据库,否则直接返回给前端判断标志 failure。因为为了数据安全, 数据库中密码的存储使用了 MD5 加密,所以在进行密码校验时,也需要将用户输入的原密码进行 MD5 加密,然后再与数据库中密码比较。 * 短信通知模块
短信通知:
系统需要对学生通过短信进行课前提醒。该课题设计方案中短信通知采用的第三方平台服务,如阿里云短信服务。在使用阿里云的短信服 务时,需要根据阿里云的 API ,进行开发,创建账号、访问密钥和申请签名模板等,其中签名和模板为短信内容的一部分。然后添加阿里 的 SDK 依赖包,参照阿里的 API ,调用短信接口,完成发送功能。当然短信发送为系统自行发送,当判断出有学生在一小时后有课程, 则进行短息提醒。所以采用定时任务框架 Quartz ,设置定时任务,每10分钟进行数据库查询,若有符合条件的学生,则列出学生的电话 及课程相关信息,然后进行短信发送。下图为阿里云短信服务的基本使用流程:
![阿里云短信服务使用流程图](https://github.com/Jump-Boy/laboratory_system/blob/master/illustration/阿里云短信服务流程.png) 下图为短信测试控制台打印出的信息
![短信输出](https://github.com/Jump-Boy/laboratory_system/blob/master/illustration/短信测试.png)

配置文件设计

  • 数据源配置
    使用 C3P0 数据源,需要进行参数配置,这些参数包括依赖的驱动 jar 包、 JdbcUrl 、数据库用户名、数据库密码和数据库连接池的相 关参数等。C3P0 配置的方式主要有三种,第一种是 Java 代码中编写,如构造 ComboPooledDataSource 对象,调用域更改器方法去设置 参数。第二种是创建 c3p0.properties 文件,在 properties 文件中去配置参数,然后在 Java 代码中去加载和解析配置文件。第三种 是创建 c3p0-config.xml 文件,在xml中去配置参数,然后构建 ComboPooledDataSource 对象,调用 API 获得连接。该项目设计采用了 第三种方式配置数据源,下表为 c3p0-config.xml 文件的主要配置参数(其中 jdbcUrl 中“…”处为数据库服务器 IP 地址,user 中 “…”为数据库用户名,password中“…”为数据库密码):
    数据源配置参数表
参数节点名 参数节点值
driverClass com.mysql.jdbc.Driver
jdbcUrl jdbc:mysql:// … :3306/mydb1
user
password
initialPoolSize 10
maxIdleTime 30
maxPoolSize 100
minPoolSize 10
maxStatements 200
  • 应用配置
    为了提供给前端接口,需要将后端代码中各 servlet 类进行映射,需要在 web.xml 中配置映射路径。当然在 web.xml 中还需要配置其他 功能所需配置的信息,如禁止 js 脚本修改 cookie 。下表为在 web.xml 的中配置过滤器主要参数:
    过滤器配置参数表
参数节点名 参数节点值
filter-name encodingFilter
filter-class team.hmhlyh.web.filter.EncodingFilter
url-pattern /*

下表为在 web.xml 中配置 session 和 cookie 的主要参数,包含设置 session 的有效时间以及设置禁止应用程序通过 js 操作 cookie:
session和cookie配置参数表

参数节点名 参数节点值
session-timeout 180
http-only true

下表为为所有接口配置映射 url(其中 name 中“…”为 servlet 名称,用于资源与接口匹配,class 中“…”为 servlet 的资源路径, pattern 中“…”为具体接口 url。所有接口配置结构类似,仅文本结点不同):
接口映射配置参数表

参数节点名 参数节点值
servlet-name
servlet-class
url-pattern

在设置项目首页时,将节点名为“welcome-file”的节点值设置成“index.html”。
* 虚拟目录配置
如果集成编译工具如IDEA,直接在Application中配置 / ,可以跳过此步骤,如果手动部署到 WEBAPP 下为了实现当通过 IP+端口号直接访 问到项目资源,需要在 Tomcat 安装路径下的“conf\Catalina\localhost”中创建名为“ROOT.xml”的配置文件,在该 xml 文件中,配置 资源的虚拟路径,对节点名为“Context”的节点值进行设置,docBase 中的值为项目资源的绝对路径。
* 集群配置
为了通过 Nginx 实现 Tomcat 集群,需要在 Nginx 中配置 nginx.conf 文件。下表为主要配置参数(其中 server 中的“…”为项目资 源服务器 IP:端口号,集群的服务器个数与 server 个数等同):
集群配置参数表
参数节点名 参数节点值
server
listen 8080
server-name 127.0.0.1
proxy_pass http://server_lb

Disclaimer
版权归原作者所有,欢迎自由转载-非商用-非衍生-请保持署名和链接。