29基于java的在线考试系统设计与实现
  uBh4vDpCltTp 2023年11月01日 41 0

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

系统概要

近年来,随着世界各国需要参加考核的人员与日俱增,单纯依靠传统的人工安排考场和监考人员的纸质化考试逐渐显示出了效率低,易发生冲突的缺陷,这时,在线考试系统便应运而生,此种考试方式以方便快捷高效等优点将越来越适用于如今的各项考试、考核。此外,无纸化在线考试对考试人员和审阅人员均提供了便捷。因此,本文将主要以JAVA为开发基础,实现一个在线考试系统。

它的用户由学生、教师,管理员和超级管理员组成。学生登陆系统可以进行在线测试和成绩查询。当学生登陆时,系统会随机地为学生选取试题组成考卷。当学生提交考卷后,系统会自动批改客观题,并将试卷提供给教师查看和提醒教师对试卷主观题进行修改。待教师修改完试卷后,系统会自动生成考生成绩和分数段统计信息。学生可以查询自己的成绩信息和试卷,以便更好地了解自己的学习情况。教师也可以通过分数段统计信息更好地了解学生的学生情况。后台管理员可以对考题,考试设置信息,用户信息进行维护。学生,教师,管理员和超级管理员都可以对个人信息进行维护。

  • 基础功能
  • 学生角色
  • 教师角色
  • 管理员角色
  • 超级管理角色
    拥有全部角色权限,且在此基础上添加功能:

详细功能在下面会介绍到。

系统使用的架构和内容获取

采用B/S的架构实现,整体遵循MVC的设计思想。

> 后端:java,spring,springmvc,mybatis,springboot等
> 数据库:mysql
> 开发工具:idea或者eclipse
> 前端:html,css,javascript,jquery,layui等
> 文件储存:采用的七牛云储存
> 更多内容可查看:http://projecthelp.top

项目实现

  • 用户 UserController 的实现
