29基于java的在线考试系统设计与实现

打印 上一主题 下一主题

主题 966|帖子 966|积分 2898

本章节来介绍一个基于java的在线考试系统的实现
系统概要

近年来,随着世界各国需要参加考核的人员与日俱增,单纯依靠传统的人工安排考场和监考人员的纸质化考试逐渐显示出了效率低,易发生冲突的缺陷,这时,在线考试系统便应运而生,此种考试方式以方便快捷高效等优点将越来越适用于如今的各项考试、考核。此外,无纸化在线考试对考试人员和审阅人员均提供了便捷。因此,本文将主要以JAVA为开发基础,实现一个在线考试系统。
它的用户由学生、教师,管理员和超级管理员组成。学生登陆系统可以进行在线测试和成绩查询。当学生登陆时,系统会随机地为学生选取试题组成考卷。当学生提交考卷后,系统会自动批改客观题,并将试卷提供给教师查看和提醒教师对试卷主观题进行修改。待教师修改完试卷后,系统会自动生成考生成绩和分数段统计信息。学生可以查询自己的成绩信息和试卷,以便更好地了解自己的学习情况。教师也可以通过分数段统计信息更好地了解学生的学生情况。后台管理员可以对考题,考试设置信息,用户信息进行维护。学生,教师,管理员和超级管理员都可以对个人信息进行维护。


  • 基础功能
  • 登录、注册
  • 首页公告栏
  • 操作日志
    ....等等
  • 学生角色
  • 查询考试列表
  • 参加考试
  •   查看错题集
  • 成绩分析
    .....等等
  • 教师角色
  • 审批管理:管理请求绑定自己班级的审批
  • 学生管理:管理自己班级下的所有学生
  •   班级管理:管理自己的班级
  • 考试管理:发布考试(自动生成试卷)、修改考试信息、取消考试
  • 成绩统计
    ....等等
  • 管理员角色
  • 用户管理:管理普通用户(学生、教师角色)
  • 审批管理:管理学生绑定教师某个班级的审批(增、同意/拒绝审批、删、查)
  • 班级管理:管理系统中所有班级
  • 查询成绩、做题记录
  • 题目管理:包括单选、多选、判断
  • 题库管理
  • 公告管理
  • 试卷管理:管理相应试卷(对已结束考试锁定,不可修改)
  • 考试管理:管理考试相关信息
    ....等等
  • 超级管理角色
    拥有全部角色权限,且在此基础上添加功能:
  • 管理员管理:管理管理员角色用户
  •   系统公告管理
  •   系统所有的操作日志留痕
详细功能在下面会介绍到。
系统使用的架构和内容获取

采用B/S的架构实现,整体遵循MVC的设计思想。
  1. > 后端:java,spring,springmvc,mybatis,springboot等
  2. > 数据库:mysql
  3. > 开发工具:idea或者eclipse
  4. > 前端:html,css,javascript,jquery,layui等
  5. > 文件储存:采用的七牛云储存
  6. > 更多内容可查看:http://projecthelp.top
