Skip to content

CMW845751770/quiz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

项目介绍

后端基于SpringBoot+MyBatis+SpringSecurity实现,实现的功能模块大致上分为以下几个

  • 用户模块
  • 安全模块
  • 选择题
  • 编程题

用户模块包含用户的注册、登录、修改用户信息等;安全模块使用SpringSecurity开发了基于JWT token的认证方式以及基于角色的授权,并且使用了全局的异常处理机制以及基于拦截器+注解实现的接口限流;实现了选择题的生成、校对、打分等功能;编程题模块实现了列表以及提交判断等功能。

项目截图

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here 项目的演示地址为http://47.101.33.252 因为没有备案的服务器和域名。所以直接就是用IP了。该项目是前后端分离的,前端项目地址https://github.com/SG-XM/OnlineOJ-Web

技术选型

技术 说明 官网
SpringBoot 容器+MVC框架 https://spring.io/projects/spring-boot
SpringSecurity 认证授权 https://spring.io/projects/spring-security
MyBatis ORM框架 http://www.mybatis.org/mybatis-3/zh/index.html
MyBatisGenerator 数据层代码生成 http://www.mybatis.org/generator/index.html
PageHelper MyBatis物理分页插件 http://git.oschina.net/free/Mybatis_PageHelper
Hibernator-Validator 验证框架 http://hibernate.org/validator/
RabbitMq 消息队列 https://www.rabbitmq.com/
Redis 分布式缓存 https://redis.io/
Lombok 简化对象封装工具 https://github.com/rzwitserloot/lombok

核心功能实现

  • 注册
    注册功能使用的是邮箱+激活链接的方式。这里是在用户的状态中使用一个bit表示激活状态,在用户注册的时候向数据库插入其用户信息但状态仍为未激活,往Redis中设置好对应的token后然后使用RabbitMQ异步发送消息,这里我是设置消费端为手动ACK模式,这样的话发送失败还可以将消息重新入队重新发送,可以设置一个阈值来控制重新发送的次数,因为只是发送激活邮件,幂等性以及100%消费这两个问题其实没必要考虑太多。
  • 登录
    登陆其实跟普通的用户名、密码方式的登录差不太多,只不过这里我使用的是SpringSecurity+JWT的方式。
  • 编程题提交
    这里我也是参考的别人的思路,毕竟之前也没做过相应的功能。收到前端传过来的代码以及题目ID后,查询出数据库中对应的测试用例,这里Judge使用的是测试框架Junit+Hamcrest,基本做法将用户的代码生成一个Main.java的文件,然后后台也生成一个MainTest.java文件,这个MainTest类中调用Main类的实例并使用Junit来进行Judge,然后就是生成一个Linux下的shell脚本并调用这个脚本执行编译MainTest.java和Main.java并执行MainTest,最后读取Linux的标准输出并处理返回的结果。这是一个MainTest类的示例 enter image description here
  • 选择题生成
    因为我们的选择题是有答题时间限制的,只使用数据库还是比较麻烦的,所以我使用的是Redis。实现起来很简单,就是调用的时候将随机生成的题目以及选项设置到Redis中,然后设置相应的过期时间。这里考虑一个场景,如果用户答题答到一半就掉线退出了,这个怎么处理呢。我的解决方式分为以下两种情况: 第一种情况是如果用户迅速的返回该题,并且题目还没有超时,则重新设置一下题目的过期时间,然后让他继续答题。(这个当然是有问题的) 第二种情况就是用户掉线,且题目也已经超时了。这里可以有两种方式解决,第一种是使用监听Redis的key过期事件,每当Redis中这道题目过期,就结束这个用户的答题(功能是只要答错一题就结束答题),这个可以实现一个Redis自动处理答题结果的效果。 第二种方式就是当用户掉线重连后,检测他上次答题是不是超时了,如果超时了那就结算他上次答题的分数并返回,这种方式的实现比较简单,而且因为我们没有让用户查看往期答题记录的功能,所以也比较人性化。

环境搭建

环境的部署比较简单,因为毕竟只是一个单体项目。首先这个项目只能部署在linux上,如果使用Windows的话,OJ提交的接口就用不了了。 首先在application.yml中填好你对应的中间件、邮箱服务以及数据源的信息,然后在EmailConst中修改对应的邮件激活链接的地址,然后打包部署即可。 前端部署使用的是nginx,分别要代理前端的目录以及反向代理后端服务,网上的配置也很多,这里我就不贴了。