负载均衡式在线OJ判题系统

news2024/11/20 8:31:40

文章目录

    • 负载均衡式在线OJ
      • 1. 演示项目
      • 2. 所用技术及开发环境
          • 所用技术:
          • 开发环境
      • 3. 项目宏观设计
        • I. leetcode结构
        • II.宏观结构
        • III.编写思路
      • 4. compiler服务
            • 1. 编译功能:
            • 2. 运行功能
            • 3. 编译并运行功能
            • 4. 打包成一个网络服务
      • 5. 基于MVC结构的oj服务设计
            • 1. 用户请求的服务路由功能-oj_server.cc
            • 2.Oj-Model
            • 3. Oj_Control
            • 4. Oj_view
            • 5. 判题功能
            • 6. 编辑负载均衡选择功能
      • 6. 设计题库
        • ->文件版题目设计
        • Mysql版本
      • 7. 增加整体Makefile
      • 8. view渲染和前端页面设计(略)
      • 9.总结

负载均衡式在线OJ

1. 演示项目

2. 所用技术及开发环境

所用技术:
  • C++STL标准库
  • Boost准标准库(实现字符串切割)
  • cpp-httplib第三方开源网络库
  • 多进程,多线程
  • ctemplate第三方开源网页渲染库
  • jsoncpp第三方开源序列化,反序列化
  • 负载均衡设计
  • MySQL C connect
  • Ace编辑器和html/css/js/jquery/ajax(了解)
开发环境
  • Centos 7云服务器
  • vscode
  • MySQL Wokbench

3. 项目宏观设计

核心是三个板块

  1. comm:装载着公共的功能板块
  2. compile_server:编译和运行板块
  3. oj_server:获取题目列表,查看文件编写界面,负载均衡。

I. leetcode结构

  • 只实现LeetCode题目列表+在线编程功能

II.宏观结构

在这里插入图片描述

III.编写思路

  1. compile_server服务
  2. oj_server服务
  3. version1文件版在线OJ
  4. 前端页面设计
  5. version2基于MySQL版在线OJ

4. compiler服务

提供的服务:编译并运行代码,得到格式化的相关的结果。

1. 编译功能:

compiler.hpp:只负责实现代码的编译功能.

在这里插入图片描述

  1. 输入需要编译的临时文件名到Compile方法中,只需要文件名,文件路径和后缀在comm/util.hpp中的PathUtil自动完成拼接。AddSuffix()

    util.hpp:装填着公共工具方法。

  2. 创建子进程来进行文件的编译:子进程采用程序替换execlp(),程序替换成程序名为g++实现了将file_name的源文件编译形成的同名可执行文件.exe,若编译时报错形成.stderr同名文件。在这里插入图片描述

  3. 父进程需要等待子进程编译结果waitpid();在这里插入图片描述

    检验编译是否成功就是查看是否形成了同名可执行程序,所以需要引进判断文件是否存在的功能函数:temp/util.hpp/FileUtil::IsFileExits(); 使用系统调用接口stat,检测特定路径下文件的相关属性放到struct stat结构体中,获取文件属性成功即文件存在返回0.
    在这里插入图片描述

    stat获取到的文件信息各自填充到结构体的字段中:
    在这里插入图片描述

  4. g++时产生的错误信息需要放到文件中,便于后续重定向。所以要在编译之前打开错误文件使用系统个调用接口open();
    在这里插入图片描述

  5. newfd作为old的一份拷贝,将原来的显示器文件重定向到标准错误文件中。因为如果g++编译失败会打印到显示屏上,为了不让他打印到显示器所以重定向到文件中,便于后续返回到前端。

在这里插入图片描述

  1. 在过程中的错误信息只是返回了,而要打印的话不选择cout而是引进了日志功能。在comm中添加Log.hpp。当中添加了日志时间戳,所以引入comm/util.hpp/TimeUtil()::GetTimeStamp();

在这里插入图片描述

在这里插入图片描述

2. 运行功能

