一.项目简单介绍
通过这么两个月以来的java学习,自己终于能够独立完成一个小型的项目了;
激动的同时,也暴露出自己不少的问题,在此有必要记录一下;
话不多说,直接进入主题!
此篇博客只做个记录,至于项目中遇到的问题,会另写一篇博客来总结;
先整体看一下效果吧:
登录后就显示一些题库,然后提交答案,之后自动批改选择题
此次写的是一个前后端分离的
考试答题系统
的小项目;
项目要求实现功能:
- 登录
- 展示题目
- 保存题目
- 自动批改考生选择题
- 自动计算考生总成绩
- 考生成绩排名
技术选型如下:
后端 springboot,springMVC,mybatis,log4j,springboot定时任务 前端 VUE 数据库 mysql,druid连接池 项目管理和部署 阿里云服务器,linux,maven,gitee码云
一下是maven中所有的依赖包及其对应额版本:
springboot使用的是2.4.0版本
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.18</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- gson格式转换 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!--引入热部署依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- 引入实现分页功能的依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
<!--thymeleaf模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
依赖的介绍
- lombok :可以简化类的书写,不用再自己写getter和setter方法
- devtools:热部署,不用每次修改代码后重启项目,直接按ctrl+F9
- gson:对前端传入的json数据进行转换
二.源代码
yml配置文件
spring:
datasource:
username: xxx
password: xxxx
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://xxxxx/exam?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
//配置这一部分,主要是使控制台打印SQL语句的一些信息
logging:
level:
com:
jw:
springbootexam:
mapper: trace
mybatis:
configuration:
map-underscore-to-camel-case: true
server:
port: 8080
//配置这一部分,主要是使控制台打印SQL语句的一些信息
logging:
level:
com:
jw:
springbootexam:
mapper: trace
config配置
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1.配置一个管理后台的servlet
@Bean
public ServletRegistrationBean stateViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
initParams.put("allow","");//默认就是允许所有都可访问
bean.setInitParameters(initParams);
return bean;
}
//2.配置一个web监控的filter
@Bean//加入到容器汇中
public FilterRegistrationBean webStatFileter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
controller层
@Controller
@CrossOrigin(origins="*")//解决跨域
@Slf4j
@RequestMapping("/user")
public class TestController {
@Autowired
private DisplayService displayService;
/**
* @Author YangJiaWen
* @Description //校验考生的登录
* @Date 12:04 2020/12/6
* @Param [username, password]
* @return java.util.Map<java.lang.String,java.lang.String>
**/
@PostMapping("/login")
@ResponseBody
public ResultVO checkUsernameAndPassword(@RequestParam("username") String username,
@RequestParam("password") String password){
StuLogin user = displayService.findPasswordByUsername(username);
Map<String,String> map = new HashMap<>();
if (user == null) {
return ResultVOUtil.userNotExist();
}else{
if (password.equals(user.getPassword())){
return ResultVOUtil.success(username);
}
}
return ResultVOUtil.pwdNotTrue();
}
/**
* @Author YangJiaWen
* @Description //展示题目
* @Date 12:03 2020/12/6
* @Param []
* @return java.util.Map<java.lang.String,java.lang.Object>
**/
@GetMapping("/exam")
@ResponseBody
public Map<String,Object> showAllSelect(){
Map<String,Object> map =new HashMap<>();
map.put("selectArray",displayService.showAllSelect());
map.put("subjectArray",displayService.showAllSubject());
return map;
}
/**
* @Author YangJiaWen
* @Description //保存考生的答案
* @Date 12:04 2020/12/6
* @Param [map]
* @return void
**/
@PostMapping("/save")
@ResponseBody
public ResultVO saveAllAnswer(@RequestBody String json){
Gson gson = new Gson();
AllAnswer allAnswer = gson.fromJson(json, AllAnswer.class);
System.out.println(allAnswer);
int i = displayService.insertAllAnswer(allAnswer);
if (i==2){
return ResultVOUtil.success();
}else{
return ResultVOUtil.insertFail();
}
}
}
mapper层
@Mapper
@Repository
public interface selectMapper {
//查询所有选择题
@Select("select * from question_select")
public List<QuestionSelect> findAllSelect();
//查询所有客观题
@Select("select * from question_program")
public List<QuestionSubject> findAllSubject();
//插入选择题答案
@Insert("insert into answer_examinee_select(stuid,q1,q2,q3,q4,q5)" +
"values(#{stuid},#{Q1},#{Q2},#{Q3},#{Q4},#{Q5})")
public int insertChoiceAnswer(AnswerSelect answerSelect);
//插入客观题答案
@Insert("insert into answer_examinee_program(stuid,q6,q7,q8,q9,q10,q11,q12,q13,q14)" +
"values(#{Stuid},#{Q6},#{Q7},#{Q8},#{Q9},#{Q10},#{Q11},#{Q12},#{Q13},#{Q14})")
public int insertSubjectAnswer(AnswerSubject answerSubject);
//查询选择题标准答案
@Select("select * from answer_standard_select")
public List<StandardSelectAns> findStandardSelectAns();
//查询主观题标准答案
@Select("select * from answer_standard_program")
public List<StandardSubjectAns> findStandardSubjectAns();
//查询考生答题情况
@Select("select * from answer_examinee_select")
public List<AnswerSelect> findAllSelectAns();
//更新考生的选择题成绩
@Update("update examinee_score set select_score = #{score} where stuid = #{stuId}")
public int updateSelectScore(@Param("stuId")String stuId, @Param("score") int score);
@Select("select * from stu_login where username=#{username}")
public StuLogin selectByUsername(String username);
}
model层
@Data
@NoArgsConstructor
public class AllAnswer{
String password;
AnswerSelect selectAns;
AnswerSubject subjectAns;
}
@Data
@NoArgsConstructor
public class AnswerSelect {
private String Stuid;
private String Q1;
private String Q2;
private String Q3;
private String Q4;
private String Q5;
}
@Data
@NoArgsConstructor
public class AnswerSubject {
private String Stuid;
private String Q6;
private String Q7;
private String Q8;
private String Q9;
private String Q10;
private String Q11;
private String Q12;
private String Q13;
private String Q14;
}
@AllArgsConstructor
@Data
public class QuestionSelect {
String Id;
String Content;
String optionA;
String optionB;
String optionC;
String OptionD;
}
@Data
@AllArgsConstructor
public class QuestionSubject {
String Id;
String Content;
}
@Data
@AllArgsConstructor
public class StandardSelectAns {
private String Id;
private String Content;
}
@Data
@AllArgsConstructor
public class StandardSubjectAns {
private String Id;
private String Content;
}
@Data
@AllArgsConstructor
public class StuLogin {
private Integer Id;
private String Username;
private String Password;
}
service层
@Service
public class DisplayService {
@Autowired
private selectMapper selectMapper;
@Autowired
private UserMapper userMapper;
public StuLogin findPasswordByUsername(String username){
return userMapper.selectByUsername(username);
}
public List<QuestionSelect> showAllSelect(){
return selectMapper.findAllSelect();
}
public List<QuestionSubject> showAllSubject(){
return selectMapper.findAllSubject();
}
/**
* @Author YangJiaWen
* @Description //保存考生的所有答案
* @Date 12:02 2020/12/6
* @Param [map]
* @return void
**/
public int insertAllAnswer(AllAnswer allAnswer){
AnswerSelect selectAns = allAnswer.getSelectAns();
AnswerSubject subjectAns = allAnswer.getSubjectAns();
String password = allAnswer.getPassword();
selectAns.setStuid(password);
subjectAns.setStuid(password);
int i = selectMapper.insertChoiceAnswer(selectAns);
int i1 = selectMapper.insertSubjectAnswer(subjectAns);
return i+i1;
}
/**
* @Author YangJiaWen
* @Description //自动批改考生的选择题
* @Date 12:03 2020/12/6
* @Param []
* @return void
**/
@Scheduled(cron = "0 38 11 13 12 *")
public void checkUserAns(){
List<StandardSelectAns> standardSelectAns = selectMapper.findStandardSelectAns();
List<AnswerSelect> allSelectAns = selectMapper.findAllSelectAns();
List<String> answer=new LinkedList<>();
for (AnswerSelect answerSelect : allSelectAns) {
//考生选择题成绩
int selectScore = 0;
answer.add(answerSelect.getQ1());
answer.add(answerSelect.getQ2());
answer.add(answerSelect.getQ3());
answer.add(answerSelect.getQ4());
answer.add(answerSelect.getQ5());
String stuId = answerSelect.getStuid();
for (int i = 0; i < standardSelectAns.size(); i++) {
String standardAns = standardSelectAns.get(i).getContent();
String userAns = answer.get(i);
if (standardAns.equals(userAns)){
selectScore+=5;
}
}
int i = selectMapper.updateSelectScore(stuId,selectScore);
answer.clear();
}
}
}
VO(返回给前端的类)
@Data
public class ResultVO<T> {
private String code;
private String message;
private T data;
}
public class ResultVOUtil {
//成功
public static ResultVO success(Object object){
ResultVO resultVO = new ResultVO();
resultVO.setCode("1");
resultVO.setMessage("成功");
resultVO.setData(object);
return resultVO;
}
public static ResultVO success(){
return success(null);
}
public static ResultVO userNotExist(){
ResultVO resultVO = new ResultVO();
resultVO.setCode("0");
resultVO.setMessage("用户名不存在");
return resultVO;
}
public static ResultVO pwdNotTrue(){
ResultVO resultVO = new ResultVO();
resultVO.setCode("0");
resultVO.setMessage("密码错误");
return resultVO;
}
public static ResultVO insertFail(){
ResultVO resultVO = new ResultVO();
resultVO.setCode("0");
resultVO.setMessage("保存失败");
return resultVO;
}
}
这里只列举了部分代码,完整代码可以到我的码云(gitee)
上去clone
SSH密钥:(git@gitee.com:yun_1002/yilingquestion.git).
此项目会持续更新!