作者主页:夜未央5788
简介:Java领域优质创作者、Java项目、学习资料、技术互助
文末获取源码
ssm在线答题系统
技术框架
使用SSM+Vue的形式来实现,SSM框架用于处理后台的数据逻辑,Vue框架用于前端的数据显示
系统分为客户端,管理端
注意事项
1 数据库文件在一级目录下,命名为answerWeb.sql,部署时,需要在answerWeb/config/dbconfig.properties配置文件中配置好数据库
2 管理端用户表为'admins'表
3 客户端用户表为'user'表,用户端登录页登录帐号为邮箱
4 管理端,在创建题目时,在选择完图片后,图片会立即上传到百度云BOS对象存储中(需要在util包的BOSUtil工具类你的BOS对象存储),未点击添加题目时,此时试题的资源(图片,视频)是在BOS的临时文件夹下(在QuestionController类定义路径),当点击添加题目后,会把此试题的资源添加到目标文件夹下(在QuestionController类定义路径),临时文件夹下的东西可以设置任务调度器进行定时删除,防止浪费BOS存储空间。
5 项目的jar包除了用maven管理外,有一部分jar需要手动导入(answerWeb/WebRoot/WEB-INF/lib)
运行截图
相关代码
管理员登入
package cn.edu.lingnan.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import cn.edu.lingnan.pojo.Admins;
import cn.edu.lingnan.service.AdminsService;
@Controller
public class AdminController extends BaseController {
@Autowired
private AdminsService adminsService;
/**
* 管理员登入
* @param admins
* @param map
* @author lizhi
*/
@RequestMapping("/adminLogin")
public String adminLogin(Admins admins,Map<String,Object> map){
if(adminsService.login(admins).size()<=0){
map.put("loginError", "帐号或密码错误");
return "/admin/login";
}
super.session.setAttribute("admins", adminsService.login(admins).get(0));
return "redirect:/selectUserByExample";
}
/**
* 更新管理员资料(修改密码)
* @param admins
* @author lizhi
*/
@RequestMapping("/changeAdminPassword")
public String changeAdminPassword(Admins admins){
adminsService.updateSelective(admins);
return "redirect:/selectUserByExample";
}
/**
* 注销
* @return
*/
@RequestMapping("/logout")
public String logout(){
session.invalidate();
return "/admin/login";
}
}
获取题目基础类型
package cn.edu.lingnan.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import cn.edu.lingnan.pojo.Options;
import cn.edu.lingnan.pojo.Question;
import cn.edu.lingnan.pojo.QuestionOption;
import cn.edu.lingnan.pojo.QuestionType;
import cn.edu.lingnan.pojo.User;
import cn.edu.lingnan.pojo.WeChatUser;
import cn.edu.lingnan.service.AnswerService;
@Controller
public class AnswerController extends BaseController {
public static final int QUESTION_NUMBER = 10;
@Autowired
private AnswerService answerService;
/**
* @author huang
* 获取题目基础类型
*/
@ResponseBody
@RequestMapping(value="user/getType")
public Map<String, Object> getQuestionType() {
Map<String, Object> map = new HashMap<String, Object>();
List<QuestionType> firstlist = answerService.findType();
if (firstlist.size() <= 0) {
map.put("error", "系统错误:一级菜单获取失败");
} else {
map.put("firstlist", firstlist);
}
return map;
}
/**
* @author huang
* 获取题目具体类型
*/
@ResponseBody
@RequestMapping(value="user/getType/{id}")
public Map<String, Object> getQuestionType(@PathVariable int id) {
Map<String, Object> map = new HashMap<String, Object>();
List<QuestionType> secondlist = answerService.findType(id);
if (secondlist.size() <= 0) {
map.put("error", id);
} else {
//判断是否为3级菜单
List<QuestionType> thirdList = answerService.findType(secondlist.get(0).getTypeno());
if(thirdList.size() <= 0)
map.put("grade", "two");
else
map.put("grade", "third");
map.put("secondlist", secondlist);
}
return map;
}
/**
* @author huang
* 根据类型获取题目
*/
@ResponseBody
@RequestMapping(value="user/getQuestion/{typeno}")
public Map<String, Object> getQuestion(@PathVariable int typeno) {
Map<String, Object> map = new HashMap<String, Object>();
List<Question> questionList = answerService.getQuestionByType(typeno);
List<QuestionOption> questionOptionsList = new ArrayList<QuestionOption>();
for (Question q : questionList) {
List<Options> optionlist = answerService.getOptionsByQuestion(q.getQuestionno());
QuestionOption questionOption = new QuestionOption(q,optionlist);
questionOptionsList.add(questionOption);
}
map.put("question",questionOptionsList);
map.put("maxnumber", QUESTION_NUMBER);
map.put("title", answerService.getQuestionTypeByID(typeno).getTypename());
return map;
}
/**
* @author huang
* 用户答题更新记录
*/
@RequestMapping(value="user/refreshRecord/{typeno}/{status}")
public void refreshRecord(@PathVariable int typeno, @PathVariable int status){
User user = (User) super.session.getAttribute("user");
WeChatUser weuser = (WeChatUser) super.session.getAttribute("weChatUser");
if (user != null)
answerService.answerRecord(user.getUserno(), typeno, status, 0);
else if (weuser != null)
answerService.answerRecord(weuser.getWechatuserno(), typeno, status, 1);
}
}
可根据条件分页查询所有候选答案
package cn.edu.lingnan.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import cn.edu.lingnan.pojo.Options;
import cn.edu.lingnan.pojo.OptionsExample;
import cn.edu.lingnan.service.OptionsService;
@Controller
public class OptionsController extends BaseController {
@Autowired
private OptionsService optionsService;
/**
* 可根据条件分页查询所有候选答案
* @return
* @author lizhi
*/
@RequestMapping("/selectOptions")
public String selectOptions(OptionsExample options, Map<String, Object> map,
@RequestParam(value = "pn", defaultValue = "1") Integer pn) {
// 每页显示八条数据,且当前页是参数pn
PageHelper.startPage(pn, 8);
List<Options> list = optionsService.selectOptionsByExample(options);
// 对数据进行分页处理
PageInfo pageInfo = new PageInfo(list);
map.put("optionsListPageInfo", pageInfo);
// 到时候前端写出网页后再修改到具体的页面
return "admin/index";
}
/**
* 更新候选答案
* @return
* @author lizhi
*/
@RequestMapping("/updateOptions")
public String updateOptions(Options options){
optionsService.updateByPrimaryKey(options);
return "admin/index";
}
}
QuestionController
package cn.edu.lingnan.controller;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import cn.edu.lingnan.pojo.Options;
import cn.edu.lingnan.pojo.OptionsList;
import cn.edu.lingnan.pojo.Question;
import cn.edu.lingnan.pojo.TempUrl;
import cn.edu.lingnan.service.OptionsService;
import cn.edu.lingnan.service.QuestionService;
import cn.edu.lingnan.service.QuestionTypeService;
import cn.edu.lingnan.service.TempUrlService;
import cn.edu.lingnan.utils.BOSUtil;
@Controller
public class QuestionController extends BaseController {
@Autowired
private QuestionService questionService;
@Autowired
private QuestionTypeService questionTypeService;
@Autowired
private OptionsService optionsService;
@Autowired
private TempUrlService tempUrlService;
/**
* 分页根据条件查找试题
* @param question
* @param map
* @param pn
* @author lizhi
*/
@RequestMapping("/selectQuestion")
public String selectQuestion(Question question, Map<String, Object> map,
@RequestParam(value = "pn", defaultValue = "1") Integer pn,@RequestParam("toid")Integer toid) {
// 每页显示八条数据,且当前页是参数pn
PageHelper.startPage(pn, 6);
List<Question> list = questionService.selectQuestionByExample(question);
// 对数据进行分页处理
PageInfo pageInfo = new PageInfo(list);
map.put("pageInfo", pageInfo);
//找出所有三级菜单类型,返回到前端多条件选择
map.put("questionTypeList",questionTypeService.getAllQuestionType());
//在选项卡一中显示
map.put("toid", toid);
// 到时候前端写出网页后再修改到具体的页面
return "/admin/questionList";
}
/**
* 更新试题第一步
* @param question
* @author lizhi
*/
@RequestMapping("/updateQuestionFirst")
public String updateQuestionFirst(@RequestParam("questionno")Integer questionno,Map<String,Object> map,@RequestParam("pn") Integer pn){
//找出具体题目
map.put("question",questionService.getQuestionByKey(questionno));
//找出题目的候选答案
map.put("optionsList",optionsService.getQuestionOptions(questionno));
//找出所有三级菜单类型,返回到更新页面
map.put("questionTypeList",questionTypeService.getAllQuestionType());
map.put("pn",pn);
return "/admin/updateQuestion";
}
/**
* 更新试题第二步
* @param question
* @param pn
* @author lizhi
*/
@RequestMapping("/updateQuestionSecond")
public String updateQuestionSecond(Question question,@RequestParam("pn") Integer pn,OptionsList optionsList,String oldContent,String oldDescription){
//如果不同文件名,就要移动
if(!question.getContent().equals(oldContent)){
String strExtension = question.getContent().substring(question.getContent().lastIndexOf('.') + 1);
String path = "/resource/images/question/";
if(strExtension.equals("mp3")){
path = "/resource/audio/";
//将文件从临时文件夹移动到目标文件夹
BOSUtil.moveFile("/temp/"+question.getContent(),path+question.getContent());
}else if(strExtension.equals("mp4")){
path = "/resource/video/";
//将文件从临时文件夹移动到目标文件夹
BOSUtil.moveFile("/temp/"+question.getContent(),path+question.getContent());
}else if(strExtension.equals("jpg")||strExtension.equals("gif") ||strExtension.equals("png") || strExtension.equals("bmp")){
//将文件从临时文件夹移动到目标文件夹
BOSUtil.moveFile("/temp/"+question.getContent(),path+question.getContent());
}
}
//如果不同文件名,就要删除原来的
if(!question.getContent().equals(oldContent)){
//把原来的文件删除
String path="";
String oldExtension = oldContent.substring(oldContent.lastIndexOf('.') + 1);
String oldpath = "/resource/images/question/";
if(oldExtension.equals("mp3")){
path = "/resource/audio/";
BOSUtil.deleteFile(path+oldContent);
}else if(oldExtension.equals("mp4")){
path = "/resource/video/";
BOSUtil.deleteFile(path+oldContent);
}else if(oldExtension.equals("jpg")||oldExtension.equals("gif") || oldExtension.equals("png") || oldExtension.equals("bmp")){
BOSUtil.deleteFile(path+oldContent);
}
}
//对答案图片进行更新
if(question.getDesstatus()==2){
if(!question.getDescription().equals(oldDescription)){
String path = "/resource/images/answer/";
//移动答案图片
BOSUtil.moveFile("/temp/"+question.getDescription(),path+question.getDescription());
//删除原来的答案图片
BOSUtil.deleteFile(path+oldDescription);
}
}
questionService.updateSelective(question);
for(Options options:optionsList.getOptionsList()){
optionsService.updateByPrimaryKey(options);
}
redirectAttributes.addAttribute("pn",pn);
redirectAttributes.addAttribute("toid",1);
return "redirect:/selectQuestion";
}
/**
* 上传题目的图片,视频,音频
* @param file
* @param typename
* @return
* @throws IllegalStateException
* @throws IOException
*/
@ResponseBody
@RequestMapping(value = "/addQuestionFile", produces = "text/html;charset=UTF-8")
public String addQuestionFile(@RequestParam(value = "file", required = false) MultipartFile file,@RequestParam(value="desFile",required=false) MultipartFile desFile
,@RequestParam(value="flag",required=false) Integer flag ) throws IllegalStateException, IOException {
if(flag == 1){
/* String strExtension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.') + 1);
String path = "/resource/images/question/";
if(strExtension.equals("mp3")){
path = "/resource/audio/";
}else if(strExtension.equals("mp4")){
path = "/resource/video/";
}*/
// fileName唯一性
int a = ThreadLocalRandom.current().nextInt(100,999);
String fileName =+ a +"-"+ System.currentTimeMillis()+ file.getOriginalFilename();
//上传到临时文件夹
String typeImagesTempPath = "/temp/"+fileName;
BOSUtil.upload(file, typeImagesTempPath);
//插入上传记录
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
TempUrl tempUrl = new TempUrl(null,fileName,format.format(new Date()));
tempUrlService.addTempUrl(tempUrl);
return fileName;
//这是答案详解图片的预览
}else if(flag == 2){
String path = "/resource/images/answer/";
// fileName唯一性
int a = ThreadLocalRandom.current().nextInt(100,999);
String fileName =+ a +"-"+ System.currentTimeMillis()+ desFile.getOriginalFilename();
//上传到临时文件夹
String typeImagesTempPath = "/temp/"+fileName;
BOSUtil.upload(desFile, typeImagesTempPath);
//插入上传记录
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
TempUrl tempUrl = new TempUrl(null,fileName,format.format(new Date()));
tempUrlService.addTempUrl(tempUrl);
return fileName;
}
return "error";
}
/**
* 增加试题
* @param question
* @author lizhi
* @throws IOException
* @throws IllegalStateException
*/
@RequestMapping("/addQuestion")
public String addQuestion(Question question,OptionsList optionsList,@RequestParam("pn") Integer pn) throws IllegalStateException, IOException{
String strExtension = question.getContent().substring(question.getContent().lastIndexOf('.') + 1);
String path = "/resource/images/question/";
if(strExtension.equals("mp3")){
path = "/resource/audio/";
//将文件从临时文件夹移动到目标文件夹
BOSUtil.moveFile("/temp/"+question.getContent(),path+question.getContent());
}else if(strExtension.equals("mp4")){
path = "/resource/video/";
//将文件从临时文件夹移动到目标文件夹
BOSUtil.moveFile("/temp/"+question.getContent(),path+question.getContent());
}else if(strExtension.equals("jpg") || strExtension.equals("gif") || strExtension.equals("png") || strExtension.equals("bmp")){
//将文件从临时文件夹移动到目标文件夹
BOSUtil.moveFile("/temp/"+question.getContent(),path+question.getContent());
}
//移动答案图片
if(question.getDesstatus()==2){
String desImapgePath = "/resource/images/answer/";
//移动答案图片
BOSUtil.moveFile("/temp/"+question.getDescription(),desImapgePath+question.getDescription());
}
//插入数据库
questionService.insertQuestion(question);
for(Options options:optionsList.getOptionsList()){
options.setQuestionno(question.getQuestionno());
optionsService.insert(options);
}
redirectAttributes.addAttribute("pn",pn);
redirectAttributes.addAttribute("toid",1);
return "redirect:/selectQuestion";
}
/**
* 根据试题id删除试题
* @param id
* @author lizhi
*/
/*@RequestMapping(value="/deleteQuestion/{id}",method=RequestMethod.DELETE)
public String deleteQuestion(@PathVariable(value="id") Integer id){
questionService.deleteQuestion(id);
return "/admin/index";
}*/
/**
* 根据试题id删除试题
* @param id
* @author lizhi
*/
@RequestMapping(value="/deleteQuestion")
public String deleteQuestion(@RequestParam("questionno") Integer questionno,@RequestParam("pn") Integer pn){
Question question = questionService.getQuestionByKey(questionno);
questionService.deleteQuestion(questionno);
redirectAttributes.addAttribute("pn", pn);
redirectAttributes.addAttribute("toid",1);
//删除题目内容对应的资源
if(question.getConstatus()!=1){
String contentExtension = question.getContent().substring(question.getContent().lastIndexOf('.') + 1);
String path = "/resource/images/question/";
if(contentExtension.equals("mp3")){
path = "/resource/audio/";
BOSUtil.deleteFile(path+question.getContent());
}else if(contentExtension.equals("mp4")){
path = "/resource/video/";
BOSUtil.deleteFile(path+question.getContent());
}else if(contentExtension.equals("jpg") || contentExtension.equals("gif") || contentExtension.equals("png") || contentExtension.equals("bmp")){
BOSUtil.deleteFile(path+question.getContent());
}
}
//删除题目答案对应的资源
if(question.getDesstatus()==2){
BOSUtil.deleteFile("/resource/images/answer/"+question.getDescription());
}
return "redirect:/selectQuestion";
}
}