runner.hpp:

  1. 指明文件名即可,不需要带路径和后缀。

  2. 创建子进程去执行新形成的.exe,也就是temp/同名.exe文件。

  3. 运行结果存在

    • 代码跑完,结果正确
    • 代码跑完结果不正确
    • 代码没跑完,异常中止

    Run方法不需要考虑结果是否正确,正确与否是有给定的测试用例决定的!只考虑是否正确运行完毕

  • 必须知道可执行程序是谁?comm/util.hpp/PathUtil(filename);

  • 一个程序在默认启动的时候

    • 标准输入:不处理,由OJ平台处理
    • 标准输出:程序运行完成,输出结果是什么
    • 标准错误:运行时错误信息,运行时错误写到Stderr中

    把这些临时文件东西全都写到同名文件当中,运行函数只是帮你跑完,结果不关心,最关心的是有没有运行时异常中止。所以报错文件有两个:.Compiler_err编译时报错文件,.std_err运行时报错文件。运行时需要的临时文件也需要.stdin,.stdout,.stderr三个临时文件。

    文件保存运行结果,所以对应的文件需要先都打开。

  • 子进程负责将012的内容重定向到三个文件中,然后调用程序替换函数,因为我们有可执行程序的全称,所以使用execl();

  1. 如何知道程序运行完是异常呢?一定是因为收到了信号!好奇是什么原因异常的?退出信号判定

    返回值>0.程序异常,返回值就是对应的信号编号

    返回值==0,正常运行完毕,结果不关心,保存到对应临时文件中。

    返回值<0,内部错误。

  2. 测试并且添加日志

  3. 设置时间限制和内存限制,以及不同的错误映射不同的原因并且返回。

    setrlimit();在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

终止进程是通过信号中止的。

//测试超出资源限制
#include <iostream>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <signal.h>
void handler(int signo)
{
std::cout << "signo : " << signo << std::endl;
exit(1);
}
int main()
{
//资源不足,导致OS终止进程,是通过信号终止的
for(int i =1; i <= 31; i++){
signal(i, handler);
}
// 限制累计运行时长
// struct rlimit r;
// r.rlim_cur = 1;
// r.rlim_max = RLIM_INFINITY;
// setrlimit(RLIMIT_CPU, &r);
//while(1);
struct rlimit r;
r.rlim_cur = 1024 * 1024 * 40; //20M
r.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_AS, &r);
int count = 0;
while(true)
{
int *p = new int[1024*1024];
count++;
std::cout << "size: " << count << std::endl;
sleep(1);
}
return 0;
}
//内存申请失败
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
signo : 6
[whb@bite-alicloud OnlineJudge]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
...
//CPU使用超时
[whb@bite-alicloud OnlineJudge]$ ./a.out
signo : 24
[whb@bite-alicloud OnlineJudge]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR

3. 编译并运行功能

compile_run.hpp:

