使用AWS Amplify、Lambda、API Gateway和DynamoDB部署静态Web应用

news/2025/9/23 13:44:16/文章来源:https://www.cnblogs.com/qife122/p/19107046

如何使用AWS Amplify、Lambda、API Gateway和DynamoDB部署静态Web应用

构建现代Web应用通常涉及复杂的设置和服务器管理,但其实不必如此。Amazon Web Services(AWS)提供了一套强大的"无服务器"服务,让您能够构建和部署应用而无需担心底层基础设施。这意味着AWS会为您处理所有繁重的服务器、扩展和维护工作。

在本教程中,我们将引导您使用几个关键的AWS无服务器服务构建一个简单但功能完整的Web应用。您将学习如何将前端(用户看到的界面)与强大的后端(处理数据的部分)连接起来,实现自动高效的扩展。

目录

  • 我们将构建什么:无服务器求和计算器
  • 核心AWS服务介绍
  • 先决条件:需要准备什么
  • 开始构建:如何构建我们的无服务器Web应用
  • 如何测试应用:是否正常工作?
  • 常见问题及解决方案
  • 下一步:增强您的应用
  • 结论

我们将构建什么:无服务器求和计算器

我们将创建一个简单的求和计算器Web应用。该应用将允许用户输入两个数字,将其发送到我们的AWS后端进行计算,存储结果,然后将求和结果返回给用户。

计算器的工作流程如下:

  1. 接收用户输入:在简单网页中输入两个数字
  2. 后端处理:这些数字将发送到运行在AWS Lambda上的代码,进行相加计算
  3. 数据存储:计算详情(两个数字、它们的和以及计算时间)将保存在名为DynamoDB的高速数据库中
  4. 显示结果:求和结果将返回到网页并显示给用户

这个项目是理解无服务器架构核心概念以及不同AWS服务如何协同工作创建动态Web应用的绝佳方式。

核心AWS服务介绍

在深入之前,让我们熟悉将要使用的主要AWS服务。将它们视为专业工具,每个都有特定职责,共同构建我们的应用。

AWS Lambda:想象一下有一个只在收到特定任务时才激活的小机器人。这就是Lambda!它是"无服务器计算"服务,意味着您不需要管理任何服务器。只需上传代码(本例中的计算器逻辑),Lambda只在需要时运行它。

为什么使用它:它处理我们的后端数学计算(数字相加)。当用户请求求和时,Lambda"唤醒",执行计算,然后返回休眠状态。这很高效且成本效益高,因为您只需为代码实际运行时间付费。

Amazon API Gateway:将其视为后端的门卫或接待员。当您的网页想要与Lambda函数通信时,它不会直接对话。而是将请求发送到API Gateway。

为什么使用它:API Gateway安全地接收来自网页的请求(如"请计算这两个数字的和"),然后告诉正确的Lambda函数唤醒并处理它。它充当后端的安全入口点,确保只有授权请求才能通过。

Amazon DynamoDB:这是我们高速、灵活的数据库。与传统数据库不同,DynamoDB是NoSQL数据库,非常适合快速高效处理大量数据而无需固定结构。

为什么使用它:我们将使用DynamoDB存储计算历史(输入的数字及其和)。它设计用于处理大量流量而不会减慢速度,非常适合需要快速存储和检索数据的Web应用。

AWS Amplify:Amplify就像您的Web和移动应用个人施工队。它简化了构建、部署和托管前端应用的过程,并与其他AWS服务无缝集成。

为什么使用它:我们将使用Amplify托管简单的HTML、CSS和JavaScript网页。它提供了将网站上线互联网的简单方法,为我们处理所有复杂的部署步骤。

先决条件:需要准备什么

要跟随本教程,您应该具备:

  • AWS账户:这是访问所有AWS服务所必需的
  • Python基础知识:我们的后端逻辑将使用Python编写
  • REST API理解:了解API是什么以及RESTful API的工作原理会有帮助
  • HTML/CSS/JavaScript熟悉度:我们的前端将使用这些标准Web技术构建
  • NoSQL基础知识:虽然不是严格要求,但理解数据库中的键值对概念会有益

