知识问答服务器
功能需求:
1. 实现用户登陆验证(按照用户权限进行划分,主要分为管理员和普通访问者两种权限)
2. 实现普通用户的注册(需要输入用户名和密码)
3. 实现知识问答题库的录入(权限为管理员)
4. 实现知识问答题目的随机选题(从题库中随机选出10题)
5. 普通用户成功登陆后,服务器将发送题目给用户,每回只发一题,用户答完后,服务器立即验证用户的答案是否正确,并将结果发给用户,然后发送下一题的题目。
6. 用户完成所有的题目后服务器将会把用户的最终的得分以及答题的正确率发给用户。
7. 实现服务器日志用于保存用户访问的时间,离开的时间和用户的答题结果。(服务器日志文件由3个文件组成,每个文件有固定大小1M,写满后自动切换写入下一个文件,同时将写满的文件进行归档保存,即保存到压缩文件)
8. 知识问答服务器能够实现多人同时访问。
9. 以上所述的文件均为属性文件(包括题库,用户验证)
10. 日志文件为*.log文件
项目时间:3个工作日
知识考察点:
IO流,多线程,socket通讯,Properties,Map,Set,List,HashMap,HashSet,ArrayList,数组,staitc初始化块 ,final修饰符,Date类,File类,递归,getset器,构造器,方法的重载与覆盖.
启动服务器类:
/**
* 知识问答服务器
*/
public class KnowledgeServer {
private boolean started;
public KnowledgeServer(){
try {
ServerSocket ss = new ServerSocket(5000);
System.out.println("WEPULL知识问答服务器启动!");
started = true;
while(started){
Socket s = ss.accept();
System.out.println(s.getInetAddress()+"用户连接上来!");
new KnowledgeSession(s).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new KnowledgeServer();
}
}
核心类:
public class KnowledgeSession extends Thread {
private static Properties users = new Properties(); //用户属性文件
private static Properties quizs = new Properties(); //题目属性文件
private static Properties admins = new Properties(); //管理员属性文件
//静态初始化块,系统一启动就把这三个属性文件加载到内存中
static{
try {
InputStream is = new FileInputStream("users.properties");
users.load(is);
is.close();
is = new FileInputStream("quizs.properties");
quizs.load(is);
is.close();
is = new FileInputStream("admin.properties");
admins.load(is);
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket s;
private BufferedReader br;
private PrintStream ps;
private String inTime; //用户登录时间
private String outTime; //用户退出时间
private String result; //用户得分结果
private String username; //用户名名
public KnowledgeSession(Socket s) {
this.s = s;
try {
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//log
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日hh时mm分ss秒");
inTime = sdf.format(now); //获得用户登录时间
ps.println(s.getRemoteSocketAddress()+",欢迎您来到知识问答服务器,这是锻炼您头脑的天堂!");
sendMainUI();
}
/**
* 给客户端发送 选择服务 主界面
*/
private void sendMainUI() {
ps.println("********************************");
ps.println("请您选择服务种类:");
ps.println("1.普通用户注册");
ps.println("2.普通用户登录");
ps.println("3.管理员登录");
ps.println("4.退出系统");
ps.println("********************************");
String command = null;
try {
command = br.readLine();
if("1".equalsIgnoreCase(command))
doRegister(); // 1 代表用户注册,调用注册方法
else if("2".equalsIgnoreCase(command))
doLogin(); // 2 代表用户登录,调用登录方法
else if("3".equalsIgnoreCase(command))
doAdminLogin(); // 3 代表管理员登录,调用管理员登录方法
else if("4".equalsIgnoreCase(command)){
ps.println("正在退出·····");
doQuit(); // 4 代表退出系统,调用退出方法
}else{
ps.println("输入有误!请输入对应菜单前面数字!");
sendMainUI();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 退出方法
*/
private void doQuit() {
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日hh时mm分ss秒");
outTime = sdf.format(now);
//将用户登录离开信息写入日志中
MyLogger.output("用户【"+username+"】于"+inTime+
"进入系统,答题分数为:【"+result+"】,于"+outTime+"离开系统!");
if(s!=null&&!s.isClosed()){
try {
ps.println("再见,欢迎下次光临!");
br.close();
ps.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 管理员登录方法,登录成功则录入题目
*/
private void doAdminLogin() {
ps.println("请您输入管理员登陆用户名:");
try {
username = br.readLine();
ps.println("请您输入管理员登陆密码:");
String password = br.readLine();
String realPass = admins.getProperty(username);
if(password.equals(realPass)){
ps.println("恭喜您,管理员成功登录!");
ps.println("******************************");
ps.println("请您仔细录入题库!");
ps.println("******************************");
ps.println();
do{
ps.println("请输入题目:");
String q = br.readLine();
ps.println("请输入答案:");
String a = br.readLine();
OutputStream os = new FileOutputStream("quizs.properties");
quizs.setProperty(q, a);
quizs.store(os, null);
os.close();
ps.println("您还要继续录入吗?[y/n]");
}while("y".equalsIgnoreCase(br.readLine()));
}else{
ps.println("对不起,用户名或密码错误!");
}
ps.println();
sendMainUI(); //重新发送主界面
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 用户登录方法,登录成功即可答题
*/
private void doLogin() {
ps.println("请您输入登陆用户名:");
try {
username = br.readLine();
ps.println("请您输入登陆用户密码:");
String password = br.readLine();
String realPass = users.getProperty(username);
if(password.equals(realPass)){
ps.print("恭喜您,登陆成功,系统马上转入答题环节,请稍候");
for (int i = 0; i < 6; i++) {
ps.print(".");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ps.println();
sendQuizs();
}else{
ps.println("对不起,用户名或密码错误!");
ps.println();
sendMainUI(); //重新发送主界面
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @throws IOException
* 随机出题方法
*/
private void sendQuizs() throws IOException {
/********随机出题实现*****************/
Object[] objs = quizs.keySet().toArray();
Random ran = new Random();
Set<String> set = new HashSet<String>();
while(set.size()<5) {
int index = ran.nextInt(objs.length); //随机出现指定范围内的一个整数
set.add((String) objs[index]);
}
ps.println("***************************");
ps.println("请认真做好答题准备,遵守考场纪律!");
ps.println("***************************");
int count = 0; //题数
int right = 0; //答题正确数
Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
count++;
ps.println("【☆☆返回主菜单请输入QUIT☆☆】 第【"+count+"】题:"+key);
String answer = br.readLine();
if("quit".equalsIgnoreCase(answer)){
break;
}
String rightAnswer = quizs.getProperty(key);
if(answer.equalsIgnoreCase(rightAnswer)){
right++;
ps.println("恭喜您,回答正确!");
}else{
ps.println("对不起,回答错误,正确答案是:【"+rightAnswer+"】!");
}
ps.println();
}
result = right*100/count+"分";
ps.println("答题完毕!本次答题总共【"+count+"】道,您答对【"+right+"】道,正确率为:【"+right*100/count+"%】,得分为【"+right*100/count+"】分!");
sendMainUI();
}
/**
* 用户注册方法
*/
private void doRegister() {
try {
ps.println("请您输入注册用户名:");
String username = br.readLine();
if(users.getProperty(username)==null){
ps.println("请您输入注册用户密码:");
String password = br.readLine();
ps.println("请您再次输入确认用户密码:");
String confirmPass = br.readLine();
if(password.equals(confirmPass)){
//注册成功添加到users属性文件中
users.setProperty(username, password);
OutputStream out = new FileOutputStream("users.properties");
users.store(out, null);
out.close();
ps.println("恭喜您,注册成功!");
ps.println();
sendQuizs(); //调用发题目方法
}else {
ps.println("两次输入密码不匹配!");
sendMainUI();
}
}else {
ps.println("该用户名已经存在!请重新输入!");
doRegister();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}