temp目录下的用于测试编译运行功能的code.cpp应该是从客户端传过来的。所以,

  • 适配用户的需求,定制通信协议字段
  • 正确调用compile 和 run方法
  • 形成唯一文件名。编译服务随时可能被多个人请求,必须保证传递上来的code形成源文件名称的时候具有本身的唯一性,避免多个用户之间互相影响。
  1. 需要引进网络功能,通过http,client上传一个json cpp。认识jsoncpp
    在这里插入图片描述

    所以需要jsoncpp来实现网络的序列化和反序列化。将结构化数据转化为一个字符串,结构化数据就是用户的各种信息,时间,提交的代码,用户名等等,我们需要将他之转化为字符串。

  2. 输入应该有字段:

    • code: 用户提交的代码
    • cpu_limit
    • mem_limit

    输出的字段应该有:

    • status:状态退出码
    • reason:请求结果,解释信息。
    • stdout: 运行结果

    如果有报错:还需要stderr

  3. 解析json串,也就是反序列化的过程,将一大串字符串转化为K-V结构的结构化数据,所以可以根据[]进行获取对应字符串。

  4. 形成唯一文件名放到temp目录下->/comm/util.hpp/UniqFileName();,没有路径和后缀。

    毫秒级时间戳+原子性递增的唯一值:来保证唯一性。<time.h>中的gettimeofday();

    原子性唯一定增的值,C++11中的<atomic.h>定义一个id,为了避免每次调用时重新定义,所以设置为static。

  5. 将code的代码写到文件中,/comm/util.hpp/WriteFile();形成src源文件

    <fstream.h> ostream out(target);

  6. 编译并运行文件全路径下的文件 ,

    • 编译可能存在成功或者失败的情况,都需要进行差错处理。

      编译出错,将Compile_err文件中的内容交给reason,作为失败的原因。/comm/util.hpp/ReadFile();

      读取文件,一行一行读取getline(),不保存行分隔符,但是有的时候需要保存分隔符比如代码中的换行是需要的,还有一些特殊格式是需要保存的。所以添加一个标识符keep=false来确定是否需要保存换行符。

      getline()内部重载了强制类型转换,返回之时bool类型

    • 运行结果,<0属于服务器内部错误,==0是正常运行结束,结果在stdout文件中,使用函数读出来就行,>0就是异常中止信号。而每一种报错都对应着一种信息,所以设计一个映射关系的描述函数:CodeToDes();

      特殊几个情况采用switch-case语句进行处理。引入<signal.h>

  7. 输出out_json就是序列化的过程。

  8. 差错处理

    为了统一化管理避免出现代码冗余,在结尾设置END标签,在每一种情况中设置goto END;注意:在goto语句和END标签之间定义变量是不被允许的,所以都要提前定义好。

  9. 测试时的问题;

    include "compile_run.hpp"
    using namespace ns_compile_and_run;
    //编译服务随时可能被多个人请求,必须保证传递上来的code,形成源文件名称的时候,要具有
    //唯一性,要不然多个用户之间会互相影响
    int main()
    {
    //提供的编译服务,打包形成一个网络服务
    //cpp-httplib
    // in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
    // out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
    // 通过http 让client 给我们 上传一个json string
    // 下面的工作,充当客户端请求的json串
    std::string in_json;
    Json::Value in_value;
    //R"()", raw string
    in_value["code"] = R"(#include<iostream>
    int main(){
    std::cout << "你可以看见我了" << std::endl;
    aaaaaaaa
    return 0;
    })";
    in_value["input"] = "";
    in_value["cpu_limit"] = 1;
    in_value["mem_limit"] = 10240*3;
    Json::FastWriter writer;
    in_json = writer.write(in_value);
    std::cout << in_json << std::endl;
    //这个是将来给客户端返回的json串
    std::string out_json;
    CompileAndRun::Start(in_json, &out_json);
    std::cout << out_json << std::endl;
    return 0;
    }
    
    • R"()",raw string 将括号中的特殊字符按照原生字符打印出来,保持原貌。
    • 但是在测试json_string时赋值给input时,我用\n无法成功,但是在用回车键代替时就可以成功。
    • 预设制的空间限制时太小,以至于程序在加载库的时候都无法完成。
  10. 删除每一次产生的很多临时文件:RemoveTempFile ();

    • 产生的临时文件的个数是不确定的,因为可能在任何时刻报错产生不一致的文件.但是应该有什么我知道,最都有6个。先拼接各种文件,然后再判断temp文件夹中是否有,然后指定删除文件用unlink();重复6次判断就行。

在这里插入图片描述

4. 打包成一个网络服务

引入cpp-httplib 0.7.15,

  • 简介:避免对编译器要求太高。只需要将.h文件拷贝到项目中comm中即可使用,或者放到usr/include目录下。需要更新gcc到gcc7~9,如果没有升级就是编译报错。scl gcc devsettool升级gcc,已经完成升级。
    在这里插入图片描述

用法测试:Makefile中还需要引入-lpthread,因为cpp-httplib是阻塞式原生线程库。

网页访问时,不指定资源时,默认是根目录,在访问hello资源时自动返回后面的内容响应,但是会出现乱码。所以后续添加charset=utf-8编码设置。
在这里插入图片描述

所以,当我们收到req的json串,在Lambda表达式中进行编译运行程序调用,并返回一个json串作为Rsponse的串就可以实现交互。

响应回去应该是"applaction/json"在这里插入图片描述

  • 云服务器版本较低,在用vscode连接时调用高版本gcc太浪费资源导致被干掉了,偶发事件,只需要重启vscode重新连接即可。

这样,响应构建完成因为没有客户端,所以直接建立请求和响应。为了方便测试可以使用postman 进行发送请求个访问。
在这里插入图片描述

5. 基于MVC结构的oj服务设计

本质:建立一个小型网站

  1. 获取首页,用题目列表充当

  2. 编辑区域页面

  3. 提交编译判断题目功能(编译并运行)

  4. Modle:数据交互模块,对题库的增删查的功能(文件版,数据库版)oj_model.hpp

    v:view,通常是拿到数据之后,要进行构建网页,渲染网页内容(浏览器)oj_view.hpp

    c:control,控制器,核心业务逻辑。oj_control.hpp

    • MVC格式,control根据model提供的数据,以view为基准将model数据信息转化成网页。
1. 用户请求的服务路由功能-oj_server.cc

获取所有题目列表

用户根据编号获取题目内容

提交代码使用判题功能(测试用例&编译运行功能)

2.Oj-Model