开始构建:如何构建我们的无服务器Web应用

我们将逐步构建应用,从数据库开始,然后是后端代码,通过API连接它们,最后部署前端。

步骤1:使用Amazon DynamoDB设置数据库

我们的计算器需要存储计算结果的地方。为此,我们将使用Amazon DynamoDB。

  1. 导航到DynamoDB控制台
    首先登录AWS管理控制台。在顶部搜索栏中输入"DynamoDB"并从结果中选择"DynamoDB"。这将带您进入DynamoDB仪表板。

  2. 创建新表
    在DynamoDB仪表板上,找到并点击"Create table"按钮。

  3. 配置表
    需要为表添加以下信息:

    • 表名:输入myTable
    • 分区键:输入ID

    分区键是DynamoDB中每个唯一项的主要标识符。将其视为每个记录的唯一ID号。它帮助DynamoDB快速查找和分布数据。

    保留所有其他设置为默认值。

  4. 完成表创建
    点击页面底部的"Create table"按钮。DynamoDB现在将创建您的表,通常需要几秒钟。

  5. 重要:记下表ARN
    表创建后,点击列表中的名称(myTable)进入其详细信息页面。在"Summary"选项卡下,您将找到显示"ARN"的部分。这是在AWS中唯一标识DynamoDB表的标识符。
    复制整个ARN并安全保存(如记事本)。稍后设置Lambda函数权限时需要它。

步骤2:使用AWS Lambda创建后端逻辑

现在我们有了数据库,让我们创建操作的核心:执行加法并保存结果的Lambda函数。

  1. 导航到Lambda控制台
    在AWS管理控制台搜索栏中输入"Lambda"并从结果中选择"Lambda"。这将带您进入Lambda仪表板。
    然后点击仪表板上的"Create function"按钮创建新函数。

  2. 配置函数
    配置您的函数:

    • 选择"Author from scratch"
    • 函数名:给函数起有意义的名字,例如SumCalculatorFunction
    • 运行时:选择"Python 3.9"(或可用的最新Python 3.x运行时)
    • 架构:保留为x86_64(默认)
    • 权限:暂时保留默认执行角色
  3. 创建函数
    点击底部的"Create function"按钮创建函数。

  4. 编写Lambda函数代码
    函数创建后,您将进入其配置页面。向下滚动到"Code source"部分。这是编写或粘贴Python代码的地方。
    您将看到默认的lambda_function.py文件。将其内容替换为以下Python代码:

import json
import boto3
import time
from botocore.exceptions import ClientError# 创建DynamoDB客户端
dynamodb = boto3.resource('dynamodb')
# 指定要交互的DynamoDB表
table = dynamodb.Table('myTable')def lambda_handler(event, context):# 从event数据中提取数字num1 = event.get('num1')num2 = event.get('num2')# 基本验证:检查是否提供了两个数字if num1 is None or num2 is None:return {'statusCode': 400,'body': json.dumps({'message': 'Both num1 and num2 are required'})}# 计算两个数字的和sum_result = num1 + num2# 为DynamoDB项生成唯一IDpartition_key = str(int(time.time() * 1000))sort_key = str(int(time.time()))# 准备要存储在DynamoDB表中的数据item = {'ID': partition_key,'Timestamp': sort_key,'num1': num1,'num2': num2,'sum': sum_result}# 尝试将项存储在DynamoDB表中try:table.put_item(Item=item)except ClientError as e:return {'statusCode': 500,'body': json.dumps({'message': f'Error storing data in DynamoDB: {e.response["Error"]["Message"]}'})}# 如果一切成功,返回成功消息和计算详情return {'statusCode': 200,'body': json.dumps({'message': 'Sum calculated and stored successfully','result': {'ID': partition_key,'Timestamp': sort_key,'num1': num1,'num2': num2,'sum': sum_result}})}
  1. 部署代码
    粘贴代码后,点击代码编辑器上方的"Deploy"按钮。这将保存更改并使其生效。

  2. 测试Lambda函数
    代码部署后,测试Lambda函数(可选但推荐)。点击"Deploy"按钮旁边的"Test"按钮。系统将提示配置测试事件。
    选择"New event",对于"Event template",选择"hello-world"。将"Event JSON"框中的示例JSON替换为以下测试数据:

    { "num1": 5, "num2": 10 }
    

    给测试事件命名(例如testSum)。然后点击"Save"和"Test"。您应该看到"Status: Succeeded"消息,在"Execution result"选项卡中,您将看到statusCode: 200和计算的和。这确认了Lambda函数正常工作!

