(这里下面的文档结构由于格式原因,序号标题等产生了一些问题,请见谅)
在拿到老师的项目要求之后,首先确定项目的大体方向,然后根据软件工程的基本思想对该项目进行进一步分析和设计,从而使项目的开发思路更加清晰,项目架构更加合理。
合理确定软件的任务与目标,从需求来看,该系统可分为两个模块(教师端与学生端),下面就这两个模块进行进一步需求分析(老师给出的需求报告说明书是基础的需求,在此基础上进行扩充,由于设计需要,一部分设计思路包含在了需求分析中,严格的需求分析是不包含设计和实现思路的):
教师:
一、教学班导入:
1.将教学班信息一次导入(Excel格式导入即可),按教学班号进行导入(ExcelToDB执行多条insert语句)。
二、发布作业:
1.数据库记录题目方式:一次可发布多个内容即设置多条insert语句对数据库进行题目补充(根据题目数量执行foreach循环即可)。
2.文件记录题目方式:将多个题目记录在文件中(Word、PDF等格式),学生通过文件预览或者下载的方式获取题目信息(在本地服务器上由于不能引用微软等API服务,不支持在线预览,故在本地服务器下,文件预览时,会将Word等文档转换成图片格式,如果将项目部署到阿里或者腾讯等外网可以访问的服务器地址下则可以引用微软的API服务实现真正的Word预览。)
三、教师批阅作业:
1.对每个题目给出评阅意见和成绩,批阅完成后,自动形成该次的评阅成绩和意见。
前端可以采用数据表格格式对每位同学(student_id)的每个答题情况(answer_id)进行打分和给出意见。提交后,后端对表格数据依次插入insert到数据库。
注意事项:
有的题目可能是以文件形式发布的,在数据库题目发布统计表中可能不存在,因此如有必要还可以对数据表规定发布属性(简单题目,文件题目)的信息。
2.对于上传的附件文档,可以直接打开(不用下载),这样方便教师的批阅。
如有必要,可以将文档分为一栏,批阅作业分为一栏(方便批阅)
(对于学生上传的文档加入必要的信息形成唯一的文件名保存到服务器相应位置上)
教师可以统计到目前为止,学生作业完成情况以及相应的成绩与评价。
select*from学生成绩评价表where...;
即可完成查询操作,返回到前端列表中。
学生:
一、学生查阅所布置的作业,并选择题目完成解答并提交(可以上传附件文件):
1.将学生答题信息放入答题卡表中(应设置是否存在附件(方便老师查看附件信息并打分等,这里对于教师端前端可设置附件按钮,如果有附件则返回附件地址并查看,如果没有则不展示)、批阅状态信息以方便查看是否被批阅),方便老师批阅(批阅后应将成绩等信息insert到成绩审批表)。
2.对于上传的文件附件可必要的信息形成唯一的文件名保存到服务器相应位置上。
二、可以查阅教师返回的批阅意见和成绩,若对成绩或评阅有问题,可以返回信息给教师:
select*from学生成绩评价表wherestudent_id=studentId...;
如果可按作业批次查询则可以:
select*from学生成绩评价表wherestudent_id=studentIdandhomeworkcount=count...;
返回给列表并空余一列供学生提出意见或问题,update学生成绩评价表set学生疑问=...;这里只允许修改学生意见或问题列,不应修改成绩等信息(也可以单独列一张表记录学生反馈的信息)。
三、可以列出到目前所作的所有作业情况(包括成绩与评阅信息):
select*from学生提交作业表(发布作业表)wherestudent_id=studentId...;
可将上述两张表结合到一起(注意附件),查看自己的作业情况和成绩评价等情况。
数据库DB——>通过JDBC数据库驱动连接或者c3p0数据库连接池——>dao层——>(传递给service服务层)——>Action控制层——>通过EL表达式或者json数据串等格式返回给前端展示。
一、数据库设计与实现(数据库字典文档):
这里为了实现的简便,简化了数据表数量和数据表单内容(但属性和必要值不缺少,只是在一定程度上简化了关系,重点注意主外键的设计)。
序号
表名
注释/说明
1
publish
发布作业表
2
student
3
submit
提交作业表(包含提交后教师对学生的打分评价情况以及学生查看成绩后的疑问反馈情况)
4
teacher
1、student
列名
数据类型
长度
主键
允许空
列说明
s_id
int
√
学生id(账号)
s_password
varchar
20
密码(最初与id一致)
s_name
学生姓名
s_college
30
学院
5
s_department
系别
6
s_class
教学班号,按int类型进行定义,分为1班、2班等等(此处教学班也应单独设置一张表,然后建立外键对应关系,这里简略处理,不再建表)
7
s_sex
10
性别
8
s_email
邮件,这里为了简便,联系方式统一使用邮件
2、teacher
t_id
教师id(账号)
t_password
t_name
教师姓名
t_college
t_department
t_sex
t_email
3、publish发布作业表
id
每次发布时的题号
content
255
题目内容
requirement
题目要求
publish_count
该次发布题目的次数(第几次作业)
publish_time
datetime
deadline
_time
哪个老师发布的(哪个老师出的题)
(包含提交后教师对学生的打分评价情况以及学生查看成绩后的疑问反馈情况)
学生id(账号)(哪个学生做的该题目)
answer
学生对题目的回答
achievement
老师对学生回答情况进行打分(成绩)
evaluation
老师对学生回答的评价(建议或意见等)
feedback
学生对教师评价后的反馈信息(学生提交后不允许修改回答等表中其他信息,比如成绩等)
外键名
字段
参考模式
参考表
参考字段
删除时
更新时
teacher_id_publish
homework
CASCADE
publish_id_submit
publish_time,id,t_id
student_id_submit
teacher_id_submit
首先将struts2必须的jar包并构建到路径中:
其次将项目中用到的其他jar包构建到项目中(如c3p0数据池管理jar包,commons-fileupload文件上传下载的jar包,jxl实现数据库与Excel互相转换的jar包,mysql数据驱动连接的jar包等等):
org.apache.struts2.dispatcher.ng.filter
.StrutsPrepareAndExecuteFilter
注意必须遵守JavaBean规范,必须要有默认构造函数,注意命名规范。
当时在测试StudentAction与jsp传值时便一直在报null错误,代码静态结构分析也没有观察出有什么错误,而且在在动态分析下发现初始传值部分即为null而不是数据库或者dao层之间的问题,完全可以确定是发生在StudentAction与jsp页面之间的传值错误。修改student实体类的命名规范后发现传值成功。(细节决定成败,一定注意规范。)(不过这也是struts一点非常不好的地方,格式过于死板。在文件上传下载时命名规范更是有着严格的要求。)
引入业务模型对象属性(JavaBean)(private),每次通过get方法获取该JavaBean对象的参数值,注意必要属性一定要有get、set函数。否则获取不到无法进行传值。
例如:
//必要字段属性的get、set方法publicStudentEntitygetStudentEntity(){returnstudentEntity;}publicvoidsetStudentEntity(StudentEntitystudentEntity){this.studentEntity=studentEntity;}publicStringgetRe_password(){returnre_password;}publicvoidsetRe_password(Stringre_password){this.re_password=re_password;}publicStringgetMsg(){returnmsg;}publicvoidsetMsg(Stringmsg){this.msg=msg;}actionname是调用Action方法的名字,class是对应的Action类,method是对应的execute方法。
再次记录一个bug:
该属性指定需要Struts2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。起初要访问的资源不属于action,跳转就出现404,即被struts2拦截掉了。
因此一定要注意配置文件选合适的,配正确的。
例如from数据提交界面,表单中action配置与struts.xml文件中的actionname一一对应。同时在from表单中的属性名name要与业务控制层Action中的属性一一对应。(各组件实现数据共享是通过“Action容器”实现的,所以,在提交页面和从Action实现的跳转页面中所共享的数据,必须与Action属性一样。)
①可以采用JDBC方式对数据库进行访问,这里对于JDBC方式不再赘述。
②c3p0数据池方式:
首先进行c3p0的配置(c3p0.properties文件):
注意时区、字符格式等(很容易出现时区问题)
c3p0.user=rootc3p0.password=123456mjgc3p0.driverClass=com.mysql.cj.jdbc.Driverc3p0.jdbcUrl=jdbc:mysql://localhost:3306/homeworkuseUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaic3p0.initPoolSize=5c3p0.maxPoolSize=10然后在数据库工具类里引用c3p0数据库连接池:
//该类使用C3P0连接池技术实现数据库连接组件packagedb_util;importcom.mchange.v2.c3p0.ComboPooledDataSource;importjavax.sql.DataSource;importjava.sql.*;publicclassJdbcPoolUtils{privatestaticDataSourcedataSource=newComboPooledDataSource();publicstaticConnectiongetConnection()throwsSQLException{returndataSource.getConnection();}......}为了实现技术的练习,分别采用配置文件和注解实现不同的模块,例如在学生模块采用配置文件实现,在教师模块采用注解实现。同时增加了输入验证的内容。
这里不再赘述。
需要同时运行两个项目(端口号不一样)以实现本地服务器在线预览等功能。
选用该开源项目原因:
同时此项目为文件文档在线预览项目解决方案,对标业内付费产品有【永中office】【office365】【idocv】等,在取得公司高层同意后以Apache协议开源出来反哺社区。该项目使用流行的springboot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,Excel,pdf,txt,zip,rar,图片等等。
项目运行简略结构图:
项目引用服务:(运行该开源项目时需要的一系列工作略去):
首页界面:
输入验证失败并返回信息:
进入学生信息管理界面:
修改、删除(移除教学班)学生信息等:
添加学生信息:
注册学生信息:
上述学生信息可实现从Excel表到数据库之间的转换等(从Excel表中导入到数据库、从数据表导出到Excel):
文档的在线预览功能(老师对作业的在线批改功能(不用一一下载)和实现老师发布文档形式的题目以便同学们查看):
这里以老师发布的任务为例:
由于篇幅原因,具体运行界面不再一一赘述。
凑巧的bug(数据表单null测试用例):
因此我们在复用代码时一定要仔细检查逻辑的正确性,注意细节问题。
一、学会查看tomcatlocalhostLog日志文件信息:
二、在前端提交表单访问Action时需要注意是jsp标签还是struts2标签(重点注意路径区别):
jsp标签:
<%
Stringpath=request.getContextPath();
StringbasePath=request.getScheme()+"://"
+request.getServerName()+":"+request.getServerPort()
+path+"/";
%>
struts2标签:
(不用添加基础路径,直接访问相应的
<%@taglibprefix="s"uri="/struts-tags"%>
注意jsp(HTML)标签与struts2标签属性值的区别:
jsp(HTML)标签:
三、注意Action中type类型的取值:
尤其注意type="dispatcher"与type="redirect"、type="redirectAction"的区别:
type="dispatcher"为默认类型,表示转发,上一个界面中的信息不会丢失,可以被获取,而type="redirect"、type="redirectAction"表示重定向到URL或者Action,上一个界面的信息将会丢失。
易产生问题:在EL表达式需要获取值时应采用type="dispatcher",而不是type="redirect"。
type的一些其他取值:
stream:向浏览器发送InputStream对象,通常用于处理文件下载(比如在导出Excel数据时),还可用于Ajax数据。
当然还有chain,用于处理Action链,被跳转的Action中仍能获取上个页面的值如request信息等等。