基于前后端分离的springboot考试答题系统

springboot考试答题系统

一.项目简单介绍

通过这么两个月以来的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).

此项目会持续更新!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
基于Spring Boot的在线考试系统前后端分离可以通过以下方式实现。 首先,前端使用基于JavaScript的前端框架进行开发,如React、Vue或Angular等。这些框架能够提供丰富的页面交互和用户体验,同时支持组件化开发,方便模块化的构建前端界面。前端开发人员可以根据需求设计和实现考试系统的用户界面,包括登录、考试页面、题目展示、答题提交等。 然后,后端使用Spring Boot框架进行开发。Spring Boot提供了开发Java应用程序的一系列功能,包括依赖管理、自动配置、快速构建和部署等。后端开发人员可以使用Spring Boot快速开发考试系统后端逻辑,包括用户认证、试题管理、答题验证等。 前后端的数据交互可以使用RESTful API进行通信。前端发起HTTP请求到后端API接口,后端处理请求并返回相应的数据。这种方式使得前后端可以独立开发和部署,同时能够提高系统的可扩展性和可维护性。 为了保证系统的安全性,可以使用Token或者OAuth等身份认证机制进行用户登录。前端在用户登录成功后将获取到的Token保存在本地,之后每次请求都携带该Token进行身份验证。后端在接收到请求时通过验证Token的有效性确定用户的身份。 基于Spring Boot的在线考试系统前后端分离能够提高开发效率、降低系统复杂性,并支持系统的可扩展性和可维护性。同时,前后端分离也有利于团队合作,前端和后端开发人员可以并行进行工作,提高开发效率和协作效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值