更新Lambda函数权限(IAM角色策略)

我们的Lambda函数当前具有默认权限,通常不包括访问DynamoDB的权限。我们需要明确授予它写入myTable的权限。我们将通过IAM角色策略实现。

  1. 导航到权限
    在Lambda函数配置页面上,点击"Configuration"选项卡。然后选择"Permissions"子选项卡。
    您将看到带有"Role name"的"Execution role"部分。点击此"Role name"(它将是一个链接)。这将带您进入IAM控制台,特别是与Lambda函数关联的角色详细信息。

  2. 添加权限
    在IAM角色页面上,您将看到标题为"Permissions policies"的部分。点击"Add permissions"然后选择"Create inline policy"。

  3. 配置策略
    您将看到"Policy editor"。点击"Visual editor"选项卡(如果尚未选择)。

    • 服务:点击"Choose a service"并搜索选择"DynamoDB"
    • 操作:在"Actions"部分,展开"Write"。搜索PutItem并选择复选框
    • 资源:点击"Specific",点击"Add ARN",粘贴之前从步骤1复制的DynamoDB表ARN
  4. 审查并创建策略
    点击"Next: Review policy"。给策略起有意义的名字,例如DynamoDBPutItemPolicy。
    审查策略JSON确保它授予对特定myTable ARN的dynamodb:PutItem权限。然后点击"Create policy"。

现在您的Lambda函数具有写入DynamoDB表所需的权限!

步骤3:使用Amazon API Gateway连接前端和后端

现在我们有了Lambda函数,我们需要让网页能够与之通信。这就是API Gateway的作用。

在AWS管理控制台搜索栏中输入"API Gateway"并从结果中选择"API Gateway"。

  1. 创建新API
    在API Gateway仪表板上,在"REST API"下,点击"Build"按钮。

  2. 配置API设置

    • 选择协议:选择REST
    • 创建新API:选择New API
    • API名称:给API起清晰的名字,例如SumCalculatorAPI
    • 端点类型:选择Regional(默认)
      然后点击"Create API"。
  3. 创建资源
    创建API后,您将进入其仪表板。从"Actions"下拉菜单中,选择"Create Resource"。

    • 资源名称:可以保留为calculator或任何有意义的名称
    • 路径部分:保留为/(根路径)
      然后点击"Create Resource"。
  4. 创建方法(POST)
    在左导航面板中选择根资源(/),从"Actions"下拉菜单中,选择"Create Method"。
    从出现的下拉列表中选择"POST"并点击旁边的复选标记按钮。
    设置详情:

    • 集成类型:选择Lambda Function
    • 使用Lambda代理集成:勾选此框
    • Lambda区域:选择创建Lambda函数的AWS区域
    • Lambda函数:开始输入Lambda函数名称并从下拉列表中选择
      然后点击"Save"。可能会弹出确认添加Lambda权限的窗口。点击"OK"。
  5. 启用CORS
    这是关键步骤!我们的前端(将托管在AWS Amplify上,不同的域)需要权限与API Gateway端点通信。
    仍然选择根资源(/),从"Actions"下拉菜单中,选择"Enable CORS"。将出现对话框。可以接受此简单应用的默认设置。确保POST在"Methods"下被选中,并且"Access-Control-Allow-Origin"设置为'*'。
    然后点击"Enable CORS and replace existing CORS headers"。提示时点击"Yes, replace existing values"。

  6. 部署API
    对API Gateway方法的更改在API"部署"到"阶段"之前不会生效。从"Actions"下拉菜单中,选择"Deploy API"。

    • 部署阶段:选择"[New Stage]"
    • 阶段名称:给阶段起名字,例如dev
    • 阶段描述:(可选)添加描述
      然后点击"Deploy"。
  7. 记下调用URL
    部署后,您将进入"Stages"视图。在左导航面板中点击新创建的阶段(例如dev)。
    您将看到"Invoke URL"。这是API端点的公共URL。
    复制整个调用URL并安全保存。这是我们的前端将用于向Lambda函数发送数字的URL!

