本章節(jié)來介紹一個基于java的在線考試系統(tǒng)的實現(xiàn)
系統(tǒng)概要
近年來,隨著世界各國需要參加考核的人員與日俱增,單純依靠傳統(tǒng)的人工安排考場和監(jiān)考人員的紙質(zhì)化考試逐漸顯示出了效率低,易發(fā)生沖突的缺陷,這時,在線考試系統(tǒng)便應運而生,此種考試方式以方便快捷高效等優(yōu)點將越來越適用于如今的各項考試、考核。此外,無紙化在線考試對考試人員和審閱人員均提供了便捷。因此,本文將主要以JAVA為開發(fā)基礎,實現(xiàn)一個在線考試系統(tǒng)。
它的用戶由學生、教師,管理員和超級管理員組成。學生登陸系統(tǒng)可以進行在線測試和成績查詢。當學生登陸時,系統(tǒng)會隨機地為學生選取試題組成考卷。當學生提交考卷后,系統(tǒng)會自動批改客觀題,并將試卷提供給教師查看和提醒教師對試卷主觀題進行修改。待教師修改完試卷后,系統(tǒng)會自動生成考生成績和分數(shù)段統(tǒng)計信息。學生可以查詢自己的成績信息和試卷,以便更好地了解自己的學習情況。教師也可以通過分數(shù)段統(tǒng)計信息更好地了解學生的學生情況。后臺管理員可以對考題,考試設置信息,用戶信息進行維護。學生,教師,管理員和超級管理員都可以對個人信息進行維護。
- 基礎功能
- 學生角色
- 教師角色
- 管理員角色
- 超級管理角色
擁有全部角色權限,且在此基礎上添加功能:
詳細功能在下面會介紹到。
系統(tǒng)使用的架構和內(nèi)容獲取
采用B/S的架構實現(xiàn),整體遵循MVC的設計思想。
> 后端:java,spring,springmvc,mybatis,springboot等
> 數(shù)據(jù)庫:mysql
> 開發(fā)工具:idea或者eclipse
> 前端:html,css,javascript,jquery,layui等
> 文件儲存:采用的七牛云儲存
> 更多內(nèi)容可查看:http://projecthelp.top
項目實現(xiàn)
- 用戶
UserController
的實現(xiàn)
@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是華南區(qū)域
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));
// 解析上傳成功的結(jié)果
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;
}
//刪除文件 參數(shù):存儲的圖片文件名
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("成績導出失敗,文件下載時發(fā)生異常",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));
}
}
}
部分功能展示
登錄頁面
管理員,教師和學生角色統(tǒng)一一個登陸頁面,通過登錄進去后臺判斷不同的角色權限,跳轉(zhuǎn)到不同的頁面系統(tǒng)。
注冊
系統(tǒng)目前可以是學生和老師進行一個注冊,然后進入系統(tǒng),當然如果你的業(yè)務是不需要用戶進行注冊的話,可以把這個注冊給刪除掉,因為管理員也是可以在后臺進行添加用戶的。
管理員身份
首頁
首頁有一個輪播圖和系統(tǒng)公告,系統(tǒng)公告管理員可以加入后臺進行管理,點擊后臺入口即可進入管理頁面。
管理頁面首頁
學生和教師用戶管理
管理員可以增加和修改用戶,包括學生和教師,也可以禁用用戶操作。
班級管理
學生申請加入班級
因為開放了學生自己注冊的功能,所以學生和教師的關聯(lián),可以學生自己通過系統(tǒng)進行申請,當然如果實際情況不是注冊的方式的話,管理員可以自己進行關聯(lián)的,該功能可以靈活去掉。
在線考試管理
考試的一個過程需要在這申明一下:
1.首先先要有一個題庫 ;
2.然后管理員或者老師往這個題庫里面添加題目
3.創(chuàng)建一份試卷,試卷的產(chǎn)生是通過自己定義題目的個數(shù),然后選擇上面創(chuàng)建的題庫,進行自動組卷。
4.創(chuàng)建一次考試,需要選擇一份試卷,然后選中考試的班級,然后還有開始的時間。
5.到達開始時間后,學生登錄系統(tǒng)中進行考試。
6.考試結(jié)束后,提交試卷,為防止考試學生提前交卷,然后告訴答案給考場上面正在考試的同學,所以考試結(jié)束后才開始系統(tǒng)自動觸發(fā)批改系統(tǒng)job.
7.學生查看開始分數(shù)情況。
題庫管理
題目管理
新增加題目:
試卷管理
新增加一份試卷,進行自動組卷:
考試管理
新增加一次考試:
學生成績管理
還可以導出考試考的成績列表:
超級管理員角色
具有所有的上面管理員選線,額外再增加以下的功能:
管理所有管理員
系統(tǒng)公告管理
系統(tǒng)操作日志管理
教師身份角色
首頁
教師管理端首頁
顯示最近考試的情況統(tǒng)計。
學生列表
相對于管理員來講,就只能看到學生用戶,而看不到管理員用戶角色的,并且不可以增加學生用戶。
班級管理
下面具體的教師的權限信息,可以參照右邊的導航欄和上面管理員的角色看到教師角色所具有的權限,這里就沒必要一一列舉了:
學生角色
學生首頁
關聯(lián)教師
因為學生有可能是自己注冊進來的,所以需要自己提交申請加入老師的班級:
考試列表
這里展示的是自己關聯(lián)的老師下的班級下已經(jīng)創(chuàng)建的考試列表。
參加考試
考試頁面
我的成績
我的錯題
成績分析
個人信息
我的班級
文章來源:http://www.zghlxwxcb.cn/news/detail-436311.html
修改登錄密碼
以上是大部分功能展示,所有的功能都是正常運行,沒有bug,導入到idea或者eclipse即可運行,沒有套路,具體細節(jié)大家下載后自己慢慢研究,歡迎大家一起交流學習文章來源地址http://www.zghlxwxcb.cn/news/detail-436311.html
到了這里,關于29基于java的在線考試系統(tǒng)設計與實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!