基于Spring Cloud Vue3的分布式 OJ系统的设计与实现_第1页
基于Spring Cloud Vue3的分布式 OJ系统的设计与实现_第2页
基于Spring Cloud Vue3的分布式 OJ系统的设计与实现_第3页
基于Spring Cloud Vue3的分布式 OJ系统的设计与实现_第4页
基于Spring Cloud Vue3的分布式 OJ系统的设计与实现_第5页
已阅读5页,还剩44页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

摘要随着互联网技术的迅猛发展和Web技术应用的广泛普及,越来越多的人开始学习编程,故开发一款在线做题系统非常必要。本课题决定设计并开发一款高性能、高安全性的OJ(OnlineJudge,在线判题)系统。该系统基于SpringCloudAlibaba微服务治理方案,实现了各个功能模块的降级处理和解耦合,提高了系统的可扩展性。同时使用RabbitMQ实现系统的异步判题功能来降低系统的负载,最后采用Docker容器技术作为本系统的代码沙箱,有效限制了用户操作并隔离了运行环境,提高了系统的安全性。最终在性能测试中,我们对系统模拟1秒内500个用户同时访问的应用场景,系统的吞吐量达到了40.96/s,错误率为0。充分验证了系统的安全性和高并发性。但使用沙箱执行用户代码存在一定的威胁性,未来OJ系统将向AI判题靠拢。关键词:SpringCloud;在线判题;微服务;Docker;高并发AbstractWiththerapiddevelopmentofInternettechnologyandthewidespreadapplicationofWebtechnology,moreandmorepeoplehavebeguntolearnprogramming,soitisnecessarytodevelopanonlineproblem-solvingsystem.Thistopicdecidedtodesignanddevelopahigh-performance,high-securityOJ(OnlineJudge)system.BasedontheSpringCloudAlibabamicro-servicegovernancescheme,thesystemrealizesthedegradationanddecouplingofeachfunctionalmoduleandimprovesthescalabilityofthesystem.Atthesametime,RabbitMQisusedtorealizetheasynchronousjudgmentfunctionofthesystemtoreducetheloadofthesystem.Finally,Dockercontainertechnologyisusedasthecodesandboxofthesystem,whicheffectivelylimitstheuser'soperationisolatestherunningenvironment,andimprovesthesecurityofthesystem.Finally,intheperformancetest,wesimulatedtheapplicationscenarioof500usersaccessingatthesametimeinonesecond.Thethroughputofthesystemreached40.96/sandtheerrorratewas0.Thesecurityandhighconcurrencyofthesystemarefullyverified.However,thereisacertainthreatinusingasandboxtoexecuteusercode,andtheOJsystemwillmoveclosertoAIjudgmentinthefuture.Keywords:SpringCloud;Onlinejudgment;Micro-service;Docker;Highconcurrency目录第1章绪论 [15]。RBAC是一种广泛使用的权限管理方法,它基于角色的概念来分配和管理权限。在RBAC模型中,用户被分配到一个或多个角色,而角色则与一组权限相关联。这种设计简化了权限管理,并允许灵活地管理用户权限。具体的权限数据库模型设计如图3.6用户模块数据库模型设计图所示。3.6用户模块数据库模型设计图(2)题目模块数据库模型设计一个题目的分类可以汇集多道题目,一道题目也可以属于多个题目分类,而且一道题目可以属于多个题库,一个题库也可以拥有多道题目。题目和题目分类,题目和题库它们都属于多对多的关系。都可以通过一个中间表,把各自的主键进行关联。系统可以使用连表查询,把一个题目分类的所有题目查找出来,或者把一个题库的所有题目查找出来,让题目,题目分类和题库进行解耦合。不仅如此,一道题目可以对应多个题目提交信息,多个题目提交信息也是属于一个题目。题目和题目提交信息存在一对多的关系。为了更快查出题目提交信息所属的题目信息,题目提交表创建了一个外键绑定题目表的主键,让系统更加容易找到题目提交信息所属的题目信息。结合上述需求,本系统设计了题目模块的数据库模型,如图3.7题目模块模型数据库设计图所示。3.7题目模块数据库模型设计图(3)评论模型数据库模型设计一个话题对应多条回复,一条回复只能对应一个话题。话题和评论之间存在一对多的关系。一个话题分类对应多个话题,一个话题只能对应一个话题分类。话题和话题分类,它们之间存在一对多的关系。为了更快的查询出一个话题的所有回复和一个话题分类的全部话题。对此在回复表中创建一个外键来绑定话题的主键。以此来达到快速查询话题的目的。在话题表绑定一个话题分类来达到快速查询话题分类包含的所有话题。本系统设计了评论模块的数据库模型,如图3.8评论模块模型数据库设计图所示。图3.8评论模块数据库模型设计图3.3.2数据库表设计通过上述数据库模型可以转化为具体的数据表。基于企业开发的数据库设计规范,本系统在所有的数据表中都加入了状态,逻辑删除,创建时间,创建人,修改时间,修改人和备注等字段。详细数据表介绍如下:(1)用户表用户表主要用于保存用户信息,主要包含用户账号,用户昵称,用户邮箱,手机号码,用户性别,用户头像和密码等信息。密码采用哈希加密方式进行存储,增强用户账号的安全性。用户表详细信息如表3.1用户表所示。表3.1用户表字段名类型长度允许为空是否为主键注释user_idbigint-不允许是用户IDuser_namevarchar30不允许-用户账号nick_namevarchar30不允许-用户昵称emailvarchar50允许-用户邮箱续表3.1用户表字段名类型长度允许为空是否为主键注释phonenumbervarchar11允许-手机号码sexchar1允许-用户性别avatarvarchar100允许-头像地址passwordvarchar100允许-密码statuschar1允许-账号状态del_flagchar1允许-删除标志login_ipvarchar128允许-最后登录IPlogin_datedatetime-允许-最后登录时间create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(2)角色表该表主要用来记录系统的各种角色的信息。主要包括角色名称,角色权限字符串,和数据权限范围。如下表3.2角色表所示。表3.2角色表字段名类型长度允许为空是否为主键注释role_idbigint-不允许是角色IDrole_namevarchar30不允许-角色名称role_keyvarchar100不允许-角色权限role_sortint-不允许-显示顺序data_scopechar1允许-数据范围menu_check_strictlytinyint1允许-是否关联菜单树statuschar1不允许-角色状态del_flagchar1允许-删除标志create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(3)菜单表菜单表主要是对于系统的功能进行管理,每一个功能对应一个权限,可与角色表的角色信息关联形成一个权限组。该表主要有菜单名称,路由地址,组件路径,父菜单等字段。如下表3.3菜单表所示。表3.3菜单表字段名类型长度允许为空是否为主键注释menu_idbigint-不允许是菜单IDmenu_namevarchar50不允许-菜单名称parent_idbigint-允许-父菜单IDorder_numint-允许-显示顺序pathvarchar200允许-路由地址componentvarchar255允许-组件路径queryvarchar255允许-路由参数is_frameint-允许-是否为外链is_cacheint-允许-是否缓存menu_typechar1允许-菜单类型visiblechar1允许-菜单状态statuschar1允许-菜单状态permsvarchar100允许-权限标识iconvarchar100允许-菜单图标create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(4)题目表题目表主要是用于记录题目各种的信息,包括题目标题,题目标签,题目难度,题目内容,题目答案等基本信息。还关联了题目通过次数,题目提交次数,题目通过率,点赞数等统计信息,还有判题用例,判题配置等判题信息。如下表3.4题目表所示。表3.4题目表字段名类型长度允许为空是否为主键注释idbigint-不允许是题目ID续表3.4题目表字段名类型长度允许为空是否为主键注释titlevarchar100不允许-题目标题tagsvarchar255不允许-题目标签hardnesschar1不允许-题目难度contenttext-不允许-题目内容solutiontext-不允许-题目答案pass_countint-不允许-题目通过数commit_countint-不允许-题目提交数pass_percentdecimal10不允许-题目通过率judge_casetext-不允许-判题用例judge_configtext-不允许-判题配置thumb_countint-不允许-点赞数statuschar1不允许-题目状态del_flagchar1允许-删除标志create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(5)题目分类表题目分块表主要是对题目的类型做一个区分,方便用户根据类型来筛选自己的心仪的题目。该表主要有分类标题,分类详细介绍,分类的状态等字段。如表3.5题目分类表所示。表3.5题目分类表字段名类型长度允许为空是否为主键注释idbigint-不允许是分类IDtitlevarchar64不允许-分类标题detailvarchar500允许-分类描述statuschar1不允许-分类状态del_flagchar1允许-删除标志create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者续表3.5题目分类表字段名类型长度允许为空是否为主键注释remarkvarchar500允许-备注(6)题库表题库表主要用于对一些热门题目或者是自己喜欢的题目进行总结和收集。该表主要有题库标题,题库详细描述,题库状态等字段。如下表3.6题库表所示。表3.6题库表字段名类型长度允许为空是否为主键注释idbigint-不允许是题库IDtitlevarchar64不允许-题库标题detailvarchar500允许-题库描述statuschar1不允许-题库状态del_flagchar1允许-删除标志create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(7)题目提交信息表题目提交表主要是用来用于追踪和管理用户在特定题目上的代码提交记录。这个表不仅详细记录了每次提交的状态,如待判题、判题中和已完成,还关联了题目表,以便用户能够快速回顾和评估自己的做题进度和结果。该表主要有用户使用的语言,用户提交的代码,提交人,判题结果,题目,和判题状态等字段。如下表3.7所示。表3.7题目提交表字段名类型长度允许为空是否为主键注释idbigint-不允许是提交IDlanguagevarchar100不允许-提交语言codetext-不允许-提交代码user_idbigint-不允许-提交人judge_infotext-允许-判题结果续表3.7题目提交表字段名类型长度允许为空是否为主键注释topic_idbigint-不允许-题目IDstatuschar1不允许-判题状态del_flagchar1允许-删除标志create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(8)评论表评论表主要是用来记录用户发表的话题信息。该表主要有话题标题,话题内容,话题发起人,话题类型,话题标签,点赞数,收藏,回复数量等字段。如下表3.8评论表所示。表3.8评论表字段名类型长度允许为空是否为主键注释idbigint-不允许是话题IDtitlevarchar500不允许-话题标题contenttext-不允许-话题内容user_idbigint-不允许-发起人IDtype_idbigint-不允许-话题类型IDtagstext-允许-话题标签thumb_countint-不允许话题点赞数collect_countint-不允许话题收藏数reply_countint-不允许话题回复数statuschar1不允许-话题状态del_flagchar1允许-删除标志create_byvarchar64允许-创建者create_timedatetime-允许-创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注(9)评论回复表回复表主要是用来记录用户对于话题的回复信息。该表主要有关联话题的ID,回复人,回复内容和点赞数等字段。如下表3.9所示。表3.9回复表字段名类型长度允许为空是否为主键注释idbigint-不允许是话题回复IDtalk_idbigint-不允许-话题IDuser_idbigint-不允许-回复人contenttext-不允许-回复内容thumb_countint-不允许-回复点赞数statuschar1不允许-回复状态del_flagchar1允许删除标志create_byvarchar64允许创建者create_timedatetime-允许创建时间update_byvarchar64允许-更新者update_timedatetime-允许-更新时间remarkvarchar500允许-备注3.4本章小结本章首先深入探讨了OJ系统的三个核心角色——学生、教师和管理员对于系统的期望和需求。通过收集和分析各方的观点,明确了系统需要满足的核心功能和特性。基于上述需求分析,对OJ系统的功能进行了细致的整理与划分,最终确定了四大核心模块。接下来,根据系统需要设计的并发性和安全性对本系统进行技术选型,并且设计出系统的软件架构,然后对这四大模块中的判题功能和代码沙箱功能进行了详细的业务流程设计。在数据库模型设计方面,根据业务需求,设计了数据库表结构,确保了数据的完整性和查询效率。通过合理的表关联,为OJ系统提供了坚实的数据支撑。第4章系统实现4.1系统环境搭建4.1.1前端依赖环境(1)核心依赖库(库名–版本–作用)vue–3.2.13–前端开发框架vue-router–4.0.3–路由组件axios–1.6.5–网络请求monaco-deitor–0.45.0–代码编辑器ant-design-vue–4.1.0–前端组件库bytemd-vue-next–1.21.0–Markdown文档编辑器(2)版本管理工具(工具名–版本–作用)Node.js–18.17.0–前端JavaScript渲染引擎npm–9.6.7–依赖库管理工具webpack–4.16.5–包构建工具4.1.2后端依赖环境(1)核心依赖(库名–版本–作用)spring-cloud–Hoxton.SR9–服务端框架spring-cloud-alibaba–2021.0.5.0–服务端框架spring-boot–2.7.18–服务端框架druid–1.2.20–数据库连接池fastjson–2.0.43–JSON解析器spring-security–2.7.18–权限管理mybatis–3.5.10–持久层框架mysql–8.0.33–mysql驱动(2)后端运行环境JDK≥1.8Mysql≥5.7.0Redis≥3.0Maven≥3.0naocs≥2.0.44.2模块实现4.2.1用户模块(1)登录注册当用户首次尝试使用本系统而未进行登录时,系统将智能识别其未登录状态,并友好地引导用户跳转至登录页面进行身份验证。同样,若用户的登录令牌因各种原因而过期,系统也会及时提醒用户,并安全地引导其重新登录。系统的登录界面如图4.1系统登录界面所示。图4.1系统登录界面因为用户刚开始没有账号和密码,所以需要用户去点击右上角的注册按钮,在注册页面填写好自己的注册信息,点击注册按钮即可注册成功。在用户注册的过程中,填写的账号信息会在系统后台进行校验,若已经存在,则会做出相关提示,让用户更换用户名。系统注册界面如图4.2系统注册界面所示。图4.2系统注册界面当用户注册成功后,用户即可使用注册好的账号和密码登录到本系统了。(2)用户管理管理员可以通过系统后台的用户管理模块来管理用户信息。在这一模块中,管理员可以通过用户名,用户的手机号码,用户账号状态和用户创建时间来精确地找到某一个用户,并且可以通过点击表格中的修改按钮,对用户的身份信息进行修改。也可以点击删除按钮对该用户进行删除操作,但是这个删除只是逻辑上的删除,不会从数据库真正删除这一条记录。除此之外,用户还可以点击表格中的更多,可以更改用户的密码或分配用户的角色。用户管理界面如图4.3用户管理界面所示。图4.3用户管理界面(3)角色管理管理员能够通过系统后台的角色管理模块来管理和配置角色权限。在这一模块中,管理员可以通过角色名称,权限字符,角色的状态和创建时间来查找一个已经存在的角色信息。也可以点击新增按钮,填写新增表单的角色基础信息就可以成功添加一个角色。点击表格里的修改按钮,即可对一个已经存在的角色的基础信息进行修改。勾选角色编号旁边的多选框可以对一个角色或者多个角色进行删除操作。点击更多按钮还可以为角色添加其权限。角色管理界面如图4.4角色管理界面所示。图4.4角色管理界面图(4)菜单管理管理员可以通过系统后台的菜单管理模块,为前端页面和功能设置精细化的权限控制。系统通过SpringSecurity框架对权限进行控制,一个接口对应着一个权限,把本系统的权限进行细分,然后再菜单管理模块里面配置。这些配置和角色关联,只有拥有这些权限的角色才能使用该功能。如果用户未获得相应权限,相应的功能或组件将不会在其前端页面中显示,确保系统的安全性和用户界面的清晰度。如图4.5菜单管理界面所示。图4.5菜单管理界面4.2.2题目模块(1)评论用户在登录到系统后就可以看到系统首页。在系统首页中,用户可以看到在首页的左下方存在用户发表的话题,用户可以点击该话题进行评论。用户也可以点击自己喜欢的话题类型,查找自己喜欢的话题进行评论。系统首页如图4.6系统首页界面所示。图4.6系统首页界面(2)题库当用户点击题库时,页面会跳转到题库页面。用户可以选择自己喜欢的题库去做题。题库页面如图4.7题库界面所示。图4.7题库界面(3)题目管理管理员可以通过系统后台的题目模块来管理题目的信息。进入题目管理页面后可以看到系统查询出来已存在的题目信息。管理员可以通过标题,难度和题目状态来快速查询一道题目,并且可以点击表格中的修改,删除按钮对题目进行基本信息的修改,和删除这一条题目记录。也可以通过点击表格上方的新增按钮,填写完题目的基本信息,添加一道题目。如图4.8题目管理界面图所示。图4.8题目管理界面图4.2.3判题模块(1)做题当用户点击首页的做题按钮时,系统会跳转到题目页面,题目页面的上方是题库的信息,左下方存在一个题目的表格,用户可以根据题目分离去查找自己喜欢的题目。当用户已经找到了心仪的题目时,可点击表格中“去做题”按钮,系统就会跳转到一个做题的页面给用户做题。题目页面如图4.9题目界面所示。图4.9题目界面当用户来到做题页面时,该页面的左边展示的是题目的基本信息,包括题目标题,题目标签,题目内容等等信息,右边是一个代码编辑器给用户编写自己的程序。当用户根据题目信息写出自己的答案程序之后,用户可以点击提交的按钮,把自己的答案提交到系统,系统就会自动开启判题逻辑。判题关键代码如附录A所示。如图4.10做题界面所示。图4.10做题界面当用户做完题目后,可以通过点击做题页面上的题解按钮,来查看题目的答案,如图4.11题目题解所示。图4.11题目题解不仅如此,用户还可以点击提交记录查看自己的提交情况,包括提交时间,判题状态,判题的结果,所使用的语言,执行用时和消耗的内存。代码沙箱关键代码如附录B所示。如图4.12提交记录所示。图4.12提交记录(2)题目提交管理管理员可以在系统后台的题目提交模块中对用户的代码提交进行管理。管理员可以查看用户提交代码的所有信息,管理员可以点击修改按钮,给用户人工判题。如图4.13代码提交管理所示。图4.13代码提交管理4.3本章小结本章深入阐述了系统前后端所需的依赖项和运行环境,紧接着从用户模块,题目模块,做题模块展示系统各个组成部分,然后介绍了用户模块的登录注册功能,后台的用户管理功能,角色管理功能,菜单管理功能。还介绍了题目模块的题目管理功能,评论功能,题库功能,最后在介绍做题模块的做题功能和题目管理功能。系统详细展示了系统的操作流程和使用方法。使用户能够更加便捷地掌握系统操作方法,提升使用体验。第5章系统测试5.1测试目的系统测试也是开发过程中很重要的一环。系统在运行过程中,用户发送给系统的参数,用户提交的代码,系统本身的依赖环境,都存在着未知的风险。这些风险是有可能会使系统瘫痪,或者是其中的一个中间件瘫痪导致系统不可用的情况。为了保证系统能够平稳上线和稳定运行。本系统的决定采取两种测试方法分别为系统的功能测试和系统的性能测试。系统的功能测试可以保证系统的功能是否符合预期的功能实现,以此来验证系统有误严重的错误。系统的性能测试能够测量出系统在高负载的情况下是否还能正常工作,以此来验证系统的可靠性。5.2系统测试环境本系统运行的环境如下:系统:Windows11家庭中文版64-bit处理器:13thGenIntel(R)Core(TM)i5-13400(16CPUs),~2.5GHz内存:32768MBRAM5.3系统功能测试功能测试是系统测试的核心环节,它主要验证系统是否按照预定的需求规格说明书来实现各项功能。本系统测试系统的复杂功能。测试结果如表5.1系统功能测试表所示。表5.1系统功能测试表用例编号测试要点测试步骤输入数据预期结果测试结果1登录输入数据到表单信息并提交账号,密码如果输入正确的信息则跳转至首页,否则返回错误信息符合2注册输入数据到表单信息并提交账号,密码,确认密码如果输入正确的信息则跳转至登录页,否则返回错误信息符合续表5.1系统功能测试表用例编号测试要点测试步骤输入数据预期结果测试结果3题目管理对题目进行增删改查操作题目的基本信息如果填写了题目的必填项在则添加成功,否则添加失败,返回错误信息符合4题库管理对题库进行增删改查操作题库的基本信息如果填写了题库的必填项在则添加成功,否则添加失败,返回错误信息符合5做题填写代码并点击提交用户代码如果代码执行结果与题目设定的用例相同则答案正确,否则返回错误信息符合6用户管理对用户进行增删改查操作用户的基本信息如果填写的信息正确,则添加用户成功,否则返回错误信息-符合7角色管理对角色进行增删改查操作角色的基本信息如果填写的信息正确,则添加角色成功,否则返回错误信息-符合8菜单管理对菜单进行增删改查操作菜单的基本信息如果填写的信息正确,则添加菜单成功,否则返回错误信息-符合9评论管理对评论进行增删改查操作评论的基本信息如果填写的信息正确,则添加评论成功,否则返回错误信息-符合续表5.1系统功能测试表用例编号测试要点测试步骤输入数据预期结果测试结果10评论分类管理对评论分类进行增删改查操作评论分类的基本信息如果填写的信息正确,则添加评论分类成功,否则返回错误信息-符合11题目分类对题目分类进行增删改查操作题目分类的基本信息如果填写的信息正确,则添加题目分类成功,否则返回错误信息--符合5.4系统性能测试本次使用测压工具为jmeter。本系统在测试的时候在jmeter中创建了一个线程数为500且运行时间为1秒,循环次数为1的线程组。本次将要被用来测试的接口为本系统的功能最复杂的判题接口。测试过程如图5.1jmeter执行流程,图5.2jmeter聚合报告所示。图5.1jmeter执行流程图5.2jmeter聚合报告在jmeter的性能测试的聚合报告可以看出,在模拟1秒内500个用户同时访问本系统的情况下,最小的响应时间达到了2秒,最大的响应时间为11秒,50%的请求响应时间不超过8秒钟,错误率保持在了0%,吞吐量达到了40.96/s,这说明了系统在大量用户同时访问的情况下,系统依然可以稳定的运行,而且错误率是0%,证明系统具备了稳定性和可靠性。在用户提交代码后,系统通过异步判题机制迅速响应,因为系统采用的是异步判题,通过查看数据库数据发现,所有判题结果都得到了完整的存储和处理,实现了数据的最终一致性。5.5本章小结本章主要是讲述了系统测试的目的,系统测试的环境,系统的功能测试和系统的性能测试。系统的功能测试主要是通过表格,对系统的用户模块的登录注册功能,用户管理功能,角色管理功能,菜单管理功能进行测试,对题目模块的做题功能,题目管理功能,题库管理功能和题目分类管理功能进行测试和对评论模块的评论管理功能展开测试,测试的结果都和预期的结果相符合。因此可以推断出系统功能的安全性。系统的性能测试主要是通过jmeter工具创建线程在指定的时间内并发访问,通过模拟高并发场景下用户同时访问系统,系统依然能够保持稳定的性能,证明了系统的高并发性和处理能力。-第6章总结与展望6.1总结在人工智能的强势来袭中可以看出,编程已经不再是程序员的专属技能,而是成为越来越多人追求的能力之一。因此,本课题基于SpringCloud和Vue3技术实现分布式的OJ系统,本系统具备完整的功能,包括题目管理,自动判题,评论等多个OJ系统的基础功能,满足了OJ系统的基本需求。在经过一系列的开发和测试工作之后,本系统已经实现了预期功能目标。在功能测试方面确保了系统各个模块都能正常运行,用户能够浏览题目、在线编程,并得到自动判题的反馈结果。通过性能测试后,系统体现出了良好的稳定性和承载能力,能够应对大量用户的同时使用。本系统的搭建,为广大编程爱好者提供了一个稳定的学习平台,让大众学习编程变得更加简单和方便。6.2展望尽管本系统已经成功实现了预期的核心功能,但是还是存在着巨大的优化和扩展空间的。下面将列举部分待优化的功能:(1)增加智能推荐功能:引入智能推荐算法,根据用户的编程习惯和水平,为用户推荐合适的题目和练习题。让用户可以更有针对性地提升编程技能。(2)探索AI判题技术:探索机器学习和自然语言处理技术在判题方面的应用,以实现更快速、更准确的代码评测。让用户可以及时得到全面的反馈,更好地改进自己的编程技能。(3)优化界面与提升性能:持续优化系统的界面设计,提升响应速度,并加强数据安全保障。致力于为用户打造一个流畅、安全的学习环境,让用户能够充分享受编程学习的乐趣。在未来,我们将不断努力,把本系统变得更加完善,更好地满足用户的学习编程的需求。参考文献孔钦,叶长青,吴淳阳等.OJ平台在程序设计中的应用分析与实现[J].软件导刊,2020,19(01):172-175.张丽,尹红征,冯志慧.OJ平台在计算机专业教学中的应用[J].电脑知识与技术,2020,16(05):184-185.郝刚,曹玲.基于“云课堂+OJ系统”双平台的混合式教学模式研究与实践[J].广东技术师范大学学报,2023,44(03):75-83.严小雨,王明军,卓尧等.基于开源技术的高校OJ系统部署运维与应用[J].现代信息科技,2024,8(03):89-93+98.吕英华.在线评测系统中判题机的设计与实现[J].无线互联科技,2022,19(06):78-79.李杰.基于Docker的在线评测系统的设计与实现[D].河北科技大学,2021.张旭.基于微服务的代码在线评测系统设计与实现[D].华中科技大学,2022.吴凡,卞建玲,宋振乾等.微服务软件架构设计模式及其应用[J].数字通信世界,2024(01):102-104.沈权.容器云、微服务视角下综合平台应用实践探析[J].电脑知识与技术,2023,19(36):91-94.张玉冰.计算机软件开发中Docker技术应用探讨[J].电脑编程技巧与维护,2023,(12):16-18+22.张荻,孙蓉.计算机软件开发中Docker技术应用分析[J].产业创新研究,2023(12):145-147.唐权,周蓉,张勇.RabbitMQ消息中间件在SpringBoot教学中的应用[J].现代信息科技,2020,4(18):125-127.戴施伟,周凌珉,郑一泓.基于SSM框架和RabbitMQ技术的OJ系统的设计与实现[J].计算机时代,2022,(10):81-84+88.刘佳薇,杨博,刘琪.基于分层架构高可扩展的地铁列车显示屏软件系统研制[J].技术与市场,2023,30(10):27-31.陈海锋,丘美玲.基于RBAC模型的前后端分离系统设计与实现[J].科技创新与应用,2024,14(04):102-105+109.附录附录A:判题核心代码publicclassJavaJudgeStrategyImplimplementsJudgeStrategy{publicclassJavaJudgeStrategyImplimplementsJudgeStrategy{/***执行判题*@paramjudgeContext*@return*/@OverridepublicJudgeInfodoJudge(JudgeContextjudgeContext){JudgeInfojudgeInfo=judgeContext.getJudgeInfo();if("1".equals(judgeInfo.getStatus())){returnjudgeInfo;}Longmemory=Optional.ofNullable(judgeInfo.getMemory()).orElse(0L);Longtime=Optional.ofNullable(judgeInfo.getTime()).orElse(0L);List<String>inputList=judgeContext.getInputList();List<String>outputList=judgeContext.getOutputList();TopicVotopicVo=judgeContext.getTopicVo();List<JudgeCase>judgeCaseList=judgeContext.getJudgeCaseList();JudgeInfojudgeInfoResponse=newJudgeInfo();judgeInfoResponse.setStatus("0");judgeInfoResponse.setTime(time);judgeInfoResponse.setMemory(memory);judgeInfoResponse.setMessage("执行通过");//判断沙箱执行的输出结果是否和预期输出数量相等if(outputList.size()!=inputList.size()){judgeInfoResponse.setMessage("错误解答");returnjudgeInfoResponse;}//依次判断每一项输出和预期输出是否相等for(inti=0;i<judgeCaseList.size();i++){JudgeCasejudgeCase=judgeCaseList.get(i);if(!judgeCase.getOutput().equals(outputList.get(i))){judgeInfoResponse.setMessage("错误解答");}}//判断题目的限制是否符合要求JudgeConfigjudgeConfig=topicVo.getJudgeConfig();IntegerneedMemoryLimit=judgeConfig.getMemoryLimit();IntegerneedStackLimit=judgeConfig.getStackLimit();IntegerneedTimeLimit=judgeConfig.getTimeLimit();IntegerneedTimeLimit=judgeConfig.getTimeLimit();if(memory>needMemoryLimit){judgeInfoResponse.setMessage("超出内存限制");}//Java程序本身需要额外执行10秒钟longJAVA_PROGRAM_TIME_COST=10000L; if((time-JAVA_PROGRAM_TIME_COST)>needTimeLimit){judgeInfoResponse.setMessage("超出时间限制");}returnjudgeInfoResponse;}}附录B:代码沙箱的执行逻辑@Slf4j@Slf4jpublicabstractclassJavaCodeSandboxTemplateimplementsCodeSandbox{privatestaticfinalStringGLOBAL_CODE_DIR_NAME="tmpCode";privatestaticfinalStringGLOBAL_JAVA_CLASS_NAME="Main.java";privatestaticfinalLongTIME_OUT=5*1000L;privatestaticfinalStringSECURITY_MANAGER_PATH="G:\\后端\\yuoj-code-sandbox\\src\\main\\resources\\security";privatestaticfinalStringSECURITY_MANAGER_CLASS_NAME="MySecurityManager";@OverridepublicExecuteCodeResponseexecuteCode(ExecuteCodeRequestexecuteCodeRequest){List<String>inputList=executeCodeRequest.getInputList();Stringcode=executeCodeRequest.getCode();Stringlanguage=executeCodeRequest.getLanguage();//1.把用户代码保存为文件FileuserCodeFile=saveCodeToFile(code);//2、编译代码,得到class文件,获取编译结果ExecuteMessagecompileFileExecuteMessage=compileFile(userCodeFile);System.out.println(compileFileExecuteMessage);//3、执行代码,得到输出结果List<ExecuteMessage>executeMessageList=runFile(userCodeFile,inputList);//4、收集整理输出结果ExecuteCodeResponseoutputResponse=getOutputResponse(executeMessageList);//5、文件清理booleanb=deleteFile(userCodeFile);if(!b){log.error("删除文件失败,文件路径为={}",userCodeFile.getAbsoluteFile());}returnoutputResponse;}/***1.把用户代码保存为文件*@paramcode用户代码*@return*/publicFilesaveCodeToFile(Stringcode){//1、保存用户代码//获取项目根目录StringuserDir=System.getProperty("user.dir");StringglobalCodePathName=userDir+File.separator+GLOBAL_CODE_DIR_NAME;//判断全局代码目录是否存在//判断全局代码目录是否存在if(!FileUtil.exist(globalCodePathName)){//不存在,新建一个FileUtil.mkdir(globalCodePathName);}//把用户的代码隔离存放StringuserCodeParentPath=globalCodePathName+File.separator+UUID.randomUUID().toString();StringuserCodePath=userCodeParentPath+File.separator+GLOBAL_JAVA_CLASS_NAME;FileuserCodeFile=FileUtil.writeString(code,userCodePath,StandardCharsets.UTF_8);returnuserCodeFile;}/***2.编译代码*@paramuserCodeFile用户代码文件*@return*/publicExecuteMessagecompileFile(FileuserCodeFile){//2、编译代码,得到class文件,获取编译结果StringcompileCmd=String.format("javac-encodingutf-8%s",userCodeFile.getAbsoluteFile());try{ProcesscompileProcess=Runtime.getRuntime().exec(compileCmd);ExecuteMessageexecuteMessage=ProcessUtils.runProcessAndGetMessage(compileProcess,"编译");if(executeMessage.getExitValue()!=0){thrownewGlobalException("编译错误");}returnexecuteMessage;}catch(Exceptione){//returngetErrorResponse(e);thrownewRuntimeException(e);}}/***执行文件,获得执行结果列表**@paramuserCodeFile代码文件*@paraminputList用户输入列表*@return*/publicList<ExecuteMessage>runFile(FileuserCodeFile,List<String>inputList){StringuserCodeParentPath=userCodeFile.getParentFile().getAbsolutePath();List<ExecuteMessage>executeMessageList=newArrayList<>();for(StringinputArgs:inputList){StringrunCmd=String.format("java-Dfile.encoding=UTF-8-cp%sMain%s",userCodeParentPath,inputArgs);//StringrunCmd=String.format("java-Dfile.encoding=UTF-8-cp%s;%s-Djava.security.manager=%sMain%s",//userCodeParentPath,SECURITY_MANAGER_PATH,SECURITY_MANAGER_CLASS_NAME,inputArgs);try{try{ProcessrunProcess=Runtime.getRuntime().exec(runCmd);//超时控制newThread(()->{try{Thread.sleep(TIME_OUT);//睡醒就杀死没执行完的进程(runProcess)runProcess.destroy();System.out.println("超时了,中断");}catch(InterruptedExceptione){e.printStackTrace();}}).start();ExecuteMessageexecuteMessage=ProcessUtils.runProcessAndGetMessage(runProcess,"运行");executeMessageList.add(executeMessage);}catch(Exceptione){thrownewGlobalException("程序执行异常");}}returnexecuteMessageList;}/***获取输出结果*@paramexecuteMessageList*@return*/publicExecuteCodeResponsegetOutputResponse(List<ExecuteMessage>executeMessageList){ExecuteCodeResponseexecuteCodeResponse=newExecuteCodeResponse();List<String>outputList=newArrayList<>();//取用时最大值,便于判断是否超时longmaxTime=0;for(ExecuteMessageexecuteMessage:executeMessageList){StringerrorMassage=executeMessage.getErrorMassage();if(StrUtil.isNotBlank(errorMassage)){//执行中存在错误executeCodeResponse.setMessage(errorMassage);executeCodeResponse.setStatus(3);break;}Longtime=executeMessage.getTime();outputList.add(executeMessage.getMessage());if(time!=null){maxTime=Math.max(maxTime,time);}}//输出的数量一样,证明是运行成功的if(outputList.size()==executeMessageList.size()){//正常运行executeCodeResponse.setStatus(1);}executeCodeResponse.setOutputList(outputList);JudgeInfojudgeInfo=newJudgeInfo();JudgeInfojudgeInfo=newJudgeInfo();judgeInfo.setTime(maxTime);//todo借用第三方库来获取内存占用,非常麻烦,//judgeInfo.setMemory();executeCodeResponse.setJudgeInfo(judgeInfo);returnexecuteCodeResponse;}/***5.删除文件*@paramuserCodeFile用户代码文件*@return*/publicbooleandeleteFile(FileuserCodeFile){if(userCodeFile.getParentFile()!=null){StringuserCodeParentPath=userCodeFile.getParentFile().getAbsolutePath();booleandel=FileUtil.del(userCodeParentPath);System.out.println("删除"+(del?"成功":"失败"));returndel;}returntrue;}/***获取错误响应**@parame*@return*/privateExecuteCodeResponsegetErrorResponse(Throwablee){ExecuteCodeResponseexecuteCodeResponse=newExecuteCodeResponse();executeCodeResponse.setOutputList(newArrayList<>());executeCodeResponse.setMessage(e.getMessage());//代码沙箱错误executeCodeResponse.setStatus(2);executeCodeResponse.setJudgeInfo(newJudgeInfo());returnexecuteCodeResponse;}}@Service("docker")@Service("docker")publicclassJavaDockerCodeSandboxImplextendsJavaCodeSandboxTemplate{privatestaticfinalLongTIME_OUT=5*1000L;publicstaticfinalbooleanFIRST_INIT=true;/***创建容器,把文件复制到容器内*@paramuserCodeFile代码文件*@paraminputList用户输入列表*@return*/@OverridepublicList<ExecuteMessage>runFile(FileuserCodeFile,List<String>inputList){StringuserCodeParentPath=userCodeFile.getParentFile().getAbsolutePath();//todo获取默认的DockerClientDockerClientdockerClient=DockerClientBuilder.getInstance("tcp://lxwwa.top:2375").build();//拉镜像Stringimage="openjdk:8-alpine";if(FIRST_INIT){PullImageCmdpullImageCmd=dockerClient.pullImageCmd(image);PullImageResultCallbackpullImageResultCallback=newPullImageResultCallback(){@OverridepublicvoidonNext(PullResponseItemitem){System.out.println("下载镜像中"+item.getStatus());super.onNext(item);}};try{pullImageCmd.exec(pullImageResultCallback).awaitCompletion();System.out.println("镜像下载完成");}catch(InterruptedExceptione){System.out.println("镜像拉取异常");thrownewRuntimeException(e);}}HostConfighostConfig=newHostConfig();//限定内存hostConfig.withMemory(1024*1024*100L);//内存交换分区为0hostConfig.withMemorySwap(0L);//cpu核数hostConfig.withCpuCount(1L);//Linux安全配置选项//hostConfig.withSecurityOpts(Arrays.asList("seccomp=安全管理配置字符串"));//todo绑定文件hostConfig.setBinds(newBind(userCodeParentPath,newVolume("/app")));//hostConfig.setBinds(newBind("/code/code",newVolume("/app")));//创建容器CreateContainerCmdcontainerCmd=dockerClient.createContainerCmd(image);CreateContainerCmdcontainerCmd=dockerClient.createContainerCmd(image);CreateContainerResponsecreateContainerResponse=containerCmd.withHostConfig(hostConfig)//限制网络.withNetworkDisabled(true)//限制用户不能往根目录写文件.withReadonlyRootfs(true).withAttachStdin(true).withAttachStderr(true).withAttachStdout(true).withTty(true).exec();System.out.println("创建容器成功");StringcontainerId=createContainerResponse.getId();//启动容器dockerClient.startContainerCmd(containerId).exec();//dockerexeccontainerIdjava-cp/appMain13//执行命令并获取结果List<ExecuteMessage>executeMessageList=newArrayList<>();for(StringinputArgs:inputList){StopWatchstopWatch=newStopWatch();String[]inputArgsArray=inputArgs.split("");String[]cmdArray=ArrayUtil.append(newString[]{"java","-cp","/app","Main"},inputArgsArray);ExecCreateCmdResponseexecCreateCmdResponse=dockerClient.execCreateCmd(containerId).withCmd(cmdArray).withAttachStdin(true).withAttachStderr(true).withAttachStdout(true).exec();System.out.println("创建执行命令"+execCreateCmdResponse);ExecuteMessageexecuteMess

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论