步骤4:创建前端Web应用

现在我们的后端已准备好接收请求和处理计算,让我们构建用户将交互的简单网页。我们将使用基本的HTML、CSS和JavaScript。

您需要在计算机上的新文件夹中创建三个文件:index.html、app.js和style.css。

index.html(网页结构)

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Sum Calculator</title><link rel="stylesheet" href="style.css">
</head>
<body><h1>SUM CALCULATOR</h1><form id="calculatorForm"><label for="num1">Number 1:</label><input type="number" id="num1" required><label for="num2">Number 2:</label><input type="number" id="num2" required><button type="submit" id="calculateBtn"><span id="btnText">CALCULATE</span><span id="loadingSpinner" class="spinner d-none"></span> </button></form><div id="errorAlert" class="alert d-none"><strong style="color: red;">Error!</strong> <span id="errorMessage"></span></div><div id="resultSection" class="result-box d-none"><h2>Calculation Result:</h2><p><strong>Transaction ID:</strong> <span id="resultId"></span></p><p><strong>Timestamp:</strong> <span id="resultTimestamp"></span></p><p><strong>Numbers:</strong> <span id="resultNum1"></span> + <span id="resultNum2"></span></p><p><strong>Sum:</strong> <span id="resultSum"></span></p></div><script src="app.js"></script>
</body>
</html>

app.js(前端逻辑)
记住将替换为从步骤3复制的实际调用URL!

document.addEventListener('DOMContentLoaded', function() {const API_ENDPOINT = 'https://YOUR_API_GATEWAY_INVOKE_URL_HERE.execute-api.us-east-1.amazonaws.com/dev';const calculatorForm = document.getElementById('calculatorForm');const num1Input = document.getElementById('num1');const num2Input = document.getElementById('num2');const calculateBtn = document.getElementById('calculateBtn');const btnText = document.getElementById('btnText');const loadingSpinner = document.getElementById('loadingSpinner');const errorAlert = document.getElementById('errorAlert');const errorMessage = document.getElementById('errorMessage');const resultSection = document.getElementById('resultSection');const resultId = document.getElementById('resultId');const resultTimestamp = document.getElementById('resultTimestamp');const resultNum1 = document.getElementById('resultNum1');const resultNum2 = document.getElementById('resultNum2');const resultSum = document.getElementById('resultSum');calculatorForm.addEventListener('submit', function(event) {event.preventDefault();errorAlert.classList.add('d-none');resultSection.classList.add('d-none');const num1 = parseFloat(num1Input.value);const num2 = parseFloat(num2Input.value);if (isNaN(num1) || isNaN(num2)) {showError('Please enter valid numbers');return;}setLoadingState(true);const requestData = {num1: num1,num2: num2};fetch(API_ENDPOINT, {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(requestData)}).then(response => {if (!response.ok) {return response.json().then(errData => {throw new Error(errData.message || 'Server error');});}return response.json();}).then(data => {setLoadingState(false);if (data.statusCode && data.statusCode === 200 && data.body) {try {const resultData = typeof data.body === 'string' ? JSON.parse(data.body) : data.body;displayResult(resultData);} catch (err) {showError('Error parsing the result: ' + err.message);}} else {showError('Unexpected API response format');}}).catch(error => {setLoadingState(false);showError(error.message || 'An error occurred while communicating with the API');});});function showError(message) {errorMessage.textContent = message;errorAlert.classList.remove('d-none');}function setLoadingState(isLoading) {if (isLoading) {btnText.textContent = 'Calculating...';loadingSpinner.classList.remove('d-none');calculateBtn.disabled = true;} else {btnText.textContent = 'CALCULATE';loadingSpinner.classList.add('d-none');calculateBtn.disabled = false;}}function displayResult(data) {if (!data.result) {showError('No result data in the API response');return;}const result = data.result;let timestampDisplay = result.Timestamp;if (result.Timestamp && !isNaN(result.Timestamp)) {const date = new Date(parseInt(result.Timestamp) * 1000);timestampDisplay = date.toLocaleString();}resultId.textContent = result.ID || 'N/A';resultTimestamp.textContent = timestampDisplay || 'N/A';resultNum1.textContent = result.num1;resultNum2.textContent = result.num2;resultSum.textContent = result.sum;resultSection.classList.remove('d-none');}
});