根据题目list文件,加载所有的题目信息到内存中。,主要用来和数据进行交互,对外提供访问数据的接口。

  1. 根据题目属性,构建Question结构体。

  2. 建立题号-题目细节的映射关系unordered_map<string,Question>.

    • 加载配置文件:先获取到questions/questionlist+题目编号文件 。读取文件列表的同时,填充结构体字段属性。

      • 打开文件 ifstream in(question_list);

      • 按行读取getline();对一行字符串进行指定分隔符的切分,将切分出来的子字符串放到vector中作为输出型参数,comm/util.hpp/StringUtil::SplitString();

        使用boost库中的split方法。安装boost库

        #include<boost/algrithum/string.hpp>

        将vector中的元素一次对应填充给Question.注意转型。

      • 根据题目编号,补充某一个题目的路径字符串,然后根据路径,找到对应文件夹下的三个文件。然后再对文件描述属性,文件预设代码和测试用例属性进行填充。FileUtil::Readfile();

      • 填充好题目属性之后,将题目添加到unordered_map中。

    • 获取所有题目的函数GetAllQuestion();

      将unordered_map中的题目都放到vector数组当中输出。

    • 获取单个题号对应的题目GetOneQuestion();

3. Oj_Control

逻辑控制模块,完成对于请求处理的路由功能。

当用户发起请求之后,我们要返回的是一张填充信息的网页。调用control的方法,获取所有数据然后填充网页。AllQuestions();

ojserver负责获取用户请求,通过control控制器完成服务的路由功能,其中组合了model和view,将数据构建成网页。引入ctemplate网页渲染的库,goole,C/C++的渲染程序。实际上就是将头文件和库文件分别安装到了usr路径下。渲染原理:就是K-V的方式指定。
在这里插入图片描述

渲染现象展示:
在这里插入图片描述

4. Oj_view

获取数据成功之后,返回一个渲染网页。View _view;Expandhtml();需要一个被渲染的网页。所以提供两个网页,template目录下allquestions_html 和onequestion_html供view代码进行渲染。

  • 渲染allquestion:oj_view.cc中指定渲染模板路径,对每一个题目形成数字典。根字典,子字典,开始完成渲染功能。

  • 加载到题目列表之后,根据题号完成对某一个题目的路由。

  • 渲染onequestion:onequestion的网页中,应该具备代码编辑区,题目描述,题目预设代码等。

    形成路径,形成数据字典,获取被渲染的html,开始渲染。在title里添加a标签,使得他具备跳转功能。

  • 如果后续引入了ctemplate,一旦对网页结构进行修改,尽量的每次想看到结果,将server重启一下。ctemplate有 自己的优化加速策略,可能在内存中存在缓存网页数据(old) 。

5. 判题功能

control调用后端服务,提供判题功能。用户提交上来的json 串应该包含code:input: id:

  • 根据题号得到题目信息,GetOneQuestion();

  • 反序列化in_json得到题目信息。

  • 重新拼接用户代码和测试用例代码。客户传进来的连main函数都没有,所以需要和我提供的tailer.hpp进行拼接。

  • 选择负载最低的主机;一直选择,直到有主机可用,都这就是全部挂掉。

  • 发起http请求。->cpp-httplib,定义client对象cli就可以向对端发起请求。

    class httplib::Result res->cli.post(); out_json=res->body;

    result类型就是一个智能指针指向response,是否存在response决定是否请求成功,请求失败是没有response的。
    在这里插入图片描述

    如果状态码status是200,才是成功。如果不是200,即使访问成功也不是我们想要额,就需要重新选择主机。

  • 离线offline();就是将Online下标放到offline数组中,可萌同时有人选择主机,所以要加锁保证安全性。

  • 将结果赋值给out_json返回给用户。

6. 编辑负载均衡选择功能

可以提供服务的主机列表conf文件中,保存机器的部署信息。(一台主机提供不同接口)。

class LoadBalance{};class Machine{};提供服务的主机machine

  • 编辑负载的时候需要引入锁的概念。
  • C++中的锁是禁止拷贝,所以用拷贝锁指针的方式调用这把锁
  • 将各种机器放到vector中,实现负载均衡方法选择,用下标充当主机编号。
  • 在线主机数组和离线主机数组,用id填充数组标识是否在线。
  • 在加载时将所有主机上线:拼接主机路径,在LoadBalance()构造函数中加载。
  • 智能选择 bool SmartChoice(int *id, Machine **m) //解引用是Machine* ,让外面通过地址得到主机
  1. 加载配置文件:打开machine_conf文件,行读取配置机器内容。还需要将ip和端口号进行分割用/comm/util.hpp/stringutil::StringSplit();

    将配置信息填入Machine对象中,然后将所有主机放到online数组中。

  2. 智能选择:更新主机负载进行选择,后续可能离线该主机。

    多执行流可能会同时访问,需要保证数据安全性,上锁。

    • 负载均衡算法:轮询遍历找到最小值,随机数法。
    • 更新负载的方式:递增负载,递减负载。都需要上锁。