复制代码
项目实现


  • 用户 UserController 的实现
  1. @Controller
  2. @Slf4j
  3. @Api("用户controller")
  4. public class UserController {
  5.     @Autowired
  6.     private UserService userService;
  7.     @Autowired
  8.     private UserClazzService userClazzService;
  9.     @Autowired
  10.     private Kaptcha kaptcha;
  11.     @PostMapping("/login")
  12.     @ResponseBody
  13.     @ApiOperation("登录")
  14.     @OperationLog("登录")
  15.     public ResponseParam login(String username, String password, String code) {
  16.         String msg = "";
  17.         try {
  18.             if (kaptcha.validate(code)){
  19.                 //获取主体对象
  20.                 Subject subject = SecurityUtils.getSubject();
  21.                 subject.login(new UsernamePasswordToken(username, password));
  22.                 log.info("{}登录成功",subject.getPrincipal());
  23.                 return new ResponseParam("登录成功");
  24.             }
  25.         } catch (KaptchaNotFoundException e) {
  26.             msg="验证码已失效!";
  27.         } catch (KaptchaIncorrectException e) {
  28.             msg="验证码错误!";
  29.         } catch (UnknownAccountException e) {
  30.             msg="用户名错误!";
  31.         } catch (IncorrectCredentialsException e) {
  32.             msg="密码错误!";
  33.         } catch (Exception e){
  34.            throw e;
  35.         }
  36.         log.info("{}登录失败,{}",username,msg);
  37.         return ResponseUtil.getErrorResponseParam(msg);
  38.     }
  39.     @GetMapping("logout")
  40.     @ApiOperation("注销")
  41.     @OperationLog("注销")
  42.     public String logout() {
  43.         Subject subject = SecurityUtils.getSubject();
  44.         subject.logout();
  45.         return "login";
  46.     }
  47.     @PostMapping("/register")
  48.     @ResponseBody
  49.     @ApiOperation("注册")
  50.     @OperationLog("注册")
  51.     public ResponseParam registerTeacher(@Validated @RequestBody RequestDataParam<RegisterUserParam> req) throws Exception {
  52.         RegisterUserParam data = req.getData();
  53.         if(ObjectUtil.notEqual(data.getRole(), RoleEnum.STUDENT.getCode()) && ObjectUtil.notEqual(data.getRole(), RoleEnum.TEACHER.getCode())){
  54.             throw new ServiceException("注册失败");
  55.         }
  56.         UserRequestParam user = new UserRequestParam();
  57.         BeanUtil.copyProperties(data, user);
  58.         RequestDataParam<UserRequestParam> param = new RequestDataParam<>();
  59.         param.setData(user);
  60.         return save(param);
  61.     }
  62.     @RequiresUser
  63.     @ResponseBody
  64.     @PostMapping({"/user/information"})
  65.     @ApiOperation("个人信息修改")
  66.     @OperationLog("个人信息修改")
  67.     public ResponseParam information(@Validated @RequestBody RequestDataParam<UserRequestParam> req){
  68.         User user = (User) SecurityUtils.getSubject().getPrincipal();
  69.         UserRequestParam data = req.getData();
  70.         data.setUsername(null);
  71.         data.setRole(null);
  72.         data.setId(user.getId());
  73.         return update(data);
  74.     }
  75.     /*----------------------------------管理员------------------------------*/
  76.     @PostMapping("/user/updateUser/{id}")
  77.     @ResponseBody
  78.     @ApiOperation("用户管理:修改用户")
  79.     @OperationLog("用户管理:修改用户")
  80.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  81.     public ResponseParam updateUser(@PathVariable("id")Long id, @Validated @RequestBody RequestDataParam<UserRequestParam> req) throws Exception {
  82.         Integer role = req.getData().getRole();
  83.         if(!(RoleEnum.STUDENT.getCode().equals(role) || RoleEnum.TEACHER.getCode().equals(role))){
  84.             return ResponseUtil.getErrorResponseParam("您没有权限!");
  85.         }
  86.         req.getData().setId(id);
  87.         return update(req.getData());
  88.     }
  89.     @PostMapping("/user/saveUser")
  90.     @ResponseBody
  91.     @ApiOperation("用户管理:新增用户")
  92.     @OperationLog("用户管理:新增用户")
  93.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  94.     public ResponseParam saveUser(@Validated @RequestBody RequestDataParam<UserRequestParam> req) throws Exception {
  95.         Integer role = req.getData().getRole();
  96.         if(!(RoleEnum.STUDENT.getCode().equals(role) || RoleEnum.TEACHER.getCode().equals(role))){
  97.             return ResponseUtil.getErrorResponseParam("您没有权限!");
  98.         }
  99.         return save(req);
  100.     }
  101.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  102.     @PostMapping("/user/listUserForPage")
  103.     @ResponseBody
  104.     @ApiOperation("用户管理:查询用户")
  105.     @OperationLog("用户管理:查询用户")
  106.     public ResponseParam listUserForPage(@Validated @RequestBody PageRequestParam<UserPageRequestParam> req) throws Exception {
  107.         UserPageRequestParam data = req.getData();
  108.         Page<User> page = new Page<>(req.getPage(),req.getLimit());
  109.         page = userService.listForPage(page,data,false);
  110.         return new ResponseParam(page);
  111.     }
  112.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  113.     @PostMapping("/user/deleteUser/{id}")
  114.     @ResponseBody
  115.     @ApiOperation("用户管理:删除用户")
  116.     @OperationLog("用户管理:删除用户")
  117.     public ResponseParam deleteUser(@PathVariable("id")Long id) {
  118.         User user = userService.getById(id);
  119.         if(ObjectUtil.isNull(user) || !(RoleEnum.STUDENT.getCode().equals(user.getRole()) || RoleEnum.TEACHER.getCode().equals(user.getRole()))){
  120.             return ResponseUtil.getErrorResponseParam("您没有权限!");
  121.         }
  122.         return deleteById(id);
  123.     }
  124.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  125.     @PostMapping("/user/lockUser/{id}")
  126.     @ResponseBody
  127.     @ApiOperation("用户管理:封禁/解封用户")
  128.     @OperationLog("用户管理:封禁/解封用户")
  129.     public ResponseParam lockUser(@PathVariable("id")Long id) {
  130.         User user = userService.getById(id);
  131.         if(ObjectUtil.isNull(user) || !(RoleEnum.STUDENT.getCode().equals(user.getRole()) || RoleEnum.TEACHER.getCode().equals(user.getRole()))){
  132.             return ResponseUtil.getErrorResponseParam("您没有权限!");
  133.         }
  134.         return lockById(id);
  135.     }
  136.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  137.     @GetMapping("/user/listStudent")
  138.     @ResponseBody
  139.     @ApiOperation("用户管理:学生列表")
  140.     @OperationLog("用户管理:学生列表")
  141.     public ResponseParam listStudent() {
  142.         List<User> userList = userService.listUser(RoleEnum.STUDENT.getCode());
  143.         return new ResponseParam(userList);
  144.     }
  145.     @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
  146.     @GetMapping("/user/listTeacher")
  147.     @ResponseBody
  148.     @ApiOperation("用户管理:教师列表")
  149.     @OperationLog("用户管理:教师列表")
  150.     public ResponseParam listTeacher() {
  151.         List<User> userList = userService.listUser(RoleEnum.TEACHER.getCode());
  152.         return new ResponseParam(userList);
  153.     }
  154.     @RequiresRoles(value = "superadmin")
  155.     @PostMapping("/user/deleteAdmin/{id}")
  156.     @ResponseBody
  157.     @ApiOperation("用户管理:删除管理员")
  158.     @OperationLog("用户管理:删除管理员")
  159.     public ResponseParam deleteAdmin(@PathVariable("id")Long id) {
  160.         return deleteById(id);
  161.     }
  162.     @RequiresRoles(value = "superadmin")
  163.     @PostMapping("/user/lockAdmin/{id}")
  164.     @ResponseBody
  165.     @ApiOperation("用户管理:封禁/解封管理员")
  166.     @OperationLog("用户管理:封禁/解封管理员")
  167.     public ResponseParam lockAdmin(@PathVariable("id")Long id) {
  168.         return lockById(id);
  169.     }
  170.     @RequiresRoles(value = "superadmin")
  171.     @PostMapping("/user/listAdminForPage")
  172.     @ResponseBody
  173.     @ApiOperation("用户管理:查询管理员")
  174.     @OperationLog("用户管理:查询管理员")
  175.     public ResponseParam listAdminForPage(@Validated @RequestBody PageRequestParam<UserPageRequestParam> req) {
  176.         UserPageRequestParam data = req.getData();
  177.         Page<User> page = new Page<>(req.getPage(),req.getLimit());
  178.         page = userService.listForPage(page,data,true);
  179.         return new ResponseParam(page);
  180.     }
  181.     @PostMapping("/user/saveAdmin")
  182.     @ResponseBody
  183.     @ApiOperation("用户管理:新增管理员")
  184.     @OperationLog("用户管理:新增管理员")
  185.     @RequiresRoles(value = "superadmin")
  186.     public ResponseParam saveAdmin(@Validated @RequestBody RequestDataParam<UserRequestParam> req) throws Exception {
  187.         return save(req);
  188.     }
  189.     @PostMapping("/user/updateAdmin/{id}")
  190.     @ResponseBody
  191.     @ApiOperation("用户管理:修改管理员")
  192.     @OperationLog("用户管理:修改管理员")
  193.     @RequiresRoles(value = "superadmin")
  194.     public ResponseParam updateAdmin(@PathVariable("id")Long id, @Validated @RequestBody RequestDataParam<UserRequestParam> req) {
  195.         req.getData().setId(id);
  196.         return update(req.getData());
  197.     }
  198.     @RequiresRoles(value = {"teacher","superadmin"}, logical = Logical.OR)
  199.     @PostMapping("/user/listStudentForPage")
  200.     @ResponseBody
  201.     @ApiOperation("用户管理:查询学生")
  202.     @OperationLog("用户管理:查询学生")
  203.     public ResponseParam listStudentForPage(@Validated @RequestBody PageRequestParam<StudentPageRequestParam> req) throws Exception {
  204.         StudentPageRequestParam data = req.getData();
  205.         User user = (User) SecurityUtils.getSubject().getPrincipal();
  206.         UserClazz userClazz = UserClazz.builder().userId(user.getId()).build();
  207.         List<Long> clazzIds = userClazzService.list(userClazz).stream().map(UserClazz::getClazzId).collect(Collectors.toList());
  208.         List<Long> studentIds = userClazzService.listByClazzIds(clazzIds).stream().map(UserClazz::getUserId).collect(Collectors.toList());
  209.         data.setStudentIds(studentIds);
  210.         Page<User> page = new Page<>(req.getPage(),req.getLimit());
  211.         page = userService.listStudentForPage(page,data);
  212.         return new ResponseParam(page);
  213.     }
  214. }