style.css(页面样式)

body {background-color: #222629;color: #FFFFFF;font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;padding: 20px;display: flex;flex-direction: column;align-items: center;min-height: 100vh;margin: 0;
}h1 {color: #86C232;margin-bottom: 30px;
}label {font-size: 18px;margin-right: 10px;display: inline-block;width: 80px;text-align: right;
}input[type="number"] {background-color: #333;border: 1px solid #444;color: #FFFFFF;padding: 8px 12px;font-size: 16px;border-radius: 5px;margin-bottom: 15px;width: 150px;outline: none;
}input[type="number"]:focus {border-color: #86C232;box-shadow: 0 0 0 3px rgba(134, 194, 50, 0.5);
}button {background-color: #86C232;border: none;color: #FFFFFF;font-size: 18px;font-weight: bold;padding: 10px 20px;border-radius: 5px;cursor: pointer;transition: background-color 0.3s ease;display: flex;align-items: center;justify-content: center;gap: 10px;margin-top: 20px;width: 180px;
}button:hover:not(:disabled) {background-color: #6a9b2b;
}button:disabled {background-color: #555;cursor: not-allowed;
}#calculatorForm {background-color: #333;padding: 30px;border-radius: 8px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);display: flex;flex-direction: column;align-items: flex-start;margin-bottom: 30px;
}.spinner {border: 3px solid rgba(255, 255, 255, 0.3);border-top: 3px solid #FFFFFF;border-radius: 50%;width: 20px;height: 20px;animation: spin 1s linear infinite;
}@keyframes spin {0% { transform: rotate(0deg); }100% { transform: rotate(360deg); }
}.alert {background-color: #330d0d;border: 1px solid #ff4d4d;color: #ff4d4d;padding: 10px 15px;border-radius: 5px;margin-top: 20px;width: 100%;max-width: 400px;text-align: center;
}.result-box {background-color: #333;border: 1px solid #86C232;padding: 20px;border-radius: 8px;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);width: 100%;max-width: 400px;margin-top: 20px;animation: fadeIn 0.5s ease-in-out;
}.result-box h2 {color: #86C232;margin-top: 0;border-bottom: 1px solid #444;padding-bottom: 10px;margin-bottom: 15px;
}.result-box p {margin-bottom: 8px;
}.result-box strong {color: #99EE33;
}.d-none {display: none !important;
}@keyframes fadeIn {from { opacity: 0; transform: translateY(10px); }to { opacity: 1; transform: translateY(0); }
}

步骤5:使用AWS Amplify部署前端