6. 设计题库

->文件版题目设计

需要两个文件:

  1. 第一个:题目标号,题目标题,题目难度,时间要求,空间要求
  2. 第二个:题目描述,题目的预设值代码(header.cpp),测试用例代码(tail.cpp)

在题目列表同级文件夹下,创建以题目编号命名的文件夹,文件夹中放着同名题目描述文件,预设代码文件,以及测试用例代码文件。

用户点击提交之后,是将header.cpp和同名的tail.cpp一起提交给后端的compile_run进行编译运行。

  • 下面的代码,我们不想让编译器编译的时候,保留它,而是裁剪掉(g++ -D COMPILER_ONLINE)

    仅仅是为了让我们设计测试用例的时候,不要报错.在后端调用g++的时候加两个选项就行。

ifndef COMPILER_ONLINE 
#include "header.cpp" 
#endif

所以最大的成本是设计测试用例。

Mysql版本

  1. 数据库建立用户并赋权oj_yuanwei,设置数据库和表结构questions。

  2. 录题功能使用MySQL Workbench图形化界面设置。

  3. 连接数据库

    使用第三方库引入的方式,不进行安装。C语言连接

在这里插入图片描述

  1. oj_server基于MVC模式,升级为MYSQL版本只需要将oj_model模块进行更改就行。

  2. 因为有数据库的存在,所以获取题目列表和单个题目只有SQL语句的区别。

  3. 遇到问题内存不够了,需要增加swap区:https://blog.csdn.net/qq_34980668/article/details/119562307

  4. 解决这个问题,需要链接-ldl, dl库是用来做动态库加载的(dynamic load),将-ldl链接选项改到最后才可以 。

8.在这里插入图片描述

  1. 如果页面乱码,需要考虑是否是编码不正确。

7. 增加整体Makefile

/:一共有两个用,一个是防止转义,一个就是续行;

前面加@:可以让他不在命令行上显示。

发布模式:文件夹下只有两个可执行程序和各种配置文件,不然个被人看代码。

只需要将output文件夹发给他就行。

8. view渲染和前端页面设计(略)

9.总结

负载均衡式在线OJ项目中,

  • 负载均衡的依据仅仅是遍历所有机器的使用情况,可以有所提升。
  • 项目所需要安装的插件以及项目过程中遇到的问题以及解决方法都在文章的各个板块中展现。
  • 题库中的题目还有待丰富。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/62481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java IO流(详解)

1. File1. 创建2. 操作1. 获取文件信息2. 目录创建/删除2. IO流1. FileInputStream1. 简单使用2. 读取中文2. FileOutputStream1. 简单使用2. 追加写入3. 文件拷贝4. FileReader1. 简单使用2. 提高读取速度5. FileWriter1. 简单使用6. 节点流和处理流简介7. BufferedReader1. 简…

产品开发需要考虑哪些场景

产品到项目中去&#xff0c;也从项目中来&#xff0c;也就是说产品开发后最终都是会到项目中历练&#xff0c;然后吸取项目中的优点&#xff0c;来补全产品中业务的不足、功能的不足&#xff0c;让产品更加完善&#xff0c;最终成为精品。 每个产品的形成都要多加考虑&#xf…

Github 用户查询案例【基于Vue2全局事件总线通信】

前言&#xff1a; 本次案例是一个基于 Vue2 的全局事件总线通信的仿 Github 用户搜索模块&#xff0c;使用的接口是 Github 官方提供的搜索接口&#xff1a; https://api.github.com/search/users?qxxx&#xff08;发送请求时需要将输入的用户名称绑定替换掉xxx&#xff09;&a…

HTML期末学生大作业-宠物之家网页作业html+css+javascript

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

仪表板支持水印设置,数据集新增脱敏规则支持,DataEase开源数据可视化分析平台v1.17.0发布