@Controller
@Slf4j
@Api("用户controller")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private UserClazzService userClazzService;
    @Autowired
    private Kaptcha kaptcha;

    @PostMapping("/login")
    @ResponseBody
    @ApiOperation("登录")
    @OperationLog("登录")
    public ResponseParam login(String username, String password, String code) {
        String msg = "";
        try {
            if (kaptcha.validate(code)){
                //获取主体对象
                Subject subject = SecurityUtils.getSubject();
                subject.login(new UsernamePasswordToken(username, password));
                log.info("{}登录成功",subject.getPrincipal());
                return new ResponseParam("登录成功");
            }
        } catch (KaptchaNotFoundException e) {
            msg="验证码已失效!";
        } catch (KaptchaIncorrectException e) {
            msg="验证码错误!";
        } catch (UnknownAccountException e) {
            msg="用户名错误!";
        } catch (IncorrectCredentialsException e) {
            msg="密码错误!";
        } catch (Exception e){
           throw e;
        }
        log.info("{}登录失败,{}",username,msg);
        return ResponseUtil.getErrorResponseParam(msg);
    }

    @GetMapping("logout")
    @ApiOperation("注销")
    @OperationLog("注销")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }

    @PostMapping("/register")
    @ResponseBody
    @ApiOperation("注册")
    @OperationLog("注册")
    public ResponseParam registerTeacher(@Validated @RequestBody RequestDataParam<RegisterUserParam> req) throws Exception {
        RegisterUserParam data = req.getData();
        if(ObjectUtil.notEqual(data.getRole(), RoleEnum.STUDENT.getCode()) && ObjectUtil.notEqual(data.getRole(), RoleEnum.TEACHER.getCode())){
            throw new ServiceException("注册失败");
        }
        UserRequestParam user = new UserRequestParam();
        BeanUtil.copyProperties(data, user);
        RequestDataParam<UserRequestParam> param = new RequestDataParam<>();
        param.setData(user);
        return save(param);
    }

    @RequiresUser
    @ResponseBody
    @PostMapping({"/user/information"})
    @ApiOperation("个人信息修改")
    @OperationLog("个人信息修改")
    public ResponseParam information(@Validated @RequestBody RequestDataParam<UserRequestParam> req){
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        UserRequestParam data = req.getData();
        data.setUsername(null);
        data.setRole(null);
        data.setId(user.getId());
        return update(data);
    }

    /*----------------------------------管理员------------------------------*/

    @PostMapping("/user/updateUser/{id}")
    @ResponseBody
    @ApiOperation("用户管理:修改用户")
    @OperationLog("用户管理:修改用户")
    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    public ResponseParam updateUser(@PathVariable("id")Long id, @Validated @RequestBody RequestDataParam<UserRequestParam> req) throws Exception {
        Integer role = req.getData().getRole();
        if(!(RoleEnum.STUDENT.getCode().equals(role) || RoleEnum.TEACHER.getCode().equals(role))){
            return ResponseUtil.getErrorResponseParam("您没有权限!");
        }
        req.getData().setId(id);
        return update(req.getData());
    }

    @PostMapping("/user/saveUser")
    @ResponseBody
    @ApiOperation("用户管理:新增用户")
    @OperationLog("用户管理:新增用户")
    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    public ResponseParam saveUser(@Validated @RequestBody RequestDataParam<UserRequestParam> req) throws Exception {
        Integer role = req.getData().getRole();
        if(!(RoleEnum.STUDENT.getCode().equals(role) || RoleEnum.TEACHER.getCode().equals(role))){
            return ResponseUtil.getErrorResponseParam("您没有权限!");
        }
        return save(req);
    }

    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    @PostMapping("/user/listUserForPage")
    @ResponseBody
    @ApiOperation("用户管理:查询用户")
    @OperationLog("用户管理:查询用户")
    public ResponseParam listUserForPage(@Validated @RequestBody PageRequestParam<UserPageRequestParam> req) throws Exception {
        UserPageRequestParam data = req.getData();

        Page<User> page = new Page<>(req.getPage(),req.getLimit());
        page = userService.listForPage(page,data,false);

        return new ResponseParam(page);
    }

    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    @PostMapping("/user/deleteUser/{id}")
    @ResponseBody
    @ApiOperation("用户管理:删除用户")
    @OperationLog("用户管理:删除用户")
    public ResponseParam deleteUser(@PathVariable("id")Long id) {
        User user = userService.getById(id);
        if(ObjectUtil.isNull(user) || !(RoleEnum.STUDENT.getCode().equals(user.getRole()) || RoleEnum.TEACHER.getCode().equals(user.getRole()))){
            return ResponseUtil.getErrorResponseParam("您没有权限!");
        }
        return deleteById(id);
    }

    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    @PostMapping("/user/lockUser/{id}")
    @ResponseBody
    @ApiOperation("用户管理:封禁/解封用户")
    @OperationLog("用户管理:封禁/解封用户")
    public ResponseParam lockUser(@PathVariable("id")Long id) {
        User user = userService.getById(id);
        if(ObjectUtil.isNull(user) || !(RoleEnum.STUDENT.getCode().equals(user.getRole()) || RoleEnum.TEACHER.getCode().equals(user.getRole()))){
            return ResponseUtil.getErrorResponseParam("您没有权限!");
        }
        return lockById(id);
    }

    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    @GetMapping("/user/listStudent")
    @ResponseBody
    @ApiOperation("用户管理:学生列表")
    @OperationLog("用户管理:学生列表")
    public ResponseParam listStudent() {
        List<User> userList = userService.listUser(RoleEnum.STUDENT.getCode());
        return new ResponseParam(userList);
    }

    @RequiresRoles(value = {"admin","superadmin"}, logical = Logical.OR)
    @GetMapping("/user/listTeacher")
    @ResponseBody
    @ApiOperation("用户管理:教师列表")
    @OperationLog("用户管理:教师列表")
    public ResponseParam listTeacher() {
        List<User> userList = userService.listUser(RoleEnum.TEACHER.getCode());
        return new ResponseParam(userList);
    }

    @RequiresRoles(value = "superadmin")
    @PostMapping("/user/deleteAdmin/{id}")
    @ResponseBody
    @ApiOperation("用户管理:删除管理员")
    @OperationLog("用户管理:删除管理员")
    public ResponseParam deleteAdmin(@PathVariable("id")Long id) {
        return deleteById(id);
    }

    @RequiresRoles(value = "superadmin")
    @PostMapping("/user/lockAdmin/{id}")
    @ResponseBody
    @ApiOperation("用户管理:封禁/解封管理员")
    @OperationLog("用户管理:封禁/解封管理员")
    public ResponseParam lockAdmin(@PathVariable("id")Long id) {
        return lockById(id);
    }

    @RequiresRoles(value = "superadmin")
    @PostMapping("/user/listAdminForPage")
    @ResponseBody
    @ApiOperation("用户管理:查询管理员")
    @OperationLog("用户管理:查询管理员")
    public ResponseParam listAdminForPage(@Validated @RequestBody PageRequestParam<UserPageRequestParam> req) {
        UserPageRequestParam data = req.getData();

        Page<User> page = new Page<>(req.getPage(),req.getLimit());
        page = userService.listForPage(page,data,true);

        return new ResponseParam(page);
    }

    @PostMapping("/user/saveAdmin")
    @ResponseBody
    @ApiOperation("用户管理:新增管理员")
    @OperationLog("用户管理:新增管理员")
    @RequiresRoles(value = "superadmin")
    public ResponseParam saveAdmin(@Validated @RequestBody RequestDataParam<UserRequestParam> req) throws Exception {
        return save(req);
    }

    @PostMapping("/user/updateAdmin/{id}")
    @ResponseBody
    @ApiOperation("用户管理:修改管理员")
    @OperationLog("用户管理:修改管理员")
    @RequiresRoles(value = "superadmin")
    public ResponseParam updateAdmin(@PathVariable("id")Long id, @Validated @RequestBody RequestDataParam<UserRequestParam> req) {
        req.getData().setId(id);
        return update(req.getData());
    }

    @RequiresRoles(value = {"teacher","superadmin"}, logical = Logical.OR)
    @PostMapping("/user/listStudentForPage")
    @ResponseBody
    @ApiOperation("用户管理:查询学生")
    @OperationLog("用户管理:查询学生")
    public ResponseParam listStudentForPage(@Validated @RequestBody PageRequestParam<StudentPageRequestParam> req) throws Exception {
        StudentPageRequestParam data = req.getData();

        User user = (User) SecurityUtils.getSubject().getPrincipal();
        UserClazz userClazz = UserClazz.builder().userId(user.getId()).build();
        List<Long> clazzIds = userClazzService.list(userClazz).stream().map(UserClazz::getClazzId).collect(Collectors.toList());
        List<Long> studentIds = userClazzService.listByClazzIds(clazzIds).stream().map(UserClazz::getUserId).collect(Collectors.toList());

        data.setStudentIds(studentIds);
        Page<User> page = new Page<>(req.getPage(),req.getLimit());
        page = userService.listStudentForPage(page,data);

        return new ResponseParam(page);
    }
}
  • QiniuUtil七牛云工具类