最后,让我们使用AWS Amplify将前端Web应用上线。Amplify使托管静态网站变得异常简单。

  1. 准备前端文件
    确保所有三个文件(index.html、app.js、style.css)在计算机上的单个文件夹中。
    将此文件夹压缩为ZIP文件。确保index.html文件位于ZIP文件的根目录(不在ZIP内的另一个子文件夹中)。

  2. 导航到AWS Amplify控制台
    在AWS管理控制台搜索栏中输入"Amplify"并从结果中选择"AWS Amplify"。

  3. 无Git提供商部署
    在Amplify控制台上,您将看到连接到Git提供商的选项。为简化本教程,我们选择手动部署。
    在"Deploy without Git provider"下,点击"Deploy"。

  4. 上传文件

    • 应用名称:给应用起名字,例如SumCalculatorWebApp
    • 环境名称:可以使用dev或main
    • 拖放或浏览文件:点击"drag and drop"区域或"Choose files"按钮
    • 选择在步骤5.1中创建的ZIP文件
  5. 审查并部署
    现在点击"Save and Deploy"。Amplify将获取ZIP文件,提取其内容,并将静态网站部署到由AWS CloudFront提供的全球内容分发网络。这使您的网站在世界任何地方都能快速加载。此过程可能需要几分钟。

  6. 访问实时应用
    部署完成后,Amplify将提供"Domain" URL。点击此URL。这是您的实时公共Web应用!

如何测试应用:是否正常工作?

现在是最激动人心的部分——通过以下步骤测试我们完全无服务器的Web应用:

  1. 打开Amplify应用URL:导航到AWS Amplify提供的"Domain" URL
  2. 输入数字:在"Number 1"和"Number 2"输入字段中,输入任意两个数字(例如5和10)
  3. 点击"CALCULATE":点击"CALCULATE"按钮。您应该短暂看到按钮上显示"Calculating..."
  4. 观察结果:如果一切设置正确,您应该看到"Calculation Result"框出现在表单下方,显示交易ID、时间戳、数字及其和!
  5. 在DynamoDB中验证(可选):
    • 返回DynamoDB控制台
    • 点击myTable
    • 点击"Explore table items"选项卡
    • 您现在应该看到新条目,对应于在Web应用上执行的每个计算,存储了ID、时间戳、num1、num2和sum!

常见问题及解决方案

有时事情不会第一次就完美工作。以下是一些常见问题及解决方法:

CORS错误

  • 症状:Web浏览器开发者控制台显示错误,如"Access to fetch at '...' from origin '...' has been blocked by CORS policy"
  • 解决方案:返回步骤3第5部分(启用CORS)并确保已为API启用CORS。确保POST被选中且Access-Control-Allow-Origin正确配置

Lambda超时

  • 症状:Web应用持续显示"Calculating..."或出现通用错误,在Lambda函数日志中看到"Task timed out"
  • 解决方案:增加Lambda函数的"Timeout"设置

DynamoDB权限错误

  • 症状:Lambda函数执行失败,日志中看到错误如"User: ... is not authorized to perform: dynamodb:PutItem on resource: ..."
  • 解决方案:确保正确添加了dynamodb:PutItem操作并指定了myTable的ARN作为资源

不正确的API Gateway调用URL

  • 症状:前端发出请求但立即失败或浏览器控制台中出现网络错误
  • 解决方案:仔细检查app.js文件中的API_ENDPOINT常量是否与从API Gateway复制的调用URL完全一致

下一步:增强您的应用

这个计算器是一个很好的起点,但您可以显著扩展它:

  • 添加身份验证:实现用户登录和注册,使只有授权用户才能使用计算器
  • 实现错误处理:根据后端发送的内容显示特定错误消息,使前端更健壮
  • 创建计算历史视图:扩展前端以获取和显示DynamoDB中存储的所有过去计算列表
  • 添加输入验证:在前端和后端实现更健壮的验证以处理非数字输入或其他边缘情况
  • 实现实时更新:使用AWS AppSync或带有API Gateway的WebSocket将新计算结果实时推送到前端,无需页面刷新

结论

恭喜!您已成功在AWS上构建并部署了功能完整的无服务器Web应用。您已经了解了如何利用强大的服务如AWS Lambda、Amazon API Gateway、Amazon DynamoDB和AWS Amplify来创建可扩展、成本效益高且维护量低的应用。

这种架构非常强大,因为它可以自动扩展以处理数千甚至数百万用户,而您无需管理单个服务器。请记住在完成实验后清理AWS资源以避免不必要的费用。

