因为这是一个个人项目,由于我对于js数据处理不了解,所以没有像之前开发项目那样采用前后台分离模式,使用ajax进行数据交互,而是采用了传统的jsp方式,后台将数据传给jsp,jsp中使用jstl标签和el表达式将数据进行呈现。
开发工具为Intellij Idea2018,使用的SSM(Spring,SpringMVC,Mybatis)的框架来搭建项目的服务器后台环境,前台技术主要为css,jsp,简单js。
因为我平时主要是以web后端开发为主,所以本篇博客主要是讲解后台功能实现以及遇到的一些问题。
我将从以下几个角度介绍这篇博客:
1. 功能演示
2. 后台代码分析
3. ssm框架的遇到的一些问题
github源码地址;https://github.com/LeonP3ng/-onlineExam
这是项目上线访问地址:https://rammsteinlp.cn/onlineExam/index.jsp
这是项目包的分层截图,采用的是mvc形式,后台主要有control,service,entity,dao这四个主要的包,以及filter,util其他一些包,
resources主要放资源文件,包括mybatis的xml的文件和spring容器的配置文件,还有jdbc配置文件。
功能主要有用户登录注册,学生参与考试并统计分数,老师对于试题库内容进行增删改查这三大功能。
用户登录模块,
这里我用到了Filter过滤器,从而以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,验证用户是否登录,没有身份就不能访问某些接口。
这里我通过获取session中的student对象,判断对象是否为空,如果为空,则学生没有登录,拒绝访问学生的接口。
*代表通配符,这样访问/student/*这个路径以下的任意请求都会被我们配置的过滤器所拦截,然后执行doFilter函数。
在类名前面指定这个类的路径
同样的,老师身份的接口也配置了filter,进行判断是否登录。
用户登录可选择学生或者老师身份,登录进来后:
学生模块:
登录后,可选择进行考试,后台从数据库随机生成20道题目,
然后在control层中,把生成的题目放在session中,再在jsp中展现题目
学生做完题目后,点击提交。后端会在control层拿到学生提交的选项,再从session中获取subject题目对象,通过get方法拿到题目的答案,和接收的学生选择选项进行比较,如果一致,总分+5,最后把得分返回。
老师模块:
主要为对于题库的操作,对于试题的增删改查等基本简单逻辑,这里我就不多赘述了,只讲一下数据分页吧,
想介绍一下一个工具PageHelper,一个mybatis的分页查询工具,
这是在pom.xml中需要导入的依赖。
com.github.pagehelper
pagehelper
5.0.0
使用的话,只需要从前台传入两个参数pageNum 当前第几页,pageSize 一页多少条数据。先查询所有数据,然后通过startPage这一方法确定当前页面条数信息,再把从数据库从遍历当前表中所有数据。这个pageInfo就是我们想要的分页数据。
@RequestMapping(value="/findStudent")
public String findStudent(@RequestParam(value="pn",defaultValue="1")int pn,HttpSession session) {
int pageSize=10;
pageHelper.startPage(pn, pageSize);
Liststudents=studentDaoImpl.findAllStudent();
PageInfo pageInfo=new PageInfo(students);
session.setAttribute("PageInfo",pageInfo);
return "redirect:findStudent.jsp";
}
之前都是自己手写分页实体类,通过pageNum * pageSize - pageSize 计算得到分页的起始条数,
通过limit语句实现查询我们需要的数据
ps:说一下这个项目遇到的问题
1.jdbc驱动问题,一直500报错,无法获取数据库连接。在排除其他可能错误后,找到了以下问题:
因为我自己的本地用的是mysql版本是8.0,用的是8.0.11的驱动包。
然而在我的服务器上,下载的mysql是5.7的。
在8.0及以上版本中,不仅mysql依赖包需要改成官方将驱动的com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.Driver,所以在不同版本的数据库,连接驱动是不一样的(记得查看自己的mysql,看是哪一个版本的)
还有一点,如果项目上线服务器,在github上传项目时候应该隐去jdbc配置文件,不然你的mysql账号密码可能会被暴露!
2. 在service层中应该使用事务管理注解@Transactional,在企业级应用程序开发中,事务管理必不可少的技术,用来确保数据的完整性和一致性。
3.使用aop进行切面编程。因为这个在线考试系统我实现的功能有限,所以想加一下一些我之前使用过的技术来点缀。
首先我编写了一个自定义注解Anno
然后声明切点,任何被标注为@Anno的注解在方法返回后都会被拦截,执行AfterReturning方法里的操作。
在这个方法里获取访问这个方法的相关信息,然后将日志插入数据库,不过目前还没做访问接口
然后的话我要重点讲下我遇到的关于aop涉及到java动态代理(这是我之前学习java代理模式所做的博客https://mp.csdn.net/postedit/83033240)
我之前都是切在service层,这次我把切点声明在了control层,发现启动项目后发现spring容器没法注入service的对象,所以使用service调用dao层方法了,这时候报了500 Null Pointer空指针异常。
这个问题困扰了我三天,后来才知道spring容器中默认使用jdk动态代理,
之前我aop运行是因为代理模式这一概念,代理时候使用得是service的接口,jdk动态代理是需要一个被代理对象的,这时候service的实现类就是这个代理对象。
这是在service层声明anno注解
而如果在control层使用这个注解的话,因为他在spring中找不到一个被代理对象,自然代理就没法进行,对象为空,报空指针异常。
所以,大家在使用aop的话一定要切在service层。
项目总结:
首先是功能上吧,学习了web开发一年多,大小项目都有接触,虽然老师有作业系统的源码,但我这是第一次做作业系统,想对于作业系统这一业务模块有着更深的了解,不如自己亲手来敲实现这个项目。
然后就是好好地复习了jsp,从去年9月份开始就学习了前后台分离,有了一个靠谱的前台搭档,我的工作大量减轻了,只需要规定好数据格式,以及写好接口文档让前台同学调用,就可以专心处理我的服务器端数据了。完全不用管前台是如何数据呈现给用户。而这次项目是一个个人项目,我只好复习了一遍抛弃了快一年的jsp,使用各种jstl标签对数据处理。
总之,这次项目经验让我收获匪浅!