复制代码

  • QiniuUtil七牛云工具类
  1. @Component
  2. @Slf4j
  3. public class QiniuUtil {
  4.     @Value("${oss.qiniu.accessKey}")
  5.     private String accessKey;
  6.     @Value("${oss.qiniu.secretKey}")
  7.     private String secretKey;
  8.     @Value("${oss.qiniu.bucketname}")
  9.     private String bucketname;
  10.     public String upload(MultipartFile file) throws IOException, UploadException {
  11.         if(ObjectUtil.isNull(file)) {
  12.             return "";
  13.         }
  14.         // region2是华南区域
  15.         Configuration cfg = new Configuration(Region.autoRegion());
  16.         UploadManager uploadManager = new UploadManager(cfg);
  17.         // 生成上传凭证,然后准备上传
  18.         Auth auth = Auth.create(accessKey, secretKey);
  19.         // 上传
  20.         Response response;
  21.         String fileName;
  22.         String filType;
  23.         DefaultPutRet putRet = null;
  24.         try {
  25.             String originalFileName = file.getOriginalFilename();
  26.             filType = originalFileName.substring(originalFileName.lastIndexOf("."));
  27.             fileName = StrUtil.concat(true, String.valueOf(DateUtil.currentSeconds()), RandomUtil.randomString(6),filType);
  28.             response = uploadManager.put(file.getBytes(), fileName, auth.uploadToken(bucketname));
  29.             // 解析上传成功的结果
  30.             putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
  31.         } catch (QiniuException e) {
  32.             // 请求失败时打印的异常的信息
  33.             log.warn(StrUtil.concat(true,StrUtil.toString(e.code()),e.response.toString()));
  34.             throw new UploadException("上传七牛云失败");
  35.         }
  36.         return fileName;
  37.     }
  38.     //删除文件 参数:存储的图片文件名
  39.     public void deleteFileFromQiniu(String fileName){
  40.         Configuration cfg = new Configuration(Region.region2());
  41.         String key = fileName;
  42.         Auth auth = Auth.create(accessKey, secretKey);
  43.         BucketManager bucketManager = new BucketManager(auth, cfg);
  44.         try {
  45.             bucketManager.delete(bucketname, key);
  46.         } catch (QiniuException e) {
  47.             //如果遇到异常,说明删除失败
  48.             log.warn(StrUtil.concat(true,StrUtil.toString(e.code()),e.response.toString()));
  49.         }
  50.     }
  51. }