进一步学习资源

  • AWS Lambda文档:深入了解无服务器函数
  • Amazon DynamoDB开发指南:了解更多关于NoSQL数据库的知识
  • Amazon API Gateway教程:探索构建各种类型的API
  • AWS Amplify文档:发现构建和部署全栈应用的更多功能
    更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
    公众号二维码

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

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

相关文章

有没有做培养基的网站服务公司理念

【说明】文章内容来自《机器学习——基于sklearn》&#xff0c;用于学习记录。若有争议联系删除。 1、评价指标 对于模型的评价往往会使用损失函数和评价指标&#xff0c;两者的本质是一致的。一般情况下&#xff0c;损失函数应用于训练过程&#xff0c;而评价指标应用于测试过…

上海制作网站公司哪家好推广广告

存储引擎 MySQL体系结构 连接层&#xff1a; 最上层是一些客户端和连接服务&#xff0c;主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。服务层&#xff1a; 第二层架构主要完成大多数的核心服务功能&…

那个网站做国外售货用ps做网站尺寸

创作不易&#xff0c;请大家多鼓励支持。 在现实生活中&#xff0c;很多人的资料是不愿意公布在互联网上的&#xff0c;但是我们又要使用人工智能的能力帮我们处理文件、做决策、执行命令那怎么办呢&#xff1f;于是我们构建自己或公司的私人GPT变得非常重要。 先看效果 他的…

织梦采集侠官方网站济南 网站 建设

1.委托模式 委托模式&#xff1a;操作对象不会去处理某段逻辑&#xff0c;而是会把工作委托给另外一个辅助对象去处理。 例如我们要设计一个自定义类的来实现Set&#xff0c;可以将该实现委托给另一个对象&#xff1a; class MySet<T> (val helperSet: HashSet<T>…

上海网站开发怎么做苏州网页制作设计

一、简述传统的lru链表lru&#xff1a;least recently used相信大家对lru链表是不陌生的&#xff0c;它算是一种基础的数据结构吧&#xff0c;而且想必面试时也被问到过什么是lru链表&#xff0c;甚至是让你手写一个lru链表。想必你已经知道了mysql的buffer pool机制以及mysql组…

不用vip也能看的黄台的app中山seo技术

题目传送门&#xff1a;LOJ #3156。 题意简述&#xff1a; 有一张 \(n\) 个点 \(m\) 条边的有向图&#xff0c;边有两个权值 \(p_i\) 和 \(q_i\)&#xff08;\(p_i<q_i\)&#xff09;表示若 \(p_i\) 时刻在这条边的起点&#xff0c;则 \(q_i\) 时刻能到达这条边的终点。 你需…

推荐微网站建设哪家网站建设公司好

基础命令 1、ls(list) 用法1: # ls 含义: 列出当前工作目录下所有的 文件/文件夹 的名称 用法2: # ls 路径 含义: 列出指定路径目录下所有的 文件/文件夹 的名称 用法3: # ls 选项 路径 含义: 以指定的格式来显示指定目录下文件夹的名称 栗子: # ls -l 路径 -->> 表…

vscode的ssh-remote插件经常掉线

现象: 本地的mobaxterm的连接服务器一直是好的,vscode编辑服务器上的代码会一会儿就断线,写入不成功,要不就是ssh断开了,需要重新加载窗口。成功解决: 把服务器,属主目录下的vscode相关的全部删除掉,然后重新连…

商业性质网站设计医院客户做网站找谁

1. 用法 返回指定日期的给定日期部分的名称&#xff0c;如年份、月份、星期几等。 2. 语法 DATENAME ( datepart , date )datepart DATENAME 将返回的 date 参数的特定部分。 此表列出了所有有效的 datepart 参数 。 select getdate() 2023-12-01 16:25:47.513 datepart缩写…

dede网站制作app制作器软件下载

在处理器以八核成为主流、硬盘以T而论的今天&#xff0c;计算机辅助设计软件是设计师的得力工具。用铅笔、尺子要时间才能画好的一个室内空间平面布置图&#xff0c;如果用CAD可能一个小时都不用就完成了&#xff0c;而且很方便修改&#xff0c;可见在效率方面&#xff0c;电脑…