12月5日&#xff0c;DataEase开源数据可视化分析平台正式发布v1.17.0版本。 这一版本的功能升级包括&#xff1a;数据集方面&#xff0c;支持将数据集数据按指定条件导出为Excel文件&#xff0c;方便用户对权限范围内的数据进行二次处理。数据集字段支持日期解析格式设置&…

[附源码]计算机毕业设计网约车智能接单规划小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Service层代码单元测试以及单元测试如何Mock

一、背景 接着上一篇文章&#xff1a;单元测试入门篇&#xff0c;本篇文章作为单元测试的进阶篇&#xff0c;主要介绍如何对Springboot Service层代码做单元测试&#xff0c;以及单元测试中涉及外调服务时&#xff0c;如何通过Mock完成测试。 二、Springboot Service层代码单…

[附源码]JAVA毕业设计快递物流管理(系统+LW)

[附源码]JAVA毕业设计快递物流管理&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

华为云低代码技术:让矿区管理“智变”,一览无遗

摘要&#xff1a;基于华为低代码平台&#xff0c;万洲嘉智复用开发了9个数字化管理功能&#xff0c;成功解决了矿区管理的空区和难点&#xff0c;帮助煤矿园区实现了智能化管控。本文分享自华为云社区《【云享伙伴】第10期&#xff1a;华为云低代码技术&#xff1a;让矿区管理“…

[附源码]JAVA毕业设计-旅游产品销售管理-演示录像2020(系统+LW)

[附源码]JAVA毕业设计-旅游产品销售管理-演示录像2020&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff…

660846-99-1, Ac-Arg-Gly-Lys-AMC

Control for the two step histone deacetylase assay with Ac-Arg-Gly-Lys(Ac)-AMC. Ac-RGK-AMC corresponds to the product of the deacetylase reaction, which is subsequently cleaved by trypsin. Ac-精氨酸- gly - lys (Ac)-AMC两步法组蛋白去乙酰化酶测定对照。Ac-RGK…

直击家居建材采购痛点,数商云采购协同系统招投标功能助力企业招采透明高效

在后疫情时代&#xff0c;各类企业的采购与供应链数字化转型已是大势所趋&#xff0c;家居建材企业也不例外。用数字化技术助力建材产业转型&#xff0c;为供采双方提供线上精准对接服务&#xff0c;才能赋能新时代建材供应链。 建设采购平台已是大势所趋。作为企业价值链管理…

[附源码]Python计算机毕业设计Django南通大学福利发放管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

UEditorPlus v2.7.0发布 开放独立文档,附件样式优化

UEditor是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于MIT开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;更符…

Hoops API参考: 3D Graphics System的Set_Color()函数

void Set_Color(const char* color_spec)渲染一个段的内容时改变使用的颜色。还可以用于选择要在高亮模式中使用的曲面特性&#xff0c;以及用于特殊纹理贴图效果。 具体细节 Set_Color(&#xff09;的通用目标是使用这个颜色进行绘制。你可以之只给颜色命令&#xff0c;也可…

警惕 有种过敏叫“牛奶蛋白过敏”

过敏是一个全球性的健康问题。以此为基础。WHO据统计&#xff0c;过敏已成为世界第六大疾病。世界上有3亿人患有哮喘、特应性皮炎、过敏性鼻炎、胃肠道疾病等疾病。美国每年有4%-6%的儿童患有食物过敏。由于环境和食品添加剂的日益复杂&#xff0c;中国和发达国家的过敏性疾病正…

Java项目:SSM简单医院信息管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 管理员角色&#xff1a; 登录,个人资料管理,用户管理,科室管理,医生管理,患者管理,科室项目管理,患者诊疗记录管理等功能。 医生角色包含以下功…

SpringMVC_第1章

SpringMVC_第1章 文章目录SpringMVC_第1章一、SpringMVC简介1 SpringMVC概述问题导入1.1 SpringMVC概述2 入门案例【重点】问题导入2.1 实现步骤2.2 代码实现【第一步】创建web工程&#xff08;Maven结构&#xff09;【第二步】设置tomcat服务器&#xff0c;加载web工程(tomcat…

[附源码]计算机毕业设计基于Springboot楼盘销售管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

闲人闲谈PS之三十六——项目状态控制

**惯例闲话&#xff1a;**最近感觉时间不够用&#xff0c;脑子有很多想法&#xff0c;但是到下笔却感觉总是下不了手&#xff0c;写完一段&#xff0c;感觉和自己想的差距很大&#xff0c;然后有全部删除…这难道就是传说中年纪大了&#xff0c;手脚不停使唤…这让闲人更加焦虑…