探索RESTful API开发,构建可扩展的Web服务
介绍
当我们浏览网页、使用手机应用或与各种互联网服务交互时,我们经常听到一个术语:“RESTful API”。它听起来很高深,但实际上,它是构建现代网络应用程序所不可或缺的基础。
什么是RESTful API?
让我们将RESTful API比作您最喜爱的餐厅。想象一下,您坐在舒适的座位上,服务员带来一份菜单。菜单上列出了各种美味佳肴,而您只需告诉服务员您想要的菜肴,服务员就会把它们送到您的桌上。
在这个比喻中,您就是前端应用程序(例如网页或移动应用),而菜单就是API(应用程序接口)。RESTful API的“RESTful”部分指的是Representational State Transfer的缩写,这是一种架构风格,旨在使网络应用程序之间的通信变得简单而直观。RESTful API提供了一种标准的方法来访问和操作网络资源,就像您在餐厅菜单上选择和点餐一样。
RESTful设计原则
想象一下,您的餐厅体验是否会受到服务流程的影响?好的餐厅会遵循一些基本原则,如友好的服务、清晰的菜单和高质量的食材。同样,RESTful API也有一些设计原则:
- 统一接口: API应该具有统一的接口,使其易于理解和使用。
- 状态无关性: 客户端和服务器之间的交互不应该包含关于请求的状态信息。每个请求应该是完全独立的。
- 资源导向: API应该基于资源进行操作,而不是行为。资源可以是任何东西,如用户、产品或订单。
- 自描述性: API响应应该包含足够的信息,以便客户端能够理解如何使用该响应。
为什么选择PHP构建RESTful服务?
现在您可能想知道,为什么选择PHP来构建RESTful服务呢?PHP是一种流行的服务器端编程语言,拥有庞大的开发者社区和丰富的资源库。PHP易于学习和使用,适用于快速开发和迭代。此外,PHP与大多数数据库兼容,包括MySQL、PostgreSQL和SQLite,这使得它成为构建RESTful服务的理想选择。PHP还提供了许多优秀的框架和库,如Laravel和Symfony,可以加速开发过程,并提供了一致的代码结构和最佳实践。所以,选择PHP来构建RESTful服务,您将能够快速、高效地构建稳健且可扩展的应用程序。
实现RESTful端点
实现GET请求
当实现GET请求时,我们的目标是从服务器获取资源的信息。在RESTful API中,GET请求通常用于检索资源。下面是一个详细的实现示例:
// 检查请求方法是否为GET
if ($_SERVER['REQUEST_METHOD'] === 'GET') {// 从请求中获取资源ID$resource_id = isset($_GET['id']) ? $_GET['id'] : null;// 如果未提供资源ID,则返回错误响应if (!$resource_id) {http_response_code(400);echo json_encode(array('error' => 'Resource ID is required'));exit;}// 连接数据库$db_connection = new PDO('mysql:host=localhost;dbname=my_database', 'username', 'password');// 准备查询语句$query = "SELECT * FROM resources WHERE id = :id";$statement = $db_connection->prepare($query);// 绑定参数$statement->bindParam(':id', $resource_id, PDO::PARAM_INT);// 执行查询$statement->execute();// 检查是否找到资源if ($statement->rowCount() === 0) {// 如果未找到资源,则返回404错误响应http_response_code(404);echo json_encode(array('error' => 'Resource not found'));exit;}// 从结果集中提取资源信息$resource = $statement->fetch(PDO::FETCH_ASSOC);// 返回资源信息echo json_encode($resource);
}
在上面的示例中,我们首先检查请求是否为GET请求。然后,我们从请求中获取资源ID,并确保资源ID已提供。接下来,我们连接到数据库,并准备执行查询。我们使用PDO来执行查询,这样可以防止SQL注入攻击。如果查询返回了结果,我们提取资源信息并将其编码为JSON格式返回给客户端。如果未找到资源,我们返回404错误响应。
实现POST请求
实现POST请求时,我们的目标是在服务器上创建新资源。在RESTful API中,POST请求通常用于向服务器提交数据,以创建新的资源。以下是一个详细的实现示例:
// 检查请求方法是否为POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {// 从请求主体中获取提交的数据$data = json_decode(file_get_contents('php://input'), true);// 如果未提交数据,则返回错误响应if (!$data) {http_response_code(400);echo json_encode(array('error' => 'Invalid data submitted'));exit;}// 连接到数据库$db_connection = new PDO('mysql:host=localhost;dbname=my_database', 'username', 'password');// 准备插入语句$query = "INSERT INTO resources (name, description) VALUES (:name, :description)";$statement = $db_connection->prepare($query);// 绑定参数$statement->bindParam(':name', $data['name']);$statement->bindParam(':description', $data['description']);// 执行插入操作$success = $statement->execute();// 检查插入是否成功if (!$success) {// 如果插入失败,则返回错误响应http_response_code(500);echo json_encode(array('error' => 'Failed to create resource'));exit;}// 返回成功响应http_response_code(201); // 201 Createdecho json_encode(array('message' => 'Resource created successfully'));
}
在上面的示例中,我们首先检查请求是否为POST请求。然后,我们从请求的主体中获取提交的数据,并将其解析为关联数组。接下来,我们连接到数据库,并准备执行插入操作的SQL语句。我们使用PDO来执行插入操作,以防止SQL注入攻击。如果插入操作成功,我们返回201 Created响应代码,表示资源已成功创建。如果插入操作失败,我们返回500 Internal Server Error响应代码。
实现PUT请求
实现PUT请求时,我们的目标是更新现有资源的信息。在RESTful API中,PUT请求通常用于更新服务器上的资源。以下是一个详细的实现示例:
// 检查请求方法是否为PUT
if ($_SERVER['REQUEST_METHOD'] === 'PUT') {// 从请求主体中获取提交的更新数据$data = json_decode(file_get_contents('php://input'), true);// 获取要更新的资源ID$resource_id = isset($_GET['id']) ? $_GET['id'] : null;// 如果未提交更新数据或未提供资源ID,则返回错误响应if (!$data || !$resource_id) {http_response_code(400);echo json_encode(array('error' => 'Invalid data or resource ID'));exit;}// 连接到数据库$db_connection = new PDO('mysql:host=localhost;dbname=my_database', 'username', 'password');// 准备更新语句$query = "UPDATE resources SET name = :name, description = :description WHERE id = :id";$statement = $db_connection->prepare($query);// 绑定参数$statement->bindParam(':name', $data['name']);$statement->bindParam(':description', $data['description']);$statement->bindParam(':id', $resource_id, PDO::PARAM_INT);// 执行更新操作$success = $statement->execute();// 检查更新是否成功if (!$success) {// 如果更新失败,则返回错误响应http_response_code(500);echo json_encode(array('error' => 'Failed to update resource'));exit;}// 返回成功响应echo json_encode(array('message' => 'Resource updated successfully'));
}
在上面的示例中,我们首先检查请求是否为PUT请求。然后,我们从请求的主体中获取提交的更新数据,并获取要更新的资源ID。接下来,我们连接到数据库,并准备执行更新操作的SQL语句。我们使用PDO来执行更新操作,以防止SQL注入攻击。如果更新操作成功,我们返回成功的响应。如果更新操作失败,我们返回500 Internal Server Error响应代码。
实现DELETE请求
实现DELETE请求时,我们的目标是从服务器上删除现有资源。在RESTful API中,DELETE请求通常用于删除资源。以下是一个更详细的实现示例:
// 检查请求方法是否为DELETE
if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {// 获取要删除的资源ID$resource_id = isset($_GET['id']) ? $_GET['id'] : null;// 如果未提供资源ID,则返回错误响应if (!$resource_id) {http_response_code(400);echo json_encode(array('error' => 'Resource ID is required'));exit;}// 连接到数据库$db_connection = new PDO('mysql:host=localhost;dbname=my_database', 'username', 'password');// 准备删除语句$query = "DELETE FROM resources WHERE id = :id";$statement = $db_connection->prepare($query);// 绑定参数$statement->bindParam(':id', $resource_id, PDO::PARAM_INT);// 执行删除操作$success = $statement->execute();// 检查删除是否成功if (!$success) {// 如果删除失败,则返回错误响应http_response_code(500);echo json_encode(array('error' => 'Failed to delete resource'));exit;}// 返回成功响应echo json_encode(array('message' => 'Resource deleted successfully'));
}
在上面的示例中,我们首先检查请求是否为DELETE请求。然后,我们从请求中获取要删除的资源ID,并确保资源ID已提供。接下来,我们连接到数据库,并准备执行删除操作的SQL语句。我们使用PDO来执行删除操作,以防止SQL注入攻击。如果删除操作成功,我们返回成功的响应。如果删除操作失败,我们返回500 Internal Server Error响应代码。
身份验证及安全性
当涉及到RESTful API的安全性时,身份验证是至关重要的。以下是关于如何使用JSON Web Tokens (JWT) 进行身份验证以及一些安全性的详细实现:
使用JSON Web Tokens (JWT) 进行身份验证
JSON Web Tokens (JWT) 是一种用于安全传输信息的开放标准,通常用于在客户端和服务器之间传递身份验证信息。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
-
生成JWT: 当用户登录成功时,服务器生成一个JWT并将其发送回客户端。JWT通常包含用户的唯一标识符(如用户ID)和一些其他信息(如用户名或角色)。
-
发送JWT: 客户端收到JWT后,将其存储在本地,通常使用localStorage或sessionStorage。
-
将JWT包含在每个请求中: 客户端在发送请求时,将JWT包含在请求的Authorization头部中。服务器可以解码JWT并验证用户的身份。
以下是一个使用JWT进行身份验证的示例:
// 检查请求头中是否包含授权信息
$authorization_header = $_SERVER['HTTP_AUTHORIZATION'] ?? null;// 如果未提供授权信息,则返回未授权响应
if (!$authorization_header) {http_response_code(401);echo json_encode(array('error' => 'Unauthorized'));exit;
}// 提取JWT
$jwt = trim(str_replace('Bearer', '', $authorization_header));// 解码JWT
$decoded_jwt = jwt_decode($jwt);// 检查JWT是否有效
if (!$decoded_jwt) {http_response_code(401);echo json_encode(array('error' => 'Invalid token'));exit;
}// 用户身份验证成功
$user_id = $decoded_jwt['user_id'];
安全性最佳实践
除了使用JWT进行身份验证之外,还有一些其他的安全性的设计如下所示:
1. 密码加密
在存储用户密码时,应使用适当的密码哈希算法进行加密,并使用盐值来增加安全性。下面是一个使用PHP中的password_hash函数来加密密码的示例:
// 用户注册时,对密码进行加密并存储到数据库中
$password = 'user_password';
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// 将$hashed_password存储到数据库中
在用户登录时,通过密码哈希验证用户提供的密码是否匹配已存储的哈希值:
// 用户登录时,验证密码
$user_input_password = 'user_input_password';
$stored_hashed_password = 'stored_hashed_password_from_database';
if (password_verify($user_input_password, $stored_hashed_password)) {// 密码验证成功
} else {// 密码验证失败
}
2. 防止SQL注入
使用预处理语句或ORM(对象关系映射)来执行数据库查询,以防止SQL注入攻击。下面是一个使用PDO预处理语句的示例:
// 准备查询语句
$query = "SELECT * FROM users WHERE username = :username AND password = :password";
$statement = $pdo->prepare($query);// 绑定参数
$statement->bindParam(':username', $username);
$statement->bindParam(':password', $password);// 执行查询
$statement->execute();// 获取查询结果
$user = $statement->fetch(PDO::FETCH_ASSOC);
使用预处理语句将用户输入作为参数绑定到查询中,而不是直接将其插入查询字符串中,可以有效地防止SQL注入攻击。
3. 跨站脚本(XSS)保护
对用户输入进行正确的验证和过滤,以防止XSS攻击。在输出用户提供的数据到网页时,应使用合适的编码方式来转义特殊字符。例如,使用htmlspecialchars函数来转义HTML字符:
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
这将确保任何HTML标签都会被转义,从而防止恶意脚本被注入到网页中。
4. 限制访问
使用角色和权限来限制对敏感资源的访问,确保用户只能访问他们有权限访问的资源。在用户登录时,可以将用户的角色和权限信息存储在令牌中,然后在每个请求中验证用户的角色和权限。
5. HTTPS
使用HTTPS协议来加密数据传输,防止数据被窃取或篡改。在配置Web服务器时,应启用HTTPS并配置正确的SSL证书。
6. 定期更新密钥
如果使用JWT或其他令牌进行身份验证,定期更新密钥以增强安全性。定期更换密钥可以减少被猜测到的风险,并且可以确保即使密钥被泄露,也不会对系统造成长期的危害。
通过实施这些安全性措施,可以大大提高RESTful API的安全性,保护用户数据免受各种常见的安全威胁。
异常处理
当设计异常处理机制时,我们需要确保系统能够正确处理各种可能发生的异常情况,并向客户端提供清晰和友好的错误消息。以下是如何设计良好的错误处理机制和自定义错误响应的详细实现:
设计良好的错误处理机制
在设计良好的错误处理机制时,我们应该考虑以下几个方面:
-
捕获异常: 在代码中,我们应该使用try-catch块来捕获可能发生的异常。这样可以确保即使发生异常,也不会导致整个应用程序崩溃。
-
记录错误信息: 当捕获到异常时,我们应该记录错误信息,以便于后续的故障排除和调试。可以将错误信息记录到日志文件中或将其发送到监控系统。
-
提供友好的错误消息: 向客户端返回友好的错误消息,以帮助用户理解发生了什么问题,并可能提供解决方案。
下面是一个简单的异常处理机制的示例:
try {// 尝试执行某些可能会抛出异常的代码$result = some_code_that_may_throw_an_exception();
} catch (Exception $e) {// 捕获异常并记录错误信息error_log('An error occurred: ' . $e->getMessage());// 返回500 Internal Server Error响应http_response_code(500);echo json_encode(array('error' => 'An error occurred. Please try again later.'));exit;
}
自定义错误响应
在处理异常时,我们还可以根据具体的情况提供自定义的错误响应。例如,如果客户端提交的数据不合法,则可以返回400 Bad Request响应。如果客户端尝试访问未经授权的资源,则可以返回401 Unauthorized响应。
下面是一个自定义错误响应的示例:
// 捕获自定义异常
try {if ($invalid_data) {throw new InvalidArgumentException('Invalid data submitted');}
} catch (InvalidArgumentException $e) {// 捕获自定义异常并记录错误信息error_log('Invalid argument: ' . $e->getMessage());// 返回400 Bad Request响应http_response_code(400);echo json_encode(array('error' => 'Invalid data submitted'));exit;
}
通过设计良好的错误处理机制和提供自定义的错误响应,我们可以确保在应用程序发生异常时,能够及时地向客户端提供清晰和友好的错误消息,从而提高用户体验并方便故障排除。
结语
无论是初学者还是有经验的开发者,构建和维护RESTful API都是一个常用的技能。随着不断地学习和实践,你将逐渐掌握这一技能,并能够构建出更加强大和稳健的API系统。在这个不断变化和发展的技术领域,持续学习和探索是取得成功的关键。祝愿你在编程开发的旅程中取得成功!
相关文章:
探索RESTful API开发,构建可扩展的Web服务
介绍 当我们浏览网页、使用手机应用或与各种互联网服务交互时,我们经常听到一个术语:“RESTful API”。它听起来很高深,但实际上,它是构建现代网络应用程序所不可或缺的基础。 什么是RESTful API? 让我们将RESTful …...
苹果安卓网页的H5封装成App的应用和原生开发的应用有什么不一样?
H5封装类成App的应用和原生应用有什么不一样?——一对比谈优缺点 1. 开发速度和复用性 H5封装的App优势:一次编写,多平台运行。你只需要使用一种语言编写代码,就可以发布到不同的平台,降低开发成本。 原生应用优势&…...
IO流2.
字符流-->字符流的底层其实就是字节流 public class Stream {public static void main(String[] args) throws IOException {//1.创建对象并关联本地文件FileReader frnew FileReader("abc\\a.txt");//2.读取资源read()int ch;while((chfr.read())!-1){System.out…...
详解MySQL中的PERCENT_RANK函数
目录 1. 引入1. 基本使用2:分组使用3:处理重复值4. 使用优势4.1 手动计算百分等级4.2 使用 PERCENT_RANK 的优势4.3 使用 PERCENT_RANK 5. 总结 在 MySQL 中,PERCENT_RANK 函数用于计算一个值在其分组中的百分等级。 它的返回值范围是从 0 …...
宏任务与微任务
一、宏任务 1、概念 指消息队列中等地被主线程执行的事件 2、种类 script主代码块、setTimeout 、setInterval 、nodejs的setImmediate 、MessageChannel(react的fiber用到)、postMessage、网络I/O、文件I/O、用户交互的回调等事件、UI渲染事件&#x…...
昇思大模型学习·第一天
mindspore快速入门回顾 导入mindspore包 处理数据集 下载mnist数据集进行数据集预处理 MnistDataset()方法train_dataset.get_col_names() 打印列名信息使用create_tuple_iterator 或create_dict_iterator对数据集进行迭代访问 网络构建 mindspore.nn: 构建所有网络的基类用…...
python调用chatgpt
简单写了一下关于文本生成接口的调用,其余更多的调用方法可在官网查看 import os from dotenv import load_dotenv, find_dotenv from openai import OpenAI import httpxdef gpt_config():# 为了安全起见,将key写到当前项目根目录下的.env文件中# find…...
YOLOV8 目标检测:训练自定义数据集
1、下载 yolov8项目:ultralytics/ultralytics:新增 - PyTorch 中的 YOLOv8 🚀 > ONNX > OpenVINO > CoreML > TFLite --- ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreM…...
动态更新自建的Redis连接池连接数量
/*** 定时更新Redis连接池信息,防止资源让费*/private static final ScheduledThreadPoolExecutor DYNAMICALLY_UPDATE_REDIS_POOL_THREAD new ScheduledThreadPoolExecutor(1, new ThreadFactory() {Overridepublic Thread newThread(Runnable r) {Thread thread …...
浅谈设计师的设计地位
在当今这个创意无限的时代,设计师的地位日益凸显。他们以独特的视角和精湛的技能,为我们的生活带来了无尽的色彩与灵感。然而,随着行业的不断发展,设计师如何在众多同行中脱颖而出,提升自己的设计地位呢?答…...
C/C++ string模拟实现
1.模拟准备 1.1因为是模拟string,防止与库发生冲突,所以需要命名空间namespace隔离一下,我们来看一下基本内容 namespace yx {class string{private://char _buff[16]; lunix下小于16字节就存buff里char* _str;size_t _size;size_t _capac…...
微信小程序学习(八):behaviors代码复用
小程序的 behaviors 方法是一种代码复用的方式,可以将一些通用的逻辑和方法提取出来,然后在多个组件中复用,从而减少代码冗余,提高代码的可维护性。 如果需要 behavior 复用代码,需要使用 Behavior() 方法,…...
【The design pattern of Attribute-Based Dynamic Routing Pattern (ADRP)】
In ASP.NET Core, routing is one of the core functionalities that maps HTTP requests to the corresponding controller actions. While “Route-Driven Design Pattern” is a coined name for a design pattern, we can construct a routing-centric design pattern base…...
2713. 矩阵中严格递增的单元格数
题目 给定一个 m x n 的整数矩阵 mat,我们需要找出从某个单元格出发可以访问的最大单元格数量。移动规则是可以从当前单元格移动到同一行或同一列的任何其他单元格,但目标单元格的值必须严格大于当前单元格的值。需要返回最大可访问的单元格数量。 示例…...
git创建子模块
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。 Git …...
把Deepin塞进U盘,即插即用!Deepin To Go来袭
前言 小伙伴之前在某篇文章下留言说:把Deepin塞进U盘的教程。 这不就来了吗? 事实是可以的。这时候你要先做点小准备: 一个大小为8GB或以上的普通U盘 一个至少64GB或以上的高速U盘 一个Deepin系统镜像文件 普通U盘的大概介绍࿱…...
给【AI硬件】创业者的论文、开源项目和产品整理
一、AI 硬件精选论文 《DrEureka: Language Model Guided Sim-To-Real Transfer》 瑜伽球上遛「狗」这项研究由宾夕法尼亚大学、 NVIDIA 、得克萨斯大学奥斯汀分校的研究者联合打造,并且完全开源。他们提出了 DrEureka(域随机化 Eureka)&am…...
模拟面试题卷二
1. 什么是JavaEE框架,你能列举一些常用的JavaEE框架吗? 答:JavaEE框架是一套用于开发企业级应用的技术规范和工具集合。常用的JavaEE框架有Spring、Hibernate、Struts、JSF等。 2. 请解释一下面向对象技术和设计原则是什么,你能…...
22种常用设计模式示例代码
文章目录 创建型模式结构型模式行为模式 仓库地址https://github.com/Xiamu-ssr/DesignPatternsPractice 参考教程 refactoringguru设计模式-目录 创建型模式 软件包复杂度流行度工厂方法factorymethod❄️⭐️⭐️⭐️抽象工厂abstractfactory❄️❄️⭐️⭐️⭐️生成器bui…...
Java面试题:对比ArrayList和LinkedList的内部实现,以及它们在不同场景下的适用性
ArrayList和LinkedList是Java中常用的两个List实现,它们在内部实现和适用场景上有很大差异。下面是详细的对比分析: 内部实现 ArrayList 数据结构:内部使用动态数组(即一个可变长的数组)实现。存储方式:…...
ping: www.baidu.com: 未知的名称或服务(IP号不匹配)
我用的是VMware上的Red Hat Enterprise Linux 9,出现了能联网但ping不通外网的情况。 问题描述:设置中显示正常连接,而且虚拟机右上角有联网的图标,但不能通外网。 按照网上教程修改了/etc/resolv.conf和/etc/sysconfig/network-…...
谷神前端组件增强:子列表
谷神Ag-Grid导出Excel // 谷神Ag-Grid导出Excel let allDiscolumns detailTable.getAllDisColumns() let columnColIds columns.map(column > column.colId) let columnKeys columnColIds.filter(item > ![select, "_OPT_FIELD_"].includes(item)) detailT…...
测试cudaStream队列的深度
测试cudaStream队列的深度 一.代码二.编译运行[得出队列深度为512] 以下代码片段用于测试cudaStream队列的深度 方法: 主线程一直发任务,启一个线程cudaEventQuery查询已完成的任务,二个计数器的值相减 一.代码 #include <iostream> #include <thread> #include …...
海康威视 isecure center 综合安防管理平台任意文件上传漏洞
文章目录 前言声明一、漏洞描述二、影响版本三、漏洞复现四、修复方案 前言 海康威视是以视频为核心的智能物联网解决方案和大数据服务提供商,业务聚焦于综合安防、大数据服务和智慧业务。 海康威视其产品包括摄像机、多屏控制器、交通产品、传输产品、存储产品、门禁产品、消…...
shadertoy-安装和使用
一、安装vscode 安装vscode流程 二、安装插件 1.安装glsl编辑插件 2.安装shader toy插件 三、创建glsl文件 test.glsl文件 float Grid(float size, vec2 fragCoord) {vec2 r fragCoord / size;vec2 grid abs(fract(r - 0.5) - 0.5) / fwidth(r);float line min(grid…...
matlab线性多部法求常微分方程数值解
用Adamas内差二步方法,内差三步方法,外差二步方法,外差三步方法这四种方法计算。 中k为1和2. k为2和3 代码 function chap1_adams_methodu0 1; T 2; h 0.1; N T/h; t 0:h:T; solu exact1(t);f f1; u_inter_2s adams_inter_2steps(…...
前端页面实现【矩阵表格与列表】
实现页面: 1.动态表绘制(可用于矩阵构建) <template><div><h4><b>基于层次分析法的权重计算</b></h4><table table-layout"fixed"><thead><tr><th v-for"(_, colI…...
GPT4v和Gemini-Pro调用对比
要调用 GPT-4 Vision (GPT-4V) 和 Gemini-Pro,以下是详细的步骤分析,包括调用流程、API 使用方法和两者之间的区别,以及效果对比和示例。 GPT-4 Vision (GPT-4V) 调用步骤 GPT-4 Vision 主要通过 OpenAI 的 API 进行调用,用于处…...
破布叶(Microcos paniculata)单倍型染色体级别基因组-文献精读22
Haplotype-resolved chromosomal-level genome assembly of Buzhaye (Microcos paniculata) 破布叶、布渣叶(Microcos paniculata)单倍型解析染色体级别基因组组装 摘要 布渣叶(Microcos paniculata)是一种传统上用作民间药物和…...
浅谈RC4
一、什么叫RC4?优点和缺点 RC4是对称密码(加密解密使用同一个密钥)算法中的流密码(一个字节一个字节的进行加密)加密算法。 优点:简单、灵活、作用范围广,速度快 缺点:安全性能较差&…...
北方明珠网站建设/如何在百度上发布自己的广告
题目链接:https://vjudge.net/contest/68966#problem/Q 分析:这里的对称并不是指的是关于原矩阵(也就是最大的那一个)主对角线对称,而是对于每一个小的矩阵来说,当前矩阵的对反对角线。 #include<iost…...
广东网站建设需要多少钱/海淀区seo引擎优化
OSI七层网络模型Linux TCP/IP四层概念模型对应网络协议应用层(Application Layer)应用层(Application Layer)TFTP, FTP, NFS表示层(Presentation Layer)Telnet, Rlogin, SNMP,会话层(Session Layer)SMTP…...
做网站郑州/seo相关岗位
目录一、原文摘要二、为什么提出GR-GAN三、GR-GAN3.1、整体框架3.2、逐步求精生成器:GRG3.2.1、图像初始化阶段3.2.2、句子级细化阶段3.2.3、单词级细化阶段3.3、图像文本匹配器:ITM3.4、定量指标:CMD四、实验4.1、实验设置4.2、实验结果4.3、…...
宽城区网站建设/免费seo营销软件
近日使用VMware fushion 8 centos 7.0时,无法使用共享功能,所以必须安装vmtools。但是安装过程中有2个错误需要解决。 1、gcc错误 Searching for GCC... The path "" is not valid path to the gcc binary. 2、内核头文件问题 Searching for …...
做网站是用什么语言的/免费十八种禁用网站
所谓帧定格 Frame Hold,就是获取视频中的某一静帧画面,这一静帧既可以作为素材文件添加到项目面板以备后用,也可直接附加在剪辑上构成定格效果。导出帧在节目面板或源面板的下方都有一个相机图标,用于“导出帧” Export Frame&…...
定西做网站/广州seo技术优化网站seo
基于LabVIEW的S7300PLC与PC机的串口通信2011 仪 表 技 术 与 传 感 器 20115 Instrument Technique and Sensor No5LabV IEW S7- 300 PLC PC刘小丽, 张晓光(, 221116): 根据工业系统设计需求, 采用图形化编程语言 LabVI W 设计了 S7 - 300 PLC和 PC机间的串 通信介绍了使用 396…...