网站没收录可以做排名汕头seo网络推广服务

本篇文章有ChatGPT生成&#xff0c;觉得说的有理&#xff0c;给予刊登。 微调大型语言模型 描述&#xff1a; 微调是指在一个预训练的语言模型基础上&#xff0c;使用特定任务或领域的特定数据集进行进一步训练。这一过程会更新模型的权重&#xff0c;以提高其在新数据集上…

网站开发的项目流程物流网站后台

公司的服务器可能会存在这样一种情况&#xff0c;具体的应用是部署在一个或多个内网服务器上&#xff0c;然后由一台外网服务器通过代理的方式对外提供服务&#xff0c;例如下图&#xff1a;我们如果需要进入到内网服务器进行操作就必须先要进入外网服务器&#xff0c;然后再远…

所得税汇算是在12366网站做吗网站建设需要建站公司沟通哪些

Unity3D&#xff08;U3D&#xff09; 1.视觉效果&#xff1a;Unity3D相对UE4略逊、手机3D应用、3D游戏轻量级首选&#xff0c;支持跨平台、设备兼容性更好 2.产品力&#xff1a;Unity3D更加多元化&#xff0c;各平台都有代表作&#xff0c;比如《王者荣耀》《炉石传说》《纪念…

建设网站 xp济南网络有限公司

我在2018年,写过一篇《如何对基因组序列进行注释》,简书上有4万多人阅读,CSDN上有8万多人阅读,说明确实有不少人有相关的需求。我自己也琢磨了一段时间,刚好过年回家,简单的梳理一下。 最初的时候,我的思路就是EvidenceModeler(后面简称EVM)的思路,训练不同从头预测…

汽车网站页面上海公司招聘

备用纹理图像规范命令 Alternate Texture Image Specification Commands 二维和一维纹理图像也可以使用直接从帧缓冲区获取的图像数据进行指定&#xff0c;并且可以重新指定现有纹理图像的矩形子区域。 定义一个二维纹理图像 void glCopyTexImage2D( enum target, int level…

乐清英文网站建设wordpress缩略图只生成full

大家在学习entityframework的时候&#xff0c;都知道那linq写的叫一个爽&#xff0c;再也不用区分不同RDMS的sql版本差异了&#xff0c;但是呢&#xff0c;高效率带来了差灵活性&#xff0c;我们无法控制sql的生成策略&#xff0c;所以必须不要让自己缺乏好的工具去监控sql&…

记录第一次CCPC(2025)网络赛前后

2025年09月21 00:38 竹叶雨——竹磬 总起 ​ 今天进行了CCPC系列赛事的第一次尝试,按照总分总的形式,先说一句:非常的爽!在次,先感谢一下同队的队友:沽雨,黯叶。 ​ 接下来就是记录流水账了: 事件1:差点…

河北做网站电话网站开发相关会议

论文笔记整理&#xff1a;谭亦鸣&#xff0c;东南大学博士生&#xff0c;研究方向为跨语言知识图谱问答。来源&#xff1a;NLPCC2018链接&#xff1a;http://tcci.ccf.org.cn/conference/2018/papers/EV7.pdf问题背景与动机作者认为&#xff0c;目前的问题语料生成主要依赖于人…

第四周课前思考

1. 为什么说 Java 中的所有类都 is-a Object? 因为 Object 是所有类的最终父类,其他类都直接或间接继承自 Object 类。 2. 在 JDK 文档中查找 Object 的 toString 方法。说一说,该方法有什么用?使用 Eclipse 查看 …

声像新境:东芝电视以火箭炮SOUND重塑家庭艺术馆新标准

时代斗转星移,科技日新月异。电视从曾经的“镇宅大件”,走到今天成为日常生活的消费电子品,参数虽不断拔高,但童年记忆里那种“整间屋子都被声音点亮”的震撼,却久违难再。或许人们误把性能指标当作体验答案,而忽…