复制代码

  • 成绩导出工具类
  1. @Slf4j
  2. public class ExcelUtil {
  3.     public static void download(HttpServletResponse response,String fileName, Class pojoClass, Collection collection) throws IOException, UploadException {
  4.         try {
  5.             response.setContentType("application/vnd.ms-excel");
  6.             response.setCharacterEncoding("utf-8");
  7.             response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20") + ".xlsx");
  8.             EasyExcel.write(response.getOutputStream(), pojoClass)
  9.                     .autoCloseStream(Boolean.FALSE)
  10.                     .sheet("sheet1")
  11.                     .doWrite(collection);
  12.         } catch (Exception e) {
  13.             log.error("成绩导出失败,文件下载时发生异常",e);
  14.             response.reset();
  15.             response.setContentType("application/json");
  16.             response.setCharacterEncoding("utf-8");
  17.             Map<String, String> map = MapUtils.newHashMap();
  18.             map.put("status", "failure");
  19.             map.put("message", "下载文件失败" + e.getMessage());
  20.             response.getWriter().println(JSONUtil.toJsonStr(map));
  21.         }
  22.     }
  23. }
复制代码
部分功能展示

登录页面


管理员,教师和学生角色统一一个登陆页面,通过登录进去后台判断不同的角色权限,跳转到不同的页面系统。
注册


