Java实训模拟学生考试系统
第一部分 系统简介
- 此实训使用java语言实现,能够实现学生的注册和登录,以及能够对学生进行考试和对试卷的批改,注册的用户名、密码(密码会通过MD5加密方式加密)和考试成绩等数据会通过redies数据库存储到本地文本文档中。
第二部分 软件准备
-
我使用的是IntelliJ IDEA编译器,这篇文章的范例也都将使用IntelliJ IDEA展示,除此之外还需要redies数据库,我会将涉及到的所有软件打包放到最后。
-
IntelliJ IDEA编译器,可以去浏览器中搜索,下载社区版即可。安装过程可以借鉴其他UP主的文章,这里不再赘述。
-
redies数据库也可以去浏览器中搜索下载最新版本,我使用的不是最新版本,如有需要可以去我打包的文件中寻找。
-
redies数据库详细的使用方法:
1.将redies数据库文件夹放到新建好的文件夹中(推荐全英文路径)
2.将redies数据库启动,WIN+R启动一个运行窗口输入cmd,使用CD命令切换到redies数据库文件所在的位置运行
这里以F盘为例,C盘情况如下:
完成上步之后在最后一行输入如下代码:redis-server redis.windows.conf
选择允许访问即可,看到上图的图形说明redies数据库启动成功,此时不要关闭命令提示框,否则redies数据库将不能使用。运行程序的时候也不能关闭。
第三部分 系统代码
- 主程序 ExamController
package controller;
import java.util.List;
import java.util.Scanner;
import dao.ExamDao;
import model.Paper;
import service.impl.*;
import service.*;
public class ExamController {
public static void main(String[] args) {
String name;
String Key = "secret";
String key;
Integer score ;
boolean flag = false;
boolean flag1 = false;
String[] myAnswers = new String[5];
ExamService examServiceImpl = new ExamServiceImpl();
MultiValueMapImpl mode = new MultiValueMapImpl();
ExamDao account = new ExamDao();
Scanner reader = new Scanner(System.in);
System.out.println("***欢迎进入考试系统***");
//模拟考生登录系统
while(!flag) {
flag1 = false;
System.out.println("*************");
System.out.println("请输入r进行注册");
System.out.println("请输入l进行登录");
System.out.println("请输入q退出系统");
System.out.println("*************");
String k = reader.next();
Scanner readerType;
switch(k.charAt(0)) {
case 'r':
System.out.println("*************");
System.out.println("请注册用户名");
Scanner readerName0 = new Scanner(System.in);
name = readerName0.next();
if ( ExamDao.jedis.get(name+Key) == null){
System.out.println("*************");
System.out.println("请输入密码");
Scanner readerKey0 = new Scanner(System.in);
key = readerKey0.next();
account.saveAccount(name,key);
System.out.println("已完成注册!!!");
while(!flag1) {
System.out.println("*************");
System.out.println("请输入s开始考试");
System.out.println("请输入c查询成绩");
System.out.println("请输入h查询历史成绩");
System.out.println("请输入e返回上级");
System.out.println("*************");
readerType = new Scanner(System.in);
switch (readerType.next().charAt(0)) {
case 's':
System.out.println("考试开始");
List<Paper> paperLists = examServiceImpl.getPaper();
int i = 0;
for (Paper p : paperLists) {
if (i <= 4) {
System.out.println(p.getTitle(i));
System.out.println("*************");
System.out.println("请输入你的选项");
Scanner myAns = new Scanner(System.in);
myAnswers[i] = myAns.next().toUpperCase();
boolean flag3 = false;
if ((myAnswers[i].equalsIgnoreCase("A")) ||(myAnswers[i].equalsIgnoreCase("B")) || (myAnswers[i].toUpperCase().equals("C"))){
//equalsIgnoreCase(String anotherString)将此 String 与另一个 String 进行比较,不考虑大小写。如果两个字符串的长度相等,并且两个字符串中的相应字符都相等(忽略大小写),则认为这两个字符串是相等的。
i++;
}
else{
while (!flag3) {
System.out.println("*************");
System.out.println("请输入A、B、C(或a、b、c)!!!");
System.out.println("*************");
Scanner myAns0 = new Scanner(System.in);
myAnswers[i] = myAns.next().toUpperCase();
if ((myAnswers[i].equalsIgnoreCase("A")) || (myAnswers[i].equalsIgnoreCase("B")) || (myAnswers[i].toUpperCase().equals("C"))) {
i++;
flag3 = true;
}
}
}
}
}
examServiceImpl.check(name, myAnswers, key);
System.out.println("考试结束");
break;
case 'c':
score = examServiceImpl.getScore(name);
if (score < 0) {
System.out.println(name + "未参加考试~");
} else if (score >= 60)
System.out.println(name + "的成绩为:" + score + " 恭喜通过考试~");
else
System.out.println(name + "的成绩为:" + score + " 很遗憾,需要继续努力~");
break;
case 'h':
System.out.println(examServiceImpl.getHistroyScore(name));
break;
case 'e':
flag1 = true;
break;
}
}
}
else{
System.out.println("此用户名已注册请重新注册!!!");
}
break;
case 'l':
System.out.println("请输入用户名");
Scanner readerName1 = new Scanner(System.in);
name = readerName1.next();
if ( ExamDao.jedis.get(name+Key) != null){
System.out.println("*************");
System.out.println("请输入密码");
Scanner readerKey1 = new Scanner(System.in);
key = readerKey1.next();
if (key.equals(ExamDao.jedis.get(name+Key))){
while(!flag1) {
System.out.println("*************");
System.out.println("请输入s开始考试");
System.out.println("请输入c查询成绩");
System.out.println("请输入h查询历史成绩");
System.out.println("请输入e返回上级");
System.out.println("*************");
readerType = new Scanner(System.in);
switch(readerType.next().charAt(0)) {
case 's':
System.out.println("考试开始");
List<Paper> paperLists =examServiceImpl.getPaper();
int i = 0;
for (Paper p : paperLists) {
if (i<=4){
System.out.println(p.getTitle(i));
System.out.println("*************");
System.out.println("请输入你的选项");
Scanner myAns = new Scanner(System.in);
myAnswers[i] = myAns.next().toUpperCase();
boolean flag4 = false;
if ((myAnswers[i].equalsIgnoreCase("A")) ||(myAnswers[i].equalsIgnoreCase("B")) || (myAnswers[i].equalsIgnoreCase("C"))){
//equalsIgnoreCase(String anotherString)将此 String 与另一个 String 进行比较,不考虑大小写。如果两个字符串的长度相等,并且两个字符串中的相应字符都相等(忽略大小写),则认为这两个字符串是相等的。
i++;
}
else{
while (!flag4) {
System.out.println("*************");
System.out.println("请输入A、B、C(或a、b、c)!!!");
System.out.println("*************");
Scanner myAns1 = new Scanner(System.in);
myAnswers[i] = myAns.next().toUpperCase();
if ((myAnswers[i].equalsIgnoreCase("A")) || (myAnswers[i].equalsIgnoreCase("B")) || (myAnswers[i].equalsIgnoreCase("C"))) {
i++;
flag4 = true;
}
}
}
}
}
examServiceImpl.check(name, myAnswers, key);
System.out.println("考试结束");
break;
case 'c':
score = examServiceImpl.getScore(name);
if(score < 0) {
System.out.println(name + "未参加考试~");
}else if(score>=60)
System.out.println(name + "的成绩为:"+ score+" 恭喜通过考试~");
else
System.out.println(name + "的成绩为:"+ score+" 很遗憾,需要继续努力~");
break;
case 'h':
System.out.println(examServiceImpl.getHistroyScore(name));
break;
case 'e':
flag1 = true;
break;
}
}
}
else{
System.out.println("密码不正确!!!");
}
}
else{
System.out.println("该用户名不存在请进行注册!!!");
break;
}
break;
case 'q':
flag = true;
default:
break;
}
}
System.out.println("系统退出");
}
}
- 数据库连接和数据存储 ExamDao
package dao;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import redis.clients.jedis.Jedis;
import service.impl.MultiValueMapImpl;
import service.impl.MakeSecret;
/**
* 数据层
* @author double
*
*/
public class ExamDao {
public static Jedis jedis;
String Score = "score";
private static final String[] ansvers = {
"A", "B", "A", "C", "B"};
MultiValueMapImpl<String, String> stringMultiValueMap = new MultiValueMapImpl<>();
private static String path = "C:\Users\86761\Desktop\JavaText\LocalMemory.txt";
static {
//连接本地的Redis 服务
jedis = new Jedis("localhost");
//如果Redis服务设置了密码;需要下面这行,没有就不需要
//jedis.auth("123456");
System.out.println("连接Redis成功");
//查看服务是否运行
System.out.println("服务正在运行:" + jedis.ping());
}
public String[] getAnswers() {
return ansvers;
}
public List<String> paperPut() {
try {
String encoding = "GBK";
File file = new File("C:\Users\86761\Desktop\JavaText\Text.txt");
String text;
if (file.isFile() && file.exists()) {
// 判断文件是否存在
InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);// 考虑到文件编码问题
BufferedReader bufferedReader = new BufferedReader(read);
List<String> listString = new LinkedList<>();
while (((text = bufferedReader.readLine()) != null)) {
// System.out.println(lineTxt);
listString.add(text);
}
read.close();
return listString;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void saveAccount(String name, String key) {
String Key = "secret";
String account = name + Key;
ExamDao.jedis.set(account, key);
}
public boolean saveScore(String name, String score, String key) {
stringMultiValueMap.add(name, key);
stringMultiValueMap.add(name, score);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = sdf.format(date);
String total = "";
if (jedis.get(name) != null) {
total = jedis.get(name);
}
jedis.set(name, total + score + " " + now + "\r\n");
jedis.set(name+Score,score);
return writer(name, Integer.parseInt(score), path, now, key);
}
public boolean writer(String name, Integer score, String path, String now, String key) {
MakeSecret secretKey = new MakeSecret();
boolean flag = true;
FileWriter fw = null;
try {
fw = new FileWriter(path, true);
fw.write("\r\n" + String.format("%-3s", name) + " " + score + " " + now + " " + secretKey.getResult(key));
//刷新
fw.flush();
} catch (Exception e) {
e.printStackTrace();
flag = false;
} finally {
if (fw != null) {
try {
fw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return flag;
}
public int getName(String name) {
return jedis.get(name+Score)!= null ? Integer.parseInt(jedis.get(name+Score)) : -1;
}
public String getHistoryName(String name) {
return jedis.get(name) != null ? jedis.get(name) : "暂无历史成绩!";
}
}
- 试卷获取 Paper
package model;
import service.impl.ExamServiceImpl;
public class Paper {
private String title;
public Paper(String title) {
this.setTitle(title);
}
public String getTitle(int x) {
int i = 0;
int k;
ExamServiceImpl examService = new ExamServiceImpl();
String[] paperlist = new String[1000];
for (Paper p : examService.getPaper()){
paperlist[i] = p.title;
i++;
}
if (x>=4 & x<5){
for (k = 16; k < 19 ; k++) {
System.out.println(paperlist[k]);
}
return paperlist[k];
}
else if (x == 3) {
for (k = 12; k < 15; k++) {
System.out.println(paperlist[k]);
}
return paperlist[k];
}
else if (x == 2){
for ( k = 8; k < 11 ; k++) {
System.out.println(paperlist[k]);
}
return paperlist[k];
}
else if (x == 1){
for ( k = 4; k <7 ; k++) {
System.out.println(paperlist[k]);
}
return paperlist[k];
}
else if (x == 0) {
for (k = 0; k < 3; k++) {
System.out.println(paperlist[k]);
}
return paperlist[k];
}
else {
return null ;
}
}
public void setTitle(String title) {
this.title = title;
}
}
- 考试服务实现 ExamServiceImpl
package service.impl;
import java.util.LinkedList;
import java.util.List;
import dao.ExamDao;
import model.Paper;
import service.ExamService;
public class ExamServiceImpl implements ExamService{
ExamDao examDao = new ExamDao();
@Override
public List<Paper> getPaper(){
ExamDao examDao = new ExamDao();
List<Paper> listPaper = new LinkedList<>();
for (String textString : examDao.paperPut()){
Paper m = new Paper(textString);
listPaper.add(m);
}
return listPaper;
}
@Override
public boolean check(String name, String[] ans,String key) {
int score=this.answer(ans);
examDao.saveScore(name,""+score,key);
return true;
}
@Override
public int getScore(String name) {
// TODO Auto-generated method stub
return examDao.getName(name);
}
@Override
public String getHistroyScore(String name) {
// TODO 返回及格的历史分数
return examDao.getHistoryName(name) ;
}
@Override
public int answer(String[] ans) {
String[] correctAns=examDao.getAnswers();
int score=0;
for(int i=0;i<correctAns.length;i++){
if(correctAns[i].equals(ans[i])){
score+=20;
}
}
return score;
}
}
- 将密码加密 MakeSecret
package service.impl;
import java.math.BigInteger;
import java.security.MessageDigest;
public class MakeSecret {
public static final String KEY_MD5 = "MD5";
public String getResult(String inputStr)
{
// System.out.println("=======加密前的数据:"+inputStr);
BigInteger bigInteger=null;
try {
MessageDigest md = MessageDigest.getInstance(KEY_MD5);
byte[] inputData = inputStr.getBytes();
md.update(inputData);
bigInteger = new BigInteger(md.digest());
} catch (Exception e) {
e.printStackTrace();}
// System.out.println("MD5加密后:" + bigInteger.toString(16));
return bigInteger.toString(16);
}
}
- 构造一键多值Map的实现 MultiValueMapImpl
package service.impl;
import service.MultiValueMap;
import java.util.*;
/**
* Created in Jan 10, 2016 5:03:17 PM.
*
* @author Yan Zhenjie;
*/
public class MultiValueMapImpl<K, V> implements MultiValueMap<K, V> {
protected Map<K, List<V>> mSource = new LinkedHashMap<K, List<V>>();
public MultiValueMapImpl() {
}
@Override
public void add(K key, V value) {
if (key != null) {
// 如果有这个Key就继续添加Value,没有就创建一个List并添加Value
if (!mSource.containsKey(key))
mSource.put(key, new ArrayList<V>(2));
mSource.get(key).add(value);
}
}
@Override
public void add(K key, List<V> values) {
// 遍历添加进来的List的Value,调用上面的add(K, V)方法添加
for (V value : values) {
add(key, value);
}
}
@Override
public void set(K key, V value) {
// 移除这个Key,添加新的Key-Value
mSource.remove(key);
add(key, value);
}
@Override
public void set(K key, List<V> values) {
// 移除Key,添加List<V>
mSource.remove(key);
add(key, values);
}
@Override
public void set(Map<K, List<V>> map) {
// 移除所有值,便利Map里的所有值添加进来
mSource.clear();
mSource.putAll(map);
}
@Override
public List<V> remove(K key) {
return mSource.remove(key);
}
@Override
public void clear() {
mSource.clear();
}
@Override
public Set<K> keySet() {
return mSource.keySet();
}
@Override
public List<V> values() {
// 创建一个临时List保存所有的Value
List<V> allValues = new ArrayList<V>();
// 便利所有的Key的Value添加到临时List
Set<K> keySet = mSource.keySet();
for (K key : keySet) {
allValues.addAll(mSource.get(key));
}
return allValues;
}
@Override
public List<V> getValues(K key) {
return mSource.get(key);
}
@Override
public V getValue(K key, int index) {
List<V> values = mSource.get(key);
if (values != null && index < values.size())
return values.get(index);
return null;
}
@Override
public int size() {
return mSource.size();
}
@Override
public boolean isEmpty() {
return mSource.isEmpty();
}
@Override
public boolean containsKey(K key) {
return mSource.containsKey(key);
}
}
- 考试服务接口 ExamService
package service;
import java.util.List;
import model.Paper;
public interface ExamService {
List<Paper> getPaper();
boolean check(String name, String[] ans,String key);
int getScore(String name);
String getHistroyScore(String name);
int answer(String[] ans);
}
- 一键多值Map的接口 MultiValueMap
package service;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface MultiValueMap<K, V> {
/**
* 添加Key-Value。
*
* @param key key.
* @param value value.
*/
void add(K key, V value);
/**
* 添加Key-List<Value>。
*
* @param key key.
* @param values values.
*/
void add(K key, List<V> values);
/**
* 设置一个Key-Value,如果这个Key存在就被替换,不存在则被添加。
*
* @param key key.
* @param value values.
*/
void set(K key, V value);
/**
* 设置Key-List<Value>,如果这个Key存在就被替换,不存在则被添加。
* @param key key.
* @param values values.
* @see #set(Object, Object)
*/
void set(K key, List<V> values);
/**
* 替换所有的Key-List<Value>。
*
* @param values values.
*/
void set(Map<K, List<V>> values);
/**
* 移除某一个Key,对应的所有值也将被移除。
*
* @param key key.
* @return value.
*/
List<V> remove(K key);
/**
* 移除所有的值。
* Remove all key-value.
*/
void clear();
/**
* 拿到Key的集合。
* @return Set.
*/
Set<K> keySet();
/**
* 拿到所有的值的集合。
*
* @return List.
*/
List<V> values();
/**
* 拿到某一个Key下的某一个值。
*
* @param key key.
* @param index index value.
* @return The value.
*/
V getValue(K key, int index);
/**
* 拿到某一个Key的所有值。
*
* @param key key.
* @return values.
*/
List<V> getValues(K key);
/**
* 拿到MultiValueMap的大小.
*
* @return size.
*/
int size();
/**
* 判断MultiValueMap是否为null.
*
* @return True: empty, false: not empty.
*/
boolean isEmpty();
/**
* 判断MultiValueMap是否包含某个Key.
*
* @param key key.
* @return True: contain, false: none.
*/
boolean containsKey(K key);
}
- 以上代码的结构如图:
第四部分 具体使用
- 首先在文件夹中创建两个如下图所示的文本文档,内容复制我打包好的里面的即可
- 同时注意这两处文件的地址要相对应
- 都准备好后运行程序,出现这种画面便是进入了系统
进行注册
如果直接开始考试会显示,没有参加考试
共五道题,全部答完后便会显示考试结束,题目和答案可以自己设置
考完可以直接查询成绩
考试成绩等信息会自己保存在本地
查询历史成绩会显示成绩以及作答的具体时间
选择返回上级会直接到最开始的登录界面
如果输入的密码不正确会弹出提示
退出系统程序结束,要想再进入系统需要重新运行程序
- 此程序的不足之处在于考试题目的获取不是很完美,没有完成题目随机获取,以及题目的长度是固定的没有做到可变,希望对此有兴趣的人可以对他进行改良,欢迎大家交流。
- 拓展之处使用了MultiValueMap(一键多值)将用户名作为键,密码和分数作为值,使用了MD5加密方式把用户保存在本地的密码进行了加密。
- 如果遇到jedis报红可以使用IntelliJ IDEA的自动修复修复。
第五部分 网址链接
- 如果想继续了解redies数据库相关知识,可访问下面的网址:
- https://www.runoob.com/redis/redis-install.html
- 链接:https://pan.baidu.com/s/1cqjst0w3Y0IAHyJX1d5h-w
提取码:8096