基于javaweb+mysql的jsp+servlet考试系统(java+jsp+bootstrap+servlet+mysql)
运行环境
Java≥8、MySQL≥5.7、Tomcat≥8
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的JSP+Servlet考试系统(java+jsp+bootstrap+servlet+mysql)
项目介绍
本系统分为两个角色,一个是考生,一个是管理员, 考生功能如下: 登录、选择考试科目、选择考卷、在线考试、提交试卷、并且查询自己的考试成绩
管理员功能如下: 登录、添加试卷、并且添加试卷里的题目、编辑科目、还可以查询所有考生的成绩
环境需要
1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 5.数据库:MySql 5.7版本; 6.是否Maven项目: 否;查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目
技术栈
- 后端:servlet 2. 前端:JSP+bootstrap+jQuery
使用说明
- 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,Eclipse/MyEclipse导入时,若为maven项目请选择maven; 若为maven项目,导入成功后请执行maven clean;maven install命令,然后运行; 3. 将项目中db.properties配置文件中的数据库配置改为自己的配置; 4. 运行项目,在浏览器中输入http://localhost:8080/ 登录
}
package com.mrkj.ygl.servlet3.business;
/**
* The beauty of the code
*
*
*/
public class BusinessMainServlet extends HttpServlet {
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("main");
//返回试卷编辑
if("getMain".equals(action)){
//easyui datagrid组件传递过来的参数page代表当前页,默认1
String pageStr = req.getParameter("page");
//easyui datagrid组件传递过来的参数row代表每页显示多少行,我们设置为10
String rowStr = req.getParameter("rows");
//转换String为Integer,之所以这里不适用int是因为在某些特定情况下参数获取为null,
//使用Integer避免了空指针异常,这是一个有趣的小技巧
}
}
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException
* if an error occurs
*/
@Override
public void init() throws ServletException {
// Put your code here
}
}
package com.mrkj.ygl.servlet3.system;
public class RegisterServlet extends HttpServlet {
/**
* Constructor of the object.
*/
public RegisterServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
@Override
break;
//case 2 这里预期效果是用户每次选择答案都保存在内存当中
case "question":
//case 3 用户关闭了浏览器,会向服务器发送一条数据,这里可做持久化算分处理
case "close":
System.out.println("关闭连接");
onClose();
default:
break;
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
//发生连接异常时
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
//向客户机发送消息,如果计时完毕会向客户机发送一个状态,告诉客户机时间到了,需要提交试卷。
this.session.getBasicRemote().sendText(message);
}
}
package com.mrkj.ygl.servlet3.business;
/**
* The beauty of the code
onClose();
default:
break;
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
//发生连接异常时
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
//向客户机发送消息,如果计时完毕会向客户机发送一个状态,告诉客户机时间到了,需要提交试卷。
this.session.getBasicRemote().sendText(message);
}
}
package com.mrkj.ygl.servlet3.business;
List<Map<String, String>> ksfs = BusinessService.getKsfs(
username, tempPage, row);
Long count = BusinessService.getInfoCount(username);
// 分页
Integer lastPage = 0;
if (count % row > 0) {
lastPage = Integer.parseInt((count / row + 1) + "");
} else {
lastPage = Integer.parseInt((count / row) + "");
}
String HtmlPage = Util.page(page, lastPage);
req.setAttribute("HtmlPage", HtmlPage);
req.setAttribute("ksfs", ksfs);
req.getRequestDispatcher("WEB-INF/view/chaxun.jsp").forward(
req, resp);
} else if ("gocx".equals(action)) {
req.getRequestDispatcher("/actionKfcx.jsp").forward(req, resp);
}else if("aaa".equals(action)){
//拿到考试成绩数据
String pageStr = req.getParameter("page");
String rowStr = req.getParameter("rows");
if (pageStr == null) {
pageStr = "1";
}
if (rowStr == null) {
rowStr = "100";
}
Integer page = Integer.parseInt(pageStr);
Integer row = Integer.parseInt(rowStr);
Integer tempPage = 0;
if (page > 0) {
tempPage = (page - 1) * row;
}
List<Map<String, String>> ksfs =BusinessService.getKsfs(
"admin2", tempPage, row);
Long count = BusinessService.getInfoCount("admin2");
// 分页
if (答案2正确!=null){
check.add(UUID2);
}
if (答案3正确!=null){
check.add(UUID3);
}
if (答案4正确!=null){
check.add(UUID4);
}
//List转换为String[],这里我们使用的是答案编码,答案编码的实现是通过UUID生成字符串,
//转换为char[],把char[]里的每一个元素转换为对应的ascⅡ码,把ascⅡ码相加得出答案编码
Integer 答案编码 = MrksUtils.statistics(check.toArray(new String[check.size()]));
BusinessService.InsertQuestionAndAnswers(问题标题, 问题类型, 分数, 答案编码, 外键, daanMap);
//parent.location.href='question?que=sjbj'
}
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doPut(req, resp);
}
}
package com.mrkj.ygl.socket;
/**
* The beauty of the code
*
*
*/
public class BusinessMainServlet extends HttpServlet {
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("main");
//返回试卷编辑
if("getMain".equals(action)){
//easyui datagrid组件传递过来的参数page代表当前页,默认1
String pageStr = req.getParameter("page");
//easyui datagrid组件传递过来的参数row代表每页显示多少行,我们设置为10
String rowStr = req.getParameter("rows");
//转换String为Integer,之所以这里不适用int是因为在某些特定情况下参数获取为null,
//使用Integer避免了空指针异常,这是一个有趣的小技巧
Integer page = Integer.parseInt(pageStr);
Integer row = Integer.parseInt(rowStr);
//获取总共有多少行数据
Long count = BusinessService.getMainCount();
//计算出page的计算出当前页数从多少航开始,理解这句话,需要了解MySql分页查询语句
if (page > 0){
page = (page-1)*row;
}
//把page与row作为参数传递,最终实现分页查询
List<Map<String, String>> model = BusinessService.getMain(page, row);
String result = null;
public class BusinessMainServlet extends HttpServlet {
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("main");
//返回试卷编辑
if("getMain".equals(action)){
//easyui datagrid组件传递过来的参数page代表当前页,默认1
String pageStr = req.getParameter("page");
//easyui datagrid组件传递过来的参数row代表每页显示多少行,我们设置为10
String rowStr = req.getParameter("rows");
//转换String为Integer,之所以这里不适用int是因为在某些特定情况下参数获取为null,
//使用Integer避免了空指针异常,这是一个有趣的小技巧
Integer page = Integer.parseInt(pageStr);
Integer row = Integer.parseInt(rowStr);
//获取总共有多少行数据
Long count = BusinessService.getMainCount();
//计算出page的计算出当前页数从多少航开始,理解这句话,需要了解MySql分页查询语句
if (page > 0){
page = (page-1)*row;
}
//把page与row作为参数传递,最终实现分页查询
List<Map<String, String>> model = BusinessService.getMain(page, row);
String result = null;
try {
//这里写了一个方法,向前台返回Easyui datagrid组件需要的Json模型
result = MrksUtils.getEasyUIDataGridModel(model, count);
} catch (Exception e) {
e.printStackTrace();
}
//这里写了一个方法,使用response把Json返回给客户端
MrksUtils.responseWriteJson(resp, result);
}else{
req.getRequestDispatcher("WEB-INF/view/main.jsp").forward(req, resp);
}
}
/* (non-Javadoc)
String result = null;
try {
//这里写了一个方法,向前台返回Easyui datagrid组件需要的Json模型
result = MrksUtils.getEasyUIDataGridModel(model, count);
} catch (Exception e) {
e.printStackTrace();
}
//这里写了一个方法,使用response把Json返回给客户端
MrksUtils.responseWriteJson(resp, result);
}
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
String action = req.getParameter("action");
PrintWriter wr=resp.getWriter();
if ("add".equals(action)){ //增加问题
String 问题标题 = req.getParameter(BusinessQuestion.问题标题.toString()); //问题元素
String 问题类型 = req.getParameter(BusinessQuestion.问题类型.toString()); //问题元素
String 分数 = req.getParameter(BusinessQuestion.分数.toString()); //问题元素
String 外键 = req.getParameter(BusinessQuestion.外键.toString()); //问题元素
String 答案1 = req.getParameter("DAAN1"); //答案元素
String 答案2 = req.getParameter("DAAN2"); //答案元素
String 答案3 = req.getParameter("DAAN3"); //答案元素
String 答案4 = req.getParameter("DAAN4"); //答案元素
String 答案1正确 = req.getParameter("DAAN1CHECK"); //计算答案编码
String 答案2正确 = req.getParameter("DAAN2CHECK"); //计算答案编码
String 答案3正确 = req.getParameter("DAAN3CHECK"); //计算答案编码
String 答案4正确 = req.getParameter("DAAN4CHECK"); //计算答案编码
List<String> check = new ArrayList<>();
Map<String,String> daanMap= new HashMap<>();
String UUID1 = UUID.randomUUID().toString();
daanMap.put(UUID1, 答案1);
String UUID2 = UUID.randomUUID().toString();
daanMap.put(UUID2, 答案2);
String UUID3 = UUID.randomUUID().toString();
daanMap.put(UUID3, 答案3);
String UUID4 = UUID.randomUUID().toString();
/**
* The beault of the code
*
*
* 设计思想
*
*1、WebSocket 是在HTML 5支持的通信协议,实现客户端与服务端的长连接。
*
*2、考试时间计算方式是,本地倒计时与服务器端同时计时,这样做考虑到网络延迟因素,不单方面的依赖任何一端的计时。计时终止时试卷提交。
*
*3、客户端每次答题都会与服务器通信,服务器会记录这个答题者的答题记录,记录存在内存当中,并没有持久化,触发持久化条件有以下几种。
*
* A:用户手动提交试卷
* B:用户断开连接
* C:用户关闭网页
*
*4、
*
*
*/
@ServerEndpoint(value = "/mysocket",configurator=BaseContext.class)
public class MySocket {
private static final long serialVersionUID = 79990006013872453L;
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static CopyOnWriteArraySet<MySocket> webSocketSet = new CopyOnWriteArraySet<MySocket>();
public static java.util.concurrent.ConcurrentHashMap<String , String> useronline = new java.util.concurrent.ConcurrentHashMap<String , String>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
private ServletContext context = null;
*
*
*
*/
public class SystemLogin extends HttpServlet{
private static final SystemService 系统服务= new SystemService();
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String, String[]> parmMap = req.getParameterMap();
for (Entry<String, String[]> entry:parmMap.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue()[0]);
}
}
/*
*
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
HttpSession session = req.getSession();
if (session.getAttribute(UserInfo.用户名.toString())!=null){
req.getRequestDispatcher("WEB-INF/view/main.jsp").forward(req, resp);
}else{
resp.sendRedirect("login.jsp?msg=1");
}
}
/* The beauty of the code
*
*
*
*/
@SuppressWarnings("unused")
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String 用户名 = req.getParameter(UserInfo.用户名.toString());
String 密码 = req.getParameter(UserInfo.密码.toString());
Map<String, Object> userInfoMap = 系统服务.selectUserInfoBy用户名(用户名);
if (userInfoMap != null){
String 取出的密码 = (String)userInfoMap.get(UserInfo.密码.toString());
if (密码!=null&&密码.equals(取出的密码)){
req.getSession().setAttribute("userInof", userInfoMap);
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
//发生连接异常时
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
//向客户机发送消息,如果计时完毕会向客户机发送一个状态,告诉客户机时间到了,需要提交试卷。
this.session.getBasicRemote().sendText(message);
}
}
package com.mrkj.ygl.servlet3.business;
/**
* The beauty of the code
*
*
*设计思想
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("que");
//返回试卷编辑
if ("sjbj".equals(action)){
req.setAttribute("AllSubject", BusinessService.getAllSubPage());
req.getRequestDispatcher("/editQuestion.jsp").forward(req, resp);
}else if("getQuestion".equals(action)){
//easyui datagrid组件传递过来的参数page代表当前页,默认1
String pageStr = req.getParameter("page");
//easyui datagrid组件传递过来的参数row代表每页显示多少行,我们设置为10
String rowStr = req.getParameter("rows");
//转换String为Integer,之所以这里不适用int是因为在某些特定情况下参数获取为null,
//使用Integer避免了空指针异常,这是一个有趣的小技巧
Integer page = Integer.parseInt(pageStr);
Integer row = Integer.parseInt(rowStr);
//获取总共有多少行数据
Long count = BusinessService.getQueCount();
//计算出page的计算出当前页数从多少航开始,理解这句话,需要了解MySql分页查询语句
if (page > 0){
page = (page-1)*row;
}
//把page与row作为参数传递,最终实现分页查询
List<Map<String, String>> model = BusinessService.getQuestion(page, row);
String result = null;
try {
//这里写了一个方法,向前台返回Easyui datagrid组件需要的Json模型
result = MrksUtils.getEasyUIDataGridModel(model, count);
} catch (Exception e) {
e.printStackTrace();
}
//这里写了一个方法,使用response把Json返回给客户端
MrksUtils.responseWriteJson(resp, result);
}
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html");
*
*/
@ServerEndpoint(value = "/mysocket",configurator=BaseContext.class)
public class MySocket {
private static final long serialVersionUID = 79990006013872453L;
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static CopyOnWriteArraySet<MySocket> webSocketSet = new CopyOnWriteArraySet<MySocket>();
public static java.util.concurrent.ConcurrentHashMap<String , String> useronline = new java.util.concurrent.ConcurrentHashMap<String , String>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
private ServletContext context = null;
private HttpSession httpSession = null;
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
* @throws IOException
*/
@OnOpen
public void onOpen(Session session,EndpointConfig config) throws IOException{
//WebSocket Session
this.session = session;
webSocketSet.add(this);
//Servlet Application context
context = (ServletContext)config.getUserProperties().get(ServletContext.class.getName());
//Servlet Session
httpSession = (HttpSession)config.getUserProperties().get(HttpSession.class.getName());
//获取Session里的用户信息
Map<String,Object> userInfoMap = (Map<String,Object>)httpSession.getAttribute("userInof");
//把当前用户的的的连接对象存入Context
String 用户名 = (String)userInfoMap.get(UserInfo.用户名.toString());
context.setAttribute(用户名, this);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
break;
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
//发生连接异常时
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
//向客户机发送消息,如果计时完毕会向客户机发送一个状态,告诉客户机时间到了,需要提交试卷。
this.session.getBasicRemote().sendText(message);
}
}
package com.mrkj.ygl.servlet3.business;
/**
* The beauty of the code
*
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
* @throws IOException
*/
@OnOpen
public void onOpen(Session session,EndpointConfig config) throws IOException{
//WebSocket Session
this.session = session;
webSocketSet.add(this);
//Servlet Application context
context = (ServletContext)config.getUserProperties().get(ServletContext.class.getName());
//Servlet Session
httpSession = (HttpSession)config.getUserProperties().get(HttpSession.class.getName());
//获取Session里的用户信息
Map<String,Object> userInfoMap = (Map<String,Object>)httpSession.getAttribute("userInof");
//把当前用户的的的连接对象存入Context
String 用户名 = (String)userInfoMap.get(UserInfo.用户名.toString());
context.setAttribute(用户名, this);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
//断开连接,如果断开连接我们需要把用户答题数据持久化
//1、清除context里的属性对象
//2、理想状态下计算分数
//3、
try {
context.removeAttribute((String)httpSession.getAttribute(UserInfo.用户名.toString()));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
//用户答题时,每次回答一道题都会发送一条信息与服务器通信,这里接收用户发过来的信息。
if (message != null){
switch (message) {
public static String md5(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
str = buf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
public static String TrasformDateToString (Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
if (date != null){
return sdf.format(date);
}else{
return null;
}
}
public static String TrasformGetimeToString (Long date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
if (date != null){
return sdf.format(new Date(date));
}else{
return null;
}
}
}
Map<String, Object> resultMap = new HashMap<String, Object>();
ObjectMapper om = new ObjectMapper();
resultMap.put("rows", model);
resultMap.put("total", count);
return om.writeValueAsString(resultMap);
}
public static void responseWriteJson(HttpServletResponse resp,String result){
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json; charset=utf-8");
try {
resp.getWriter().print(result);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根据 ans_id 获取答案吗
* @param ans_id
* @return
*/
public static int statistics (String ...ans_id){
StringBuffer sb = new StringBuffer("");
for (String id : ans_id){
sb.append(id);
}
char[] cArr = sb.toString().toCharArray();
int result = 0;
for (char c : cArr){
result += c+0;
}
return result;
}
public static String md5(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
*/
public class ActionQuestionServlet extends HttpServlet {
/*
* (non-Javadoc)
*
* @see
* javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest
* , javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
/*
* (non-Javadoc)
*
* @see
* javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest
* , javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String action = req.getParameter("act");
HttpSession session = req.getSession();
if (null != session.getAttribute("userInof")) {
if ("action".equals(action)) {
// 获取完整试卷
String main_id = req.getParameter("main_id");
Map<String, Object> questions = BusinessService
.getAllQuestion(main_id);
req.setAttribute("questions", questions);
session.setAttribute(BusinessMain.答题时间.toString(),
questions.get(BusinessMain.答题时间.toString()));
req.getRequestDispatcher("/WEB-INF/view/kaoshi.jsp").forward(
req, resp);
} else if ("kskm".equals(action)) {
// 获取所有科目
List<Map<String, String>> subjects = BusinessService
.getAllSubPage();
req.setAttribute("subjects", subjects);
context = (ServletContext)config.getUserProperties().get(ServletContext.class.getName());
//Servlet Session
httpSession = (HttpSession)config.getUserProperties().get(HttpSession.class.getName());
//获取Session里的用户信息
Map<String,Object> userInfoMap = (Map<String,Object>)httpSession.getAttribute("userInof");
//把当前用户的的的连接对象存入Context
String 用户名 = (String)userInfoMap.get(UserInfo.用户名.toString());
context.setAttribute(用户名, this);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
//断开连接,如果断开连接我们需要把用户答题数据持久化
//1、清除context里的属性对象
//2、理想状态下计算分数
//3、
try {
context.removeAttribute((String)httpSession.getAttribute(UserInfo.用户名.toString()));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
//用户答题时,每次回答一道题都会发送一条信息与服务器通信,这里接收用户发过来的信息。
if (message != null){
switch (message) {
//case 1 从这步开始考试正式开始。
case "start":
//httpSession中存放了当前试卷的时间
String time = (String)httpSession.getAttribute(BusinessMain.答题时间.toString());
//分钟计算 这里是一个小时,考虑到网络延迟,这里多加了3秒,JS计时正常计算
Long targetMinute = 1000L*60L*Long.parseLong(time);//1000L*60L*60L+3000L;
//获取当前时间,用当前时间+上预期分钟,得到考试结束时间
Date curretn = new Date();
Long target = curretn.getTime()+targetMinute;
//开始考试 ,倒计时开始时,会向客户端发送一个start状态标记,客户端使用js计时也同步开始。
//结束考试,计时结束,会向客户端发送一个end状态吧iaoji,客户端使用js提交表单,完成一次考试。
@Override
public void init() throws ServletException {
// Put your code here
}
}
package com.mrkj.ygl.util;
public class MrksUtils {
public static String getEasyUIDataGridModel(List<Map<String, String>> model,Long count) throws Exception{
Map<String, Object> resultMap = new HashMap<String, Object>();
ObjectMapper om = new ObjectMapper();
resultMap.put("rows", model);
resultMap.put("total", count);
return om.writeValueAsString(resultMap);
}
public static void responseWriteJson(HttpServletResponse resp,String result){
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json; charset=utf-8");
try {
resp.getWriter().print(result);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根据 ans_id 获取答案吗
* @param ans_id
* @return
*/
String action = req.getParameter("main");
//返回试卷编辑
if("getMain".equals(action)){
//easyui datagrid组件传递过来的参数page代表当前页,默认1
String pageStr = req.getParameter("page");
//easyui datagrid组件传递过来的参数row代表每页显示多少行,我们设置为10
String rowStr = req.getParameter("rows");
//转换String为Integer,之所以这里不适用int是因为在某些特定情况下参数获取为null,
//使用Integer避免了空指针异常,这是一个有趣的小技巧
Integer page = Integer.parseInt(pageStr);
Integer row = Integer.parseInt(rowStr);
//获取总共有多少行数据
Long count = BusinessService.getMainCount();
//计算出page的计算出当前页数从多少航开始,理解这句话,需要了解MySql分页查询语句
if (page > 0){
page = (page-1)*row;
}
//把page与row作为参数传递,最终实现分页查询
List<Map<String, String>> model = BusinessService.getMain(page, row);
String result = null;
try {
//这里写了一个方法,向前台返回Easyui datagrid组件需要的Json模型
result = MrksUtils.getEasyUIDataGridModel(model, count);
} catch (Exception e) {
e.printStackTrace();
}
//这里写了一个方法,使用response把Json返回给客户端
MrksUtils.responseWriteJson(resp, result);
}else{
req.getRequestDispatcher("WEB-INF/view/main.jsp").forward(req, resp);
}
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
String action = req.getParameter("action");
if ("add".equals(action)){
String ID = UUID.randomUUID().toString();
String 标题 = req.getParameter(BusinessMain.标题.toString());
String 外键 = req.getParameter(BusinessMain.外键.toString());
@OnOpen
public void onOpen(Session session,EndpointConfig config) throws IOException{
//WebSocket Session
this.session = session;
webSocketSet.add(this);
//Servlet Application context
context = (ServletContext)config.getUserProperties().get(ServletContext.class.getName());
//Servlet Session
httpSession = (HttpSession)config.getUserProperties().get(HttpSession.class.getName());
//获取Session里的用户信息
Map<String,Object> userInfoMap = (Map<String,Object>)httpSession.getAttribute("userInof");
//把当前用户的的的连接对象存入Context
String 用户名 = (String)userInfoMap.get(UserInfo.用户名.toString());
context.setAttribute(用户名, this);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
//断开连接,如果断开连接我们需要把用户答题数据持久化
//1、清除context里的属性对象
//2、理想状态下计算分数
//3、
try {
context.removeAttribute((String)httpSession.getAttribute(UserInfo.用户名.toString()));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
//用户答题时,每次回答一道题都会发送一条信息与服务器通信,这里接收用户发过来的信息。
if (message != null){
switch (message) {
//case 1 从这步开始考试正式开始。
case "start":
//httpSession中存放了当前试卷的时间
String time = (String)httpSession.getAttribute(BusinessMain.答题时间.toString());
//分钟计算 这里是一个小时,考虑到网络延迟,这里多加了3秒,JS计时正常计算
Long targetMinute = 1000L*60L*Long.parseLong(time);//1000L*60L*60L+3000L;
//获取当前时间,用当前时间+上预期分钟,得到考试结束时间
resp.setCharacterEncoding("UTF-8");
String action = req.getParameter("action");
PrintWriter wr=resp.getWriter();
if ("add".equals(action)){ //增加问题
String 问题标题 = req.getParameter(BusinessQuestion.问题标题.toString()); //问题元素
String 问题类型 = req.getParameter(BusinessQuestion.问题类型.toString()); //问题元素
String 分数 = req.getParameter(BusinessQuestion.分数.toString()); //问题元素
String 外键 = req.getParameter(BusinessQuestion.外键.toString()); //问题元素
String 答案1 = req.getParameter("DAAN1"); //答案元素
String 答案2 = req.getParameter("DAAN2"); //答案元素
String 答案3 = req.getParameter("DAAN3"); //答案元素
String 答案4 = req.getParameter("DAAN4"); //答案元素
String 答案1正确 = req.getParameter("DAAN1CHECK"); //计算答案编码
String 答案2正确 = req.getParameter("DAAN2CHECK"); //计算答案编码
String 答案3正确 = req.getParameter("DAAN3CHECK"); //计算答案编码
String 答案4正确 = req.getParameter("DAAN4CHECK"); //计算答案编码
List<String> check = new ArrayList<>();
Map<String,String> daanMap= new HashMap<>();
String UUID1 = UUID.randomUUID().toString();
daanMap.put(UUID1, 答案1);
String UUID2 = UUID.randomUUID().toString();
daanMap.put(UUID2, 答案2);
String UUID3 = UUID.randomUUID().toString();
daanMap.put(UUID3, 答案3);
String UUID4 = UUID.randomUUID().toString();
daanMap.put(UUID4, 答案4);
if (答案1正确!=null){
check.add(UUID1);
}
if (答案2正确!=null){
check.add(UUID2);
}
if (答案3正确!=null){
check.add(UUID3);
}
if (答案4正确!=null){
check.add(UUID4);
}
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
//发生连接异常时
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
//向客户机发送消息,如果计时完毕会向客户机发送一个状态,告诉客户机时间到了,需要提交试卷。
this.session.getBasicRemote().sendText(message);
}
}
package com.mrkj.ygl.servlet3.business;
/**
* The beauty of the code
*
*
*设计思想
*
* 这个类处理考试科目,主要功能有分页,增加,修改,删除
resp.setContentType("application/json; charset=utf-8");
try {
resp.getWriter().print(result);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根据 ans_id 获取答案吗
* @param ans_id
* @return
*/
public static int statistics (String ...ans_id){
StringBuffer sb = new StringBuffer("");
for (String id : ans_id){
sb.append(id);
}
char[] cArr = sb.toString().toCharArray();
int result = 0;
for (char c : cArr){
result += c+0;
}
return result;
}
public static String md5(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)