@Component
@Slf4j
public class QiniuUtil {

    @Value("${oss.qiniu.accessKey}")
    private String accessKey;

    @Value("${oss.qiniu.secretKey}")
    private String secretKey;

    @Value("${oss.qiniu.bucketname}")
    private String bucketname;

    public String upload(MultipartFile file) throws IOException, UploadException {
        if(ObjectUtil.isNull(file)) {
            return "";
        }
        // region2是华南区域
        Configuration cfg = new Configuration(Region.autoRegion());
        UploadManager uploadManager = new UploadManager(cfg);
        // 生成上传凭证,然后准备上传
        Auth auth = Auth.create(accessKey, secretKey);
        // 上传
        Response response;
        String fileName;
        String filType;
        DefaultPutRet putRet = null;
        try {
            String originalFileName = file.getOriginalFilename();
            filType = originalFileName.substring(originalFileName.lastIndexOf("."));
            fileName = StrUtil.concat(true, String.valueOf(DateUtil.currentSeconds()), RandomUtil.randomString(6),filType);
            response = uploadManager.put(file.getBytes(), fileName, auth.uploadToken(bucketname));
            // 解析上传成功的结果
            putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException e) {
            // 请求失败时打印的异常的信息
            log.warn(StrUtil.concat(true,StrUtil.toString(e.code()),e.response.toString()));
            throw new UploadException("上传七牛云失败");
        }
        return fileName;
    }

