web综合案例
1.登录功能
1.1 登录功能
(1)MemberServlet
中添加login方法
public Result login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Member member = getData(request,Member.class);
member = memberService.login(member.getEmail(),member.getPassword());
if(member != null){
return new Result("登录成功!", member);
}else{
return new Result("用户名密码错误,请重试!", false, null, Code.LOGIN_FAIL);
}
}
(2)Code
中添加 常量
public static final Integer LOGIN_FAIL = 50101;
(3)补全service和impl和dao、xml代码
MemberService
/**
* 根据email和密码登录
* @param email
* @param password
* @return
*/
Member login(String email, String password);
MemberServiceImpl
@Override
public Member login(String email, String password) {
SqlSession sqlSession = null;
try{
//1.获取SqlSession
sqlSession = MapperFactory.getSqlSession();
//2.获取Dao
MemberDao memberDao = MapperFactory.getMapper(sqlSession, MemberDao.class);
password = MD5Util.md5(password);
Member member = memberDao.findByEmailAndPwd(email,password);
return member;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
//记录日志
}finally {
try {
TransactionUtil.close(sqlSession);
}catch (Exception e){
e.printStackTrace();
}
}
}
MemberDao
Member findByEmailAndPwd(@Param("email") String email,@Param("password") String password);
MemberDao.xml
<!--配置查询的列名公共SQL语句-->
<sql id="Base_Column_List">id,nick_name,password,gender,birthday,email,telephone,address,register_date,state </sql>
<select id="findByEmailAndPwd" parameterType="map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from tr_memberwhere email = #{email,jdbcType=VARCHAR} and password = #{password,jdbcType=VARCHAR}
</select>
(4)修改login.html
,添加164行左右
//根据返回的结果进行下一步的动作
if( res.flag){
// 跳转页面 index.html
window.open("index.html","_self");
}else{
alert(res.message);
}
启动服务器,访问页面,进行登录
1.2 将登陆信息保存到redis中
(1)将资料中工程资源文件
中的JedisUtils
拷贝工程目录下。
(2)将资料中工程资源文件
中的jedis.properties
拷贝到resources下
(3)将登录用户id信息放入到redis是,修改``login 方法,添加如下代码
代码语言:javascript复制@Override
public Member login(String email, String password) {
SqlSession sqlSession = null;
try{
//1.获取SqlSession
sqlSession = MapperFactory.getSqlSession();
//2.获取Dao
MemberDao memberDao = MapperFactory.getMapper(sqlSession, MemberDao.class);
password = MD5Util.md5(password);
Member member = memberDao.findByEmailAndPwd(email,password);
//3.将登录人的信息保存到redis中
Jedis jedis = JedisUtils.getResource();
//使用登录人的id作为key,设定3600秒的过期时间,value值待定
jedis.setex(member.getId(),3600,"");
jedis.close();
return member;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
//记录日志
}finally {
try {
TransactionUtil.close(sqlSession);
}catch (Exception e){
e.printStackTrace();
}
}
}
启动redis服务器。
启动项目服务进行测试
1.3 登陆状态校验
(1)在MemberServlet
中添加方法checkLogin
方法,用于判断登录用户的id是否存在redis中
public Result checkLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Member member = getData(request,Member.class);
//根据获取到的id去redis中查找,是否存在
String nickName = memberService.getLoginInfo(member.getId());
return new Result("", nickName);
}
(2)修改index.html
中checkLogin()方法
checkLogin() {
//判断当前用户是否登录了,判断现在是否有登录人的信息
/* 状态1:未登录
document.querySelector("#register").style.display = 'block';
document.querySelector("#login").style.display = 'block';
document.querySelector("#myexam").style.display = 'none';
document.querySelector("#exam").style.display = 'none';
document.querySelector("#exit").style.display = 'none';
document.querySelector("#nickname").style.display = 'none';
*/
/* 状态2:已登录
document.querySelector("#register").style.display = 'none';
document.querySelector("#login").style.display = 'none';
document.querySelector("#myexam").style.display = 'block';
document.querySelector("#exam").style.display = 'block';
document.querySelector("#exit").style.display = 'block';
document.querySelector("#nickname").style.display = 'block';
*/
let _this = this;
//从localStorage中获取数据,获取当前保存的用户名,再根据用户名获取后台是否登录的状态
if(!window.localStorage){
alert("浏览器不支持localStorage,请升级浏览器")
}else {
//获取localStorage对象
let storage = window.localStorage;
alert("id:" storage.id);
//测试是否有登录数据,id
if(storage.id == undefined){
//如果本地没有用户信息,显示登陆和注册按钮
document.querySelector("#register").style.display = 'block';
document.querySelector("#login").style.display = 'block';
document.querySelector("#myexam").style.display = 'none';
document.querySelector("#exam").style.display = 'none';
document.querySelector("#exit").style.display = 'none';
document.querySelector("#nickname").style.display = 'none';
}else {
//如果本地存在用户信息,需要确认服务器是否存在当前用户登录信息(redis中)
//发送请求,根据当前id去服务器中查找对应的数据
axios.post('/member/checkLogin', '{"id":"' storage.id '"}').then(function (response) {
//alert(response.data.data)
//获取响应数据
let res = response.data;
//alert("redis服务器中存储的用户名信息 : " res.data)
//判定本地用户对应是否处于登录状态,处于登录状态的用户具有用户名信息
if(res.data == undefined){
//如果没有用户名信息,当前用户未登录,显示登陆与注册按钮
document.querySelector("#register").style.display = 'block';
document.querySelector("#login").style.display = 'block';
document.querySelector("#myexam").style.display = 'none';
document.querySelector("#exam").style.display = 'none';
document.querySelector("#exit").style.display = 'none';
document.querySelector("#nickname").style.display = 'none';
}else{
//如果具有用户名信息,显示用户答题相关按钮
//设置vue对象nickname属性值
_this.nickname = res.data;
document.querySelector("#register").style.display = 'none';
document.querySelector("#login").style.display = 'none';
document.querySelector("#myexam").style.display = 'block';
document.querySelector("#exam").style.display = 'block';
document.querySelector("#exit").style.display = 'block';
//显示当前登录用户对应的登录信息组件
document.querySelector("#nickname").style.display = 'block';
}
}).catch(function (err) {
console.log(err)
});
}
}
},
(3)显示登录昵称
MemberService
接口中添加方法 getLoginInfo
/**
* 根据登录人id获取对应的昵称,从redis中获取
* @param id
* @return
*/
String getLoginInfo(String id);
修改MemberServiceImpl
实现类中login
方法
//使用登录人的id作为key,设定3600秒的过期时间,value值待定
jedis.setex(member.getId(),3600,member.getNickName());
添加方法getLoginInfo
方法
@Override
public String getLoginInfo(String id) {
//使用给定的id去查找redis中是否存在当前数据
Jedis jedis = JedisUtils.getResource();
String nickName = jedis.get(id);
jedis.close();
return nickName;
}
1.4 退出登录
(1)修改index.html
页面,将退出方法名修改成logout
,并添加logout
方法
<span class="top-right" id="exit" style="display: none">
<a href="#" @click="logout()" style="color:white">退出</a>
</span>
代码语言:javascript复制logout(){
//1.获取localStorage
let storage = window.localStorage;
//2.发送请求,清除登录状态
axios.post('/member/logout', '{"id":"' storage.id '"}').then(function (response) {
//1.获取响应数据
let data = response.data;
//2.提示
//alert(data.flag);
}).catch(function (err) {
console.log(err)
});
//3.清理localStorage
window.localStorage.clear();
//4.通过调用checkLogin方法重置主页面的右上角显示区域
this.checkLogin();
}
},
(2) MemberServlet
添加logout
方法
public Result logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Member member = getData(request,Member.class);
boolean flag = memberService.logout(member.getId());
if(flag){
return new Result("退出成功!", flag);
}else{
return new Result("", false, flag, Code.LOGOUT_FAIL);
}
}
MemberService
添加方法
boolean logout(String id);
MemberServiceImpl
添加方法
@Override
public boolean logout(String id) {
Jedis jedis = JedisUtils.getResource();
Long row = jedis.del(id);
jedis.close();
return row > 0 ;
}
2.答题试卷
2.1 生成试卷
(1)创建实体类Question
package com.itheima.domain.store;
import java.util.List;
public class Question {
private String id; //题目ID
private String subject; //题干
private String type; //题目类型 1:单选,2:多选,3:简答
}
(2) 创建ExamServlet
继承BaseServlet
@WebServlet("/exam/*")
public class ExamServlet extends BaseServlet {
public Result getPaper(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Question> questionList = examService.getPaper();
return new Result("试卷生成成功!", questionList);
}
}
(3) 创建ExamService
public interface ExamService {
List<Question> getPaper();
}
(4) 创建ExamServiceImpl
实现ExamService
public class ExamServiceImpl implements ExamService {
@Override
public List<Question> getPaper() {
SqlSession sqlSession = null;
try{
//1.获取SqlSession
sqlSession = MapperFactory.getSqlSession();
//2.获取Dao
QuestionDao questionDao = MapperFactory.getMapper(sqlSession, QuestionDao.class);
List<Question> questionList = questionDao.findAll();
return questionList;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
//记录日志
}finally {
try {
TransactionUtil.close(sqlSession);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
(5) 创建QuestionDao
public interface QuestionDao {
List<Question> findAll();
}
(6) 创建QuestionDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.store.QuestionDao">
<!--配置实体类属性和数据库表中列的对应关系-->
<resultMap id="BaseResultMap" type="com.itheima.domain.store.Question">
<id column="id" jdbcType="VARCHAR" property="id"/>
<result column="subject" jdbcType="VARCHAR" property="subject"/>
<result column="type" jdbcType="VARCHAR" property="type"/>
</resultMap>
<!--配置查询的列名公共SQL语句-->
<sql id="Base_Column_List">
id, subject,type
</sql>
<!--配置查询所有,带条件-->
<select id="findAll" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from st_question
order by
limit 2
</select>
</mapper>
启动服务,开始测试
2.2 加载选项
(1)创建QuestionItem
实体类
package com.itheima.domain.store;
public class QuestionItem {
private String id; //ID
private String questionId; //题目ID
private String content; //选项内容
private String isRight; //是否正确答案
}
(2)给Question
实体类添加属性questionItemList
private List<QuestionItem> questionItemList;
public List<QuestionItem> getQuestionItemList() {
return questionItemList;
}
public void setQuestionItemList(List<QuestionItem> questionItemList) {
this.questionItemList = questionItemList;
}
(3) 创建QuestionItemDao
public interface QuestionItemDao {
List<QuestionItem> findByQuestionId(String questionId);
}
(4)创建QuestionItemDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.store.QuestionItemDao">
<!--配置实体类属性和数据库表中列的对应关系-->
<resultMap id="BaseResultMap" type="com.itheima.domain.store.QuestionItem">
<id column="id" jdbcType="VARCHAR" property="id"/>
<result column="question_id" jdbcType="VARCHAR" property="questionId"/>
<result column="content" jdbcType="VARCHAR" property="content"/>
<result column="is_right" jdbcType="VARCHAR" property="isRight"/>
</resultMap>
<!--配置查询的列名公共SQL语句-->
<sql id="Base_Column_List">
id, question_id, content, is_right
</sql>
<!--配置查询所有,带条件-->
<select id="findAll" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from st_question_item
where question_id = #{questionId,jdbcType=VARCHAR}
</select>
<!--配置根据ID查询-->
<select id="findById" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from st_question_item
where id = #{id,jdbcType=VARCHAR}
</select>
<!--根据题目id查询所有选项-->
<select id="findByQuestionId" resultMap="BaseResultMap" parameterType="string">
select
<include refid="Base_Column_List"/>
from st_question_item
where question_id = #{questionId}
</select>
</mapper>
(5) 修改QuestionDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.store.QuestionDao">
<!--配置实体类属性和数据库表中列的对应关系-->
<resultMap id="BaseResultMap" type="com.itheima.domain.store.Question">
<id column="id" jdbcType="VARCHAR" property="id"/>
<result column="subject" jdbcType="VARCHAR" property="subject"/>
<result column="type" jdbcType="VARCHAR" property="type"/>
<!--题目对题目选项的一对多-->
<collection
property="questionItemList"
javaType="java.util.List"
ofType="com.itheima.domain.store.QuestionItem"
select="com.itheima.dao.store.QuestionItemDao.findByQuestionId"
column="id"
/>
</resultMap>
<!--配置查询的列名公共SQL语句-->
<sql id="Base_Column_List">
id, subject,type
</sql>
<!--配置查询所有,带条件-->
<select id="findAll" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from st_question
order by id desc
limit 2
</select>
</mapper>
2.3 单选结果处理
在paper.html
页面中,修改changeResultRadio
方法
changeResultRadio(item){
//输出选中信息
// alert("当前选项所属题目id:" item.questionId);
// alert('当前选项id:' item.id);
// alert("本次操作前数据结果:" JSON.stringify(this.results))
//组织数据(要加入到results中的数据)
var temp = {"questionId":item.questionId,"answer":item.id};
//alert(JSON.stringify(temp))
//删除当前results中已经存在的本题目对应的数据
this.results = this.results.filter(e=>{return e.questionId !== item.questionId})
//alert("results[操作前]:" JSON.stringify(this.results))
//将本次操作的结果加入到results
this.results.push(temp);
//alert("results[操作后]:" JSON.stringify(this.results))
},
刷新页面,查看alert信息
2.4 多选结果处理
在paper.html
页面中,修改changeResultCheckBox
方法
changeResultCheckBox(item){
/*
var s = '11,22,33,44';
x = '33'
var arr = s.split(",");
var index = arr.indexOf(x);
arr.splice(index,1);
s = arr.join(",");
alert(s)
*/
//输出选中信息
// alert("当前选项所属题目id:" item.questionId);
// alert("当前选项id:" item.id);
// alert('当前' this.checked);
// alert("本次操作前数据结果:" JSON.stringify(this.results))
var temp = this.results.find(e=>{return e.questionId === item.questionId})
if(temp == undefined){
//当前题目从来未作答过
temp = {"questionId":item.questionId,"answer":item.id};
}else{
if(this.checked){
// 添加该答案
temp.answer = temp.answer "," item.id;
}else{
//删除该答案
var arr = temp.answer.split(",");
var index = arr.indexOf(item.id);
arr.splice(index,1);
temp.answer = arr.join(",");
}
}
//组织数据(要加入到results中的数据)
// var temp = {"questionId":item.questionId,"answer":item.id};
// alert(JSON.stringify(temp))
//删除当前results中已经存在的本题目对应的数据
this.results = this.results.filter(e=>{return e.questionId !== item.questionId})
alert("results[操作前]:" JSON.stringify(this.results))
//将本次操作的结果加入到results
this.results.push(temp);
alert("results[操作后]:" JSON.stringify(this.results))
},
2.5 提交试卷
paper.html
最终代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!--<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">-->
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="/css/tt.css">
<link rel="stylesheet" type="text/css" href="./plugins/normalize-css/normalize.css" />
<link rel="stylesheet" type="text/css" href="./plugins/yui/cssgrids-min.css" />
<link rel="stylesheet" type="text/css" href="./plugins/sui/sui.min.css" />
<link rel="stylesheet" type="text/css" href="./plugins/sui/sui-append.min.css" />
<link rel="stylesheet" type="text/css" href="./plugins/font-awesome/css/font-awesome.min.css" />
<link rel="stylesheet" type="text/css" href="./css/widget-base.css" />
<link rel="stylesheet" type="text/css" href="./css/widget-head-foot.css" />
<link rel="stylesheet" type="text/css" href="./plugins/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="./css/page-sj-spit-index.css" />
<title>自我测试</title>
<script src="js/vue.js" type="text/javascript"></script>
<script src="./js/axios-0.18.0.js" type="text/javascript"></script>
<script src="element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
<div style="height:100px;background-color:black;color:white;text-align:center;font-size:35px">
开 始 答 题
</div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<div class="wrapper tag-item">
<div class="fl left-list">
<div class="tc-data-list">
<div class="tc-list">
<ul class="detail-list" v-for="question in questions">
<li class="qa-item">
<div class="fl record">
<div class="number">
<div class="border answer">
<p class="usenum"></p>
<p class="zannum"><strong> 题干</strong> </p>
</div>
<hr/>
<div class="border answer">
<p class="zannum"><strong>选项</strong> </p>
</div>
</div>
</div>
<div class="info">
<p class="text">
<b>{{question.subject}}</b>
</p>
<div class="other">
<div class="fl date">
<span>
<el-form-item label="单选题" v-if="question.type == 1">
<el-radio-group v-model="question.id">
<el-radio v-for="(item,index) in question.questionItemList"
:key="item.id"
:label="item.content"
:name="question.id"
v-model="checked"
@change="changeResultRadio(item)">
{{item.content}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="多选题" v-if="question.type == 2" >
<el-checkbox v-for="(item,index) in question.questionItemList"
:key="item.id"
:label="item.content"
:name="question.id"
v-model="checked"
@change="changeResultCheckBox(item)">
{{item.content}}
</el-checkbox>
</el-form-item>
</span>
</div>
</div>
</div>
<div class="clearfix"></div>
</li>
<ul class="detail-list" v-for="question in questions">
</ul>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">交卷</el-button>
</el-form-item>
</div>
</div>
</div>
</div>
</el-form>
</div>
</body>
</html>
<script>
/* 脚本中创建对象,处理业务 */
new Vue({
el: '#app',
data: {
questions:[],
results:[],
checked:[],
},
methods: {
/*-------------------------单选多选题处理结构 开始-------------------------
//1.分情况处理,单选题与多选题处理方式不同
//2.约定回传的答案格式 单选题由题号与选项组成,多选题由题号和多个选项组成
{
questionId:XXXXXXXX,
answer:mm
}
{
questionId:XXXXXXXX,
answer:mm,nn
}
//3.无论是单选还是多选,最终都是将所有题目的答案结果放置在一个数据中保存(results),整体操作就是为results添加/修改数据
[{},{},{}]
//4.操作模式
每次操作一个题目,先将当前题目对应的questionId在原始results中删除,添加新数据到results中
[1,1,1]
单选:加入一个数据,如果之前有这个题目的数据,先删除再添加
多选:加入一个数据,如果之前有这个题目的数据,先删除再添加
-------------------------单选多选题处理结构 结束-------------------------*/
changeResultRadio(item){
//输出选中信息
// alert("当前选项所属题目id:" item.questionId);
// alert('当前选项id:' item.id);
// alert("本次操作前数据结果:" JSON.stringify(this.results))
//组织数据(要加入到results中的数据)
var temp = {"questionId":item.questionId,"answer":item.id};
//alert(JSON.stringify(temp))
//删除当前results中已经存在的本题目对应的数据
this.results = this.results.filter(e=>{return e.questionId !== item.questionId})
//alert("results[操作前]:" JSON.stringify(this.results))
//将本次操作的结果加入到results
this.results.push(temp);
//alert("results[操作后]:" JSON.stringify(this.results))
},
changeResultCheckBox(item){
/*
var s = '11,22,33,44';
x = '33'
var arr = s.split(",");
var index = arr.indexOf(x);
arr.splice(index,1);
s = arr.join(",");
alert(s)
*/
//输出选中信息
// alert("当前选项所属题目id:" item.questionId);
// alert("当前选项id:" item.id);
// alert('当前' this.checked);
// alert("本次操作前数据结果:" JSON.stringify(this.results))
var temp = this.results.find(e=>{return e.questionId === item.questionId})
if(temp == undefined){
//当前题目从来未作答过
temp = {"questionId":item.questionId,"answer":item.id};
}else{
if(this.checked){
// 添加该答案
temp.answer = temp.answer "," item.id;
}else{
//删除该答案
var arr = temp.answer.split(",");
var index = arr.indexOf(item.id);
arr.splice(index,1);
temp.answer = arr.join(",");
}
}
//组织数据(要加入到results中的数据)
// var temp = {"questionId":item.questionId,"answer":item.id};
// alert(JSON.stringify(temp))
//删除当前results中已经存在的本题目对应的数据
this.results = this.results.filter(e=>{return e.questionId !== item.questionId})
//alert("results[操作前]:" JSON.stringify(this.results))
//将本次操作的结果加入到results
this.results.push(temp);
//alert("results[操作后]:" JSON.stringify(this.results))
var arr ;
var temp = this.results.find(e=>{return e.questionId === item.questionId})
if(temp == undefined){
temp = {"questionId":item.questionId,"answer":item.id};
}else{
if(this.checked){
temp.answer = temp.answer "," item.id;
}else{
arr = temp.answer.split(",");
var index = arr.indexOf(item.id);
arr.splice(index,1);
temp.answer = arr.join(",");
}
}
this.results = this.results.filter(e=>{return e.questionId !== item.questionId})
if(var.length > 0){
this.results.push(temp);
}
var temp = this.results.find(e=>{return e.questionId === item.questionId})
if(temp == undefined){
temp = {"questionId":item.questionId,"answer":item.id};
}else{
if(this.checked){
temp.answer = temp.answer "," item.id;
}else{
var arr = temp.answer.split(",");
var index = arr.indexOf(item.id);
arr.splice(index,1);
temp.answer = arr.join(",");
}
}
this.results = this.results.filter(e=>{return e.questionId !== item.questionId})
this.results.push(temp);
},
submitForm(formName) {
if(this.results.length != this.questions.length){
alert("请检查题目是否全部选择");
return;
}else{
if(window.confirm("确定交卷吗?")) {
//把json数据转成字符串
let str = JSON.stringify(this.results);
//获取localSotrage
let storage = window.localStorage;
//发送请求,交卷
axios.post('/exam/applyPaper', '{"memberId":"' storage.id '","results":' str '}').then(function (response) {
//输出提示信息
//alert(response.data.message);
//发送完请求,跳转到交卷成功页面
window.open('/index.html', '_self');
}).catch(function (err) {
console.log(err)
});
}
}
},
findQuestion(){
let _this = this;
//4.发送post请求,获取题目信息
axios.post('/exam/getPaper').then(function (response) {
//5.得到响应数据
var res = response.data;
//alert(JSON.stringify(res));
_this.questions = res.data;
}).catch(function (err) {
console.log(err)
});
}
},
created(){
this.findQuestion();
},
});
</script>
ExamServlet
@WebServlet("/exam/*")
public class ExamServlet extends BaseServlet {
public Result getPaper(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Question> questionList = examService.getPaper();
return new Result("试卷生成成功!", questionList);
}
public Result applyPaper(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//memberId:?????,results:[{},{}]
//1.得到全部请求的json数据
String json = JSONObject.parseObject(request.getInputStream(), String.class);
//2.将json数据转换为json对象
JSONObject jsonObject = JSON.parseObject(json);
//3.获取当前提交试卷人的id
String memberId = jsonObject.getObject("memberId", String.class);
//4.获取当前提交的试卷信息
JSONArray jsonArray = jsonObject.getJSONArray("results");
List<ExamQuestion> examQuestionList = jsonArray.toJavaList(ExamQuestion.class);
boolean flag = examService.applyPaper(memberId,examQuestionList);
return new Result("试卷提交成功!",flag);
}
}
ExamPaper
实体类
package com.itheima.domain.front;
import java.util.Date;
public class ExamPaper {
private String id;
private String memberId;
private Date applyTime;
private String state; //1-可用 0-不可用
private Integer score;
}
ExamQuestion
实体类
package com.itheima.domain.front;
public class ExamQuestion {
private String id;
private String examPaperId;
private String questionId;
private String answer;
}
ExamService
接口
package com.itheima.service.front;
import com.itheima.domain.front.ExamQuestion;
import com.itheima.domain.store.Question;
import java.util.List;
public interface ExamService {
List<Question> getPaper();
boolean applyPaper(String memberId, List<ExamQuestion> examQuestionList);
}
ExamServiceImpl
实现类
package com.itheima.service.front.impl;
import com.itheima.dao.front.ExamPaperDao;
import com.itheima.dao.front.ExamQuestionDao;
import com.itheima.dao.store.QuestionDao;
import com.itheima.domain.front.ExamPaper;
import com.itheima.domain.front.ExamQuestion;
import com.itheima.domain.store.Question;
import com.itheima.factory.MapperFactory;
import com.itheima.service.front.ExamService;
import com.itheima.utils.TransactionUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public class ExamServiceImpl implements ExamService {
@Override
public List<Question> getPaper() {
SqlSession sqlSession = null;
try{
//1.获取SqlSession
sqlSession = MapperFactory.getSqlSession();
//2.获取Dao
QuestionDao questionDao = MapperFactory.getMapper(sqlSession, QuestionDao.class);
List<Question> questionList = questionDao.findAll();
return questionList;
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
//记录日志
}finally {
try {
TransactionUtil.close(sqlSession);
}catch (Exception e){
e.printStackTrace();
}
}
}
@Override
public boolean applyPaper(String memberId, List<ExamQuestion> examQuestionList) {
SqlSession sqlSession = null;
try{
boolean flag = true;
//1.获取SqlSession
sqlSession = MapperFactory.getSqlSession();
//2.获取Dao
ExamPaperDao examPaperDao = MapperFactory.getMapper(sqlSession, ExamPaperDao.class);
ExamQuestionDao examQuestionDao = MapperFactory.getMapper(sqlSession, ExamQuestionDao.class);
//3.提交保存的试卷信息
ExamPaper examPaper = new ExamPaper();
String paperId = UUID.randomUUID().toString();
examPaper.setId(paperId);
examPaper.setApplyTime(new Date());
examPaper.setMemberId(memberId);
examPaper.setState("1");
flag = flag && examPaperDao.save(examPaper) > 0;
//4.提交保存的试卷中的所有题目对应的答案信息
for(ExamQuestion eq: examQuestionList) {
eq.setId(UUID.randomUUID().toString());
eq.setExamPaperId(paperId);
flag = flag && examQuestionDao.save(eq) > 0;
}
TransactionUtil.commit(sqlSession);
return flag;
}catch (Exception e){
TransactionUtil.rollback(sqlSession);
throw new RuntimeException(e);
//记录日志
}finally {
try {
TransactionUtil.close(sqlSession);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
ExamPaperDao
接口
package com.itheima.dao.front;
import com.itheima.domain.front.ExamPaper;
public interface ExamPaperDao {
int save(ExamPaper examPaper);
}
ExamQuestionDao
接口
package com.itheima.dao.front;
import com.itheima.domain.front.ExamQuestion;
public interface ExamQuestionDao {
int save(ExamQuestion eq);
}
ExamPaperDao.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.front.ExamPaperDao">
<insert id="save" parameterType="com.itheima.domain.front.ExamPaper">
insert into tr_examination_paper (id, member_id, state, apply_time)
values (#{id}, #{memberId}, #{state}, #{applyTime})
</insert>
</mapper>
ExamQuestionDao.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.front.ExamQuestionDao">
<insert id="save" parameterType="com.itheima.domain.front.ExamQuestion">
insert into tr_member_question (id, question_id, examinationpaper_id,answer_result)
values (#{id}, #{questionId}, #{examPaperId},#{answer})
</insert>
</mapper>