系统目前可以是学生和老师进行一个注册,然后进入系统,当然如果你的业务是不需要用户进行注册的话,可以把这个注册给删除掉,因为管理员也是可以在后台进行添加用户的。
管理员身份

首页


首页有一个轮播图和系统公告,系统公告管理员可以加入后台进行管理,点击后台入口即可进入管理页面。
管理页面首页


学生和教师用户管理


管理员可以增加和修改用户,包括学生和教师,也可以禁用用户操作。
班级管理


学生申请加入班级


因为开放了学生自己注册的功能,所以学生和教师的关联,可以学生自己通过系统进行申请,当然如果实际情况不是注册的方式的话,管理员可以自己进行关联的,该功能可以灵活去掉。
在线考试管理

考试的一个过程需要在这申明一下:
1.首先先要有一个题库 ;
2.然后管理员或者老师往这个题库里面添加题目
3.创建一份试卷,试卷的产生是通过自己定义题目的个数,然后选择上面创建的题库,进行自动组卷。
4.创建一次考试,需要选择一份试卷,然后选中考试的班级,然后还有开始的时间。
5.到达开始时间后,学生登录系统中进行考试。
6.考试结束后,提交试卷,为防止考试学生提前交卷,然后告诉答案给考场上面正在考试的同学,所以考试结束后才开始系统自动触发批改系统job.
7.学生查看开始分数情况。
题库管理


题目管理


新增加题目:

试卷管理


新增加一份试卷,进行自动组卷:

考试管理


新增加一次考试:

学生成绩管理


还可以导出考试考的成绩列表:

超级管理员角色

具有所有的上面管理员选线,额外再增加以下的功能:
管理所有管理员


系统公告管理


系统操作日志管理


教师身份角色

首页


教师管理端首页


显示最近考试的情况统计。
学生列表


相对于管理员来讲,就只能看到学生用户,而看不到管理员用户角色的,并且不可以增加学生用户。
班级管理


下面具体的教师的权限信息,可以参照右边的导航栏和上面管理员的角色看到教师角色所具有的权限,这里就没必要一一列举了:

学生角色

学生首页


关联教师

因为学生有可能是自己注册进来的,所以需要自己提交申请加入老师的班级:

考试列表


这里展示的是自己关联的老师下的班级下已经创建的考试列表。
参加考试


考试页面


我的成绩


我的错题


成绩分析


个人信息


我的班级


修改登录密码


以上是大部分功能展示,所有的功能都是正常运行,没有bug,导入到idea或者eclipse即可运行,没有套路,具体细节大家下载后自己慢慢研究,欢迎大家一起交流学习

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表