    //删除文件 参数:存储的图片文件名
    public void deleteFileFromQiniu(String fileName){
        Configuration cfg = new Configuration(Region.region2());
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(bucketname, key);
        } catch (QiniuException e) {
            //如果遇到异常,说明删除失败
            log.warn(StrUtil.concat(true,StrUtil.toString(e.code()),e.response.toString()));
        }
    }
}
  • 成绩导出工具类
@Slf4j
public class ExcelUtil {

    public static void download(HttpServletResponse response,String fileName, Class pojoClass, Collection collection) throws IOException, UploadException {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20") + ".xlsx");
            EasyExcel.write(response.getOutputStream(), pojoClass)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("sheet1")
                    .doWrite(collection);
        } catch (Exception e) {
            log.error("成绩导出失败,文件下载时发生异常",e);
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSONUtil.toJsonStr(map));
        }
    }
}

部分功能展示

登录页面

在这里插入图片描述
管理员,教师和学生角色统一一个登陆页面,通过登录进去后台判断不同的角色权限,跳转到不同的页面系统。

注册

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

管理员身份

首页

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

管理页面首页

在这里插入图片描述

学生和教师用户管理

在这里插入图片描述
管理员可以增加和修改用户,包括学生和教师,也可以禁用用户操作。

班级管理

在这里插入图片描述

学生申请加入班级

在这里插入图片描述

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

在线考试管理

考试的一个过程需要在这申明一下:

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

题库管理

在这里插入图片描述

题目管理

在这里插入图片描述
新增加题目:
在这里插入图片描述

试卷管理

在这里插入图片描述
新增加一份试卷,进行自动组卷:
在这里插入图片描述

考试管理

在这里插入图片描述
新增加一次考试:
在这里插入图片描述

学生成绩管理

在这里插入图片描述
还可以导出考试考的成绩列表:
在这里插入图片描述

超级管理员角色

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

管理所有管理员

在这里插入图片描述

系统公告管理

在这里插入图片描述

系统操作日志管理

在这里插入图片描述

教师身份角色

首页

在这里插入图片描述

教师管理端首页

在这里插入图片描述
显示最近考试的情况统计。

学生列表

在这里插入图片描述
相对于管理员来讲,就只能看到学生用户,而看不到管理员用户角色的,并且不可以增加学生用户。

班级管理

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

学生角色

学生首页

在这里插入图片描述

关联教师

因为学生有可能是自己注册进来的,所以需要自己提交申请加入老师的班级:
在这里插入图片描述

考试列表

在这里插入图片描述
这里展示的是自己关联的老师下的班级下已经创建的考试列表。

参加考试

在这里插入图片描述

考试页面

在这里插入图片描述

我的成绩

在这里插入图片描述

我的错题

在这里插入图片描述

成绩分析

在这里插入图片描述

个人信息

在这里插入图片描述

我的班级

在这里插入图片描述

修改登录密码

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

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   55   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   111   0   0 Java
  8s1LUHPryisj   2024年05月17日   47   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
uBh4vDpCltTp