跳至主要内容

使用 AWS Lambda 构建一个无服务器的学生学籍注册管理系统

前提条件

  • 难度:中级
  • 时间:8 - 12 小时
  • 费用:按需付费
  • 受众:开发者
  • 前提条件:具有 AWS 账户/IAM 用户
  • 示例代码:无代码
  • 上次更新时间:2025.11.26
  • 相关行业:通用
  • 相关产品:AWS Lambda, DynamoDB, API Gateway

教程简介

本教程将指导您使用 AWS Lambda 构建一个完整的无服务器学生学籍管理系统。我们将使用 Python 作为开发语言,结合多种 AWS 服务实现一个事件驱动的应用程序。

在项目前期规划 AWS Lambda 设计和实现该系统的解决方案,构建基本软件架构,包含前端静态网站托管在 Amazon S3,后端用 AWS Lambda 函数处理业务逻辑,连接数据库 Amazon DynamoDB 存储学生数据,同时,构建 Amazon API Gateway 以提供 RESTful API 接口;在安全身份验证方面,使用 Amazon Cognito 完成用户池管理用户认证。

  • Amazon Simple Storage Service(Amazon S3)是一种对象存储服务,提供行业领先的可扩展性、数据可用性、安全性和性能。各种规模和行业的客户都可以使用 Amazon S3 存储和保护任意数量的数据,用于数据湖、网站、移动应用程序、备份和恢复、归档、企业应用程序、IoT 设备和大数据分析。
  • NoSQL 数据库(也称为专用数据库)专为特定的数据模型而设计,并将数据存储在可轻松扩展以适应现代应用程序的灵活架构中。许多数据库工作负载可以受益于 NoSQL 数据库的成本效益和性能。本教程使用的数据库 Amazon DynamoDB 是无服务器的,因此资源利用率会自动优化,您无需为超额预置付费。此外,NoSQL 数据库还因其易于大规模开发、强大的功能和良好的性能而被广泛认可。
  • Amazon API Gateway 是一种完全托管的服务,可以帮助开发者轻松创建、发布、维护、监控和保护任意规模的 API。API 充当应用程序的前门,可从您的后端服务访问数据、业务逻辑或功能。使用 API Gateway,您可以创建 RESTful API 和 WebSocket API,以便实现实时双向通信应用程序。API Gateway 支持容器化和无服务器工作负载,以及 Web 应用程序。

本教程需要拥有一个 AWS 账户以及满足 IAM 权限的角色,并确保有操作 S3 和 AWS 其它服务的权限。

第一步 AWS 账户注册与准备事项

全部打开

    首先,您需要登录亚马逊云科技官网:aws.amazon.com 注册一个新用户,作为您的根账户。

    注册用户信息后,使用注册邮箱验证,将6位数字验证码填入后,开始设置密码。

    设置完毕后,点击 Continue (step 1 of 5) 继续注册。

    注册 AWS 有两种账户计划:

    1. 免费(6 个月)计划。可获得最高 200 美元服务抵扣金,以及免费的精选服务;
    2. 付费计划。可获得最高 200 美元服务抵扣金,使用全部 AWS 服务。

    作为初学者,用户可以先采用免费套餐,进行学习交流及试验等。点击“选择免费计划“。

    选择“个人 – 用于您自己的项目“,并填写个人信息。

    接下来,填写银联信用卡/借记卡,或者其它信用卡信息,完成注册。

    然后,进行手机号码安全验证。

    最终,注册成功!AWS 页面出现“恭喜”字样。

    *注意:为了确保账户安全,在注册了 AWS 根账户后,需要访问 Identity Access Management (IAM),用来创建一个具有特定权限的 IAM 用户,为项目专属的 AWS Lambda 服务提供资源访问权限,并在实现强大功能的同时,确保账户安全性。

    在控制台主页下方,还有“探索 AWS”部分,显示待获得的总服务抵扣金有 100 美元。

    五项任务总奖励金额 100 美元,则每项任务为 20 美元。

    本教程系统演示了如何基于 AWS Lambda 构建一套完整的无服务器学生学籍管理系统,体现了现代云原生应用的典型架构思路。系统采用事件驱动设计,前端通过 Amazon S3 托管静态网页,后端使用 AWS Lambda 处理业务逻辑,数据存储借助 Amazon DynamoDB 实现高性能的 NoSQL 持久化,并通过 API Gateway 对外提供 RESTful API 接口,整体实现了解耦、弹性伸缩和按需付费的优势。

    教程的实现路径清晰、层次分明:从账户准备、IAM 权限配置,到数据库表设计与 Lambda 函数编写,再到 API 网关的路由整合与前端页面的部署测试,逐步推进并注重实操细节。其技术特点突出无服务器架构的轻量化、自动化运维和成本可控性,适合中小型应用快速搭建与迭代。通过本教程,开发者不仅能掌握 AWS 核心服务的联动使用,更能理解如何以松耦合、高可用的方式构建可扩展的 Web 应用。

第二步 创建 Dynamo DB 数据表

全部打开

    在管理控制台页面,搜索“DynamoDB”,这是 AWS 提供的 No SQL 数据库服务。

    点击”DynamoDB”进入到 DynamoDB 控制台。

    点击“创建表”按钮。

    创建表时,保证以下信息完整:

    • 表名称,输入: Students;
    • 分区键,输入student_id; 类型为“字符串”;
    • 表设置,选择“默认设置”;
    • 点击“创建表”。

    确认信息后,在页面下方点击“创建表”。

    稍后,便显示”Students 表已成功创建。此时,表”Students”的状态是:活跃。

     

    在Students控制台页面,点击“索引”选项卡,选择“创建索引”。

    在“索引”选项页里,点击“创建索引”。

    • 创建全局二级索引

    成功提交全局二级索引。

     

第三步 创建 IAM 角色

全部打开

    登录 AWS 控制台后,在搜索栏搜索“IAM”服务。

    进入 IAM 管理控制台。

    最上方安全建议部分,要求为根用户添加 MFA。MFA 是多重身份验证(Multi-Factor Authentication)。

    点击“添加 MFA”。

    要求输入 MFA 设备名称,以及选择 MFA 设备。由于使用手机验证非常方便,选择“身份验证器应用程序。点击“下一步”继续。

    在设置设备时,首先,需要在移动设备(如:手机)或计算机上安装 Google Authenticator 等兼容应用程序。

    安装好应用程序(例如:Google Authenticator)后,点击“显示QR代码”(即二维码),然后用手机上的 Authenticator app 扫描该二维码;同时,在手机上 app 接收到的两个依次发出的 6 位数字 MFA 代码,输入正确后,点击“添加 MFA”。

     

    添加 MFA 成功!因此,账户详细信息全部更新。下次登录AWS账户,只需轻松操作手机,与电脑端 AWS Web 页面互动,完成 MFA 代码,即可开始相关研究。

    AWS 账户登录后,在 IAM 控制台页面,点击“角色” ,到“创建角色”。

     

    点击“创建角色”按钮。

     

    弹出“选择可信实体”,按照默认的可信实体类型:“AWS 服务”,使用案例选择“Lambda”,点击“下一步”继续。

     

    在搜索栏中,搜寻”DynamoDB”字样,选择 AmazonDynamoDBFullAccess 服务,点击“下一步”。

     

    再次添加一次权限策略。

     

    添加权限策略(包含 AmazonDynamoDBFullAccess,AWSLambdaBasicExecutionRole),点击“下一步“;输入添加角色名称:StudentManagementLambdaRole, 然后点击“创建角色”。

     

    角色创建成功,位于角色列表中。

第四步 创建 Lambda 函数

全部打开

    在控制台,搜索 “Lambda”服务。

    点击“Lambda进入控制台页面。

    点击“创建函数”。

    按照符合 Mac 电脑要求的处理器(arm64)架构,并且在“更改默认执行角色”中,选择“使用现有角色”,在下拉列表框中,选中刚才创建的角色,点击控制台右下角的“创建函数”按钮。

    点击“创建函数”按钮。

    至此,已成功创建 Lambda 函数。

    • 编写 Lambda 函数

    创建函数后,系统会有一个函数框架显示在代码选项卡。

    根据学生学籍管理系统要求,自行编写函数代码。示例代码如下:

    import json

    import boto3

    from boto3.dynamodb.conditions import Key

    dynamodb = boto3.resource('dynamodb')

    table = dynamodb.Table('Students')

    def lambda_handler(event, context):

    http_method = event.get('httpMethod')

    path = event.get('path')

    if http_method == 'POST' and path == '/students':

    return create_student(event)

    elif http_method == 'GET' and path == '/students':

    return get_all_students(event)

    elif http_method == 'GET' and path.startswith('/students/'):

    return get_student_by_id(event)

    elif http_method == 'PUT' and path.startswith('/students/'):

    return update_student(event)

    elif http_method == 'DELETE' and path.startswith('/students/'):

    return delete_student(event)

    elif http_method == 'GET' and '/classes/' in path:

    return get_students_by_class(event)

    else:

    return response(404, {'message': 'Not Found'})

    def create_student(event):

    try:

    body = json.loads(event.get('body', '{}'))

    student_id = body.get('student_id')

    name = body.get('name')

    age = body.get('age')

    class_name = body.get('class_name')

    email = body.get('email')

    if not all([student_id, name, class_name]):

    return response(400, {'message': 'Missing required fields'})

    item = {

    'student_id': student_id,

    'name': name,

    'age': age,

    'class_name': class_name,

    'email': email

    }

    table.put_item(Item=item)

    return response(201, {'message': 'Student created successfully', 'student': item})

    except Exception as e:

    return response(500, {'message': str(e)})

    def get_all_students(event):

    try:

    result = table.scan()

    return response(200, {'students': result.get('Items', [])})

    except Exception as e:

    return response(500, {'message': str(e)})

    def get_student_by_id(event):

    try:

    student_id = event['pathParameters']['student_id']

    result = table.get_item(Key={'student_id': student_id})

    if 'Item' in result:

    return response(200, {'student': result['Item']})

    else:

    return response(404, {'message': 'Student not found'})

    except Exception as e:

    return response(500, {'message': str(e)})

    def update_student(event):

    try:

    student_id = event['pathParameters']['student_id']

    body = json.loads(event.get('body', '{}'))

    update_expression = "SET "

    expression_attribute_values = {}

    expression_attribute_names = {}

    if 'name' in body:

    update_expression += "#n = :name, "

    expression_attribute_values[':name'] = body['name']

    expression_attribute_names['#n'] = 'name'

    if 'age' in body:

    update_expression += "age = :age, "

    expression_attribute_values[':age'] = body['age']

    if 'class_name' in body:

    update_expression += "class_name = :class_name, "

    expression_attribute_values[':class_name'] = body['class_name']

    if 'email' in body:

    update_expression += "email = :email, "

    expression_attribute_values[':email'] = body['email']

    update_expression = update_expression.rstrip(', ')

    if not expression_attribute_values:

    return response(400, {'message': 'No fields to update'})

    result = table.update_item(

    Key={'student_id': student_id},

    UpdateExpression=update_expression,

    ExpressionAttributeValues=expression_attribute_values,

    ExpressionAttributeNames=expression_attribute_names if expression_attribute_names else None,

    ReturnValues='ALL_NEW'

    )

    return response(200, {'message': 'Student updated successfully', 'student': result.get('Attributes', {})})

    except Exception as e:

    return response(500, {'message': str(e)})

    def delete_student(event):

    try:

    student_id = event['pathParameters']['student_id']

    table.delete_item(Key={'student_id': student_id})

    return response(200, {'message': 'Student deleted successfully'})

    except Exception as e:

    return response(500, {'message': str(e)})

    def get_students_by_class(event):

    try:

    class_name = event['pathParameters']['class_name']

    result = table.query(

    IndexName='class-index',

    KeyConditionExpression=Key('class_name').eq(class_name)

    )

    return response(200, {'students': result.get('Items', [])})

    except Exception as e:

    return response(500, {'message': str(e)})

    def response(status_code, body):

    return {

    'statusCode': status_code,

    'headers': {

    'Content-Type': 'application/json',

    'Access-Control-Allow-Origin': '*',

    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',

    'Access-Control-Allow-Headers': 'Content-Type, X-Amz-Date, Authorization, X-Api-Key, X-Amz-Security-Token'

    },

    'body': json.dumps(body)

    }

    将函数代码替换到默认函数代码位置。

     

    这样,就完成了编写函数过程。

    在代码源页面左侧,分别有两个蓝色按钮“Deploy”(部署)和“Test”(测试)。按照新编写的函数代码,点击“Test”开始测试。继续选择“Create new test event”(创建新的测试事件)。

    点击右侧按钮“Save”保存测试事件。

    再点击右侧“Invoke”(调用)按钮。测试成功!

    在“OUTPUT”(输出)栏,显示测试成功!

    Status: Succeeded
    Test Event Name: StudentTestEvent

    上报测试事件与前面创建的一致。

    部署函数

    测试完毕后,点击“代码源”页面左侧的“Deploy”(部署)按钮,等待部署完毕。

     

    部署成功后,显示“已成功更新函数…”的信息。

第五步 创建 API Gateway

全部打开

    在AWS管理控制台搜索打开”API Gateway”。

    进入到 API Gateway 控制台页面。

    点击“创建API”。在该页面向下滚动,选择“REST API“。

    点击“构建”按钮。

    在“创建 REST API”选项卡,输入创建的 API 名称、描述,选择默认 API 端点类型为“区域性”。

    在“Security Policy”(安全策略)下拉菜单中,选择建议的 TLS 13.1.3.

    点击“创建 API”。

     

    创建完毕,显示“已成功创建 REST API…“信息。

    在“资源“页面,点击”创建资源“。

    在默认资源路径“/”下,输入资源名,点击“创建资源”。

    资源“/students”创建成功!

    再次,点击“创建资源”。在资源下创建子资源 students_id。

    点击“创建资源”。

    Students 下面的子资源创建成功!

    同理,创建班级查询资源”class”和子资源”class_name”。已创建资源呈现树形列表。

     

    选择 students 资源,点击“创建方法”。

    在下拉列表框中选择创建的 Lambda 函数。

    点击“创建方法”按钮。选择“GET”方法,对应创建的 Lambda 函数。

    点击“创建方法”后,显示“已成功创建了方法GET”。

    根据不同资源,配置方法如下:

    1)为/students 资源配置:

    • 方法:POST → 集成类型:Lambda函数 → 选择 StudentManagementFunction
    • 方法:GET → 集成类型:Lambda函数 → 选择 StudentManagementFunction

    2)为/students/{student_id}配置:

    • 方法:GET, PUT, DELETE → 都连接到 Lambda 函数

    3)为/classes/{class_name}配置:

    • 方法:GET → 连接到 Lambda 函数

    在上述资源清单中,选择 students。

    点击右侧“启用 CORS”按钮。按照默认设置,点击“保存”。

    显示“已成功启用 CORS”。

    点击“详细信息”,显示出具体情况。

     

    对其它资源同样操作,完成启用 CORS。

    选择该 API,点击“部署”。弹出对话框,填写 API 部署信息。

    选择阶段为”*新阶段*”,给予阶段名称。点击“部署”。

     

    控制台提示“已成功创建 API 的部署”。

第六步 创建 Web 前端页面

全部打开

    • 启动 S3 服务

    在 AWS 管理控制台搜索打开“S3”,

    进入到 S3 控制台页面。

    点击“创建存储桶”。

    存储桶类型选择默认选项“通用”,输入存储桶名称。去除“阻止所有公开访问”选项,使用户可以访问该 Web 站点。

    *注意:为企业开发生产级产品服务,需慎重管理存储桶。本教程去除“屏蔽公共访问权限”仅为访问 S3 静态网站作临时配置用。

    在页面下方,点击“创建存储桶”。

    很快显示“已成功创建存储桶”。点击打开创建好的存储桶。

    打开“权限”选项卡。

    将页面向下滚动,在“存储桶策略“部分,点击“编辑”。在“策略”文本框中,添加以下策略:

    {

    "Version": "2012-10-17",

    "Statement": [

    {

    "Sid": "PublicReadGetObject",

    "Effect": "Allow",

    "Principal": "*",

    "Action": "s3:GetObject",

    "Resource": "arn:aws:s3:::student-management-web-bucket/*"

    }

    ]

    }

    单击“保存更改“按钮。

     

    该策略已经保存成功!

    点击“属性”选项卡,滚动到页面下方,“静态网站托管”部分,点击进入编辑。修改编辑静态网站托管到“启用”,并输入索引文档为”index.html”。

     

    点击“保存更改”。

     

    为了实现静态网站托管,符合学生学籍管理系统要求的主页面文件 indel.html 需要提前编码并保存,示例代码如下:

    <!DOCTYPE html>

    <html lang="zh-CN">

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <title>学生学籍管理系统</title>

        <style>

            * {

                margin: 0;

                padding: 0;

                box-sizing: border-box;

            }

            body {

                font-family: 'Arial', sans-serif;

                background-color: #f5f5f5;

                color: #333;

            }

            .container {

                max-width: 1200px;

                margin: 0 auto;

                padding: 20px;

            }

            .header {

                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

                color: white;

                padding: 2rem;

                border-radius: 10px;

                margin-bottom: 2rem;

                text-align: center;

            }

            .form-section {

                background: white;

                padding: 2rem;

                border-radius: 10px;

                box-shadow: 0 2px 10px rgba(0,0,0,0.1);

                margin-bottom: 2rem;

            }

            .form-group {

                margin-bottom: 1rem;

            }

            label {

                display: block;

                margin-bottom: 0.5rem;

                font-weight: bold;

            }

            input, select {

                width: 100%;

                padding: 0.75rem;

                border: 1px solid #ddd;

                border-radius: 5px;

                font-size: 1rem;

            }

            .btn {

                background: #667eea;

                color: white;

                padding: 0.75rem 1.5rem;

                border: none;

                border-radius: 5px;

                cursor: pointer;

                font-size: 1rem;

                margin-right: 0.5rem;

            }

            .btn:hover {

                background: #5a6fd8;

            }

            .btn-danger {

                background: #e53e3e;

            }

            .btn-danger:hover {

                background: #c53030;

            }

            .table-section {

                background: white;

                padding: 2rem;

                border-radius: 10px;

                box-shadow: 0 2px 10px rgba(0,0,0,0.1);

            }

            table {

                width: 100%;

                border-collapse: collapse;

                margin-top: 1rem;

            }

            th, td {

                padding: 1rem;

                text-align: left;

                border-bottom: 1px solid #ddd;

            }

            th {

                background-color: #f8f9fa;

                font-weight: bold;

            }

            .search-section {

                margin-bottom: 1rem;

            }

            .message {

                padding: 1rem;

                margin: 1rem 0;

                border-radius: 5px;

            }

            .success {

                background-color: #d4edda;

                color: #155724;

                border: 1px solid #c3e6cb;

            }

            .error {

                background-color: #f8d7da;

                color: #721c24;

                border: 1px solid #f5c6cb;

            }

        </style>

    </head>

    <body>

        <div class="container">

            <div class="header">

                <h1>学生学籍注册管理系统</h1>

                <p>基于AWS Lambda的无服务器应用</p>

            </div>

     

            <div class="form-section">

                <h2>学生信息管理</h2>

                <form id="studentForm">

                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">

                        <div class="form-group">

                            <label for="student_id">学号 *</label>

                            <input type="text" id="student_id" name="student_id" required>

                        </div>

                        <div class="form-group">

                            <label for="name">姓名 *</label>

                            <input type="text" id="name" name="name" required>

                        </div>

                        <div class="form-group">

                            <label for="age">年龄</label>

                            <input type="number" id="age" name="age">

                        </div>

                        <div class="form-group">

                            <label for="class_name">班级 *</label>

                            <input type="text" id="class_name" name="class_name" required>

                        </div>

                        <div class="form-group">

                            <label for="email">邮箱</label>

                            <input type="email" id="email" name="email">

                        </div>

                    </div>

                    <div style="margin-top: 1rem;">

                        <button type="submit" class="btn">添加学生</button>

                        <button type="button" class="btn" onclick="updateStudent()">更新学生</button>

                        <button type="button" class="btn" onclick="clearForm()">清空</button>

                    </div>

                </form>

            </div>

     

            <div class="search-section">

                <input type="text" id="searchClass" placeholder="输入班级名称搜索" style="width: 300px;">

                <button class="btn" onclick="searchByClass()">按班级搜索</button>

                <button class="btn" onclick="loadAllStudents()">显示所有学生</button>

            </div>

     

            <div id="message"></div>

     

            <div class="table-section">

                <h2>学生列表</h2>

                <table id="studentsTable">

                    <thead>

                        <tr>

                            <th>学号</th>

                            <th>姓名</th>

                            <th>年龄</th>

                            <th>班级</th>

                            <th>邮箱</th>

                            <th>操作</th>

                        </tr>

                    </thead>

                    <tbody id="studentsTableBody">

                        <!-- 动态填充 -->

                    </tbody>

                </table>

            </div>

        </div>

     

        <script>

            // 替换为您的API Gateway URL

            const API_URL = 'YOUR_API_GATEWAY_URL_HERE/prod';

           

            let currentEditingId = null;

     

            // 显示消息

            function showMessage(message, type = 'success') {

                const messageDiv = document.getElementById('message');

                messageDiv.innerHTML = `<div class="message ${type}">${message}</div>`;

                setTimeout(() => {

                    messageDiv.innerHTML = '';

                }, 5000);

            }

     

            // 加载所有学生

            async function loadAllStudents() {

                try {

                    const response = await fetch(`${API_URL}/students`);

                    const data = await response.json();

                    displayStudents(data.students || []);

                } catch (error) {

                    showMessage('加载学生列表失败: ' + error.message, 'error');

                }

            }

     

            // 按班级搜索

            async function searchByClass() {

                const class_name = document.getElementById('searchClass').value.trim();

                if (!class_name) {

                    showMessage('请输入班级名称', 'error');

                    return;

                }

               

                try {

                    const response = await fetch(`${API_URL}/classes/${encodeURIComponent(class_name)}`);

                    const data = await response.json();

                    displayStudents(data.students || []);

                } catch (error) {

                    showMessage('搜索失败: ' + error.message, 'error');

                }

            }

     

            // 显示学生列表

            function displayStudents(students) {

                const tbody = document.getElementById('studentsTableBody');

                tbody.innerHTML = '';

               

                students.forEach(student => {

                    const tr = document.createElement('tr');

                    tr.innerHTML = `

                        <td>${student.student_id}</td>

                        <td>${student.name}</td>

                        <td>${student.age || '-'}</td>

                        <td>${student.class_name}</td>

                        <td>${student.email || '-'}</td>

                        <td>

                            <button class="btn" onclick="editStudent('${student.student_id}')">编辑</button>

                            <button class="btn btn-danger" onclick="deleteStudent('${student.student_id}')">删除</button>

                        </td>

                    `;

                    tbody.appendChild(tr);

                });

            }

     

            // 添加学生

            document.getElementById('studentForm').addEventListener('submit', async function(e) {

                e.preventDefault();

               

                const formData = new FormData(this);

                const studentData = {

                    student_id: formData.get('student_id'),

                    name: formData.get('name'),

                    age: formData.get('age') ? parseInt(formData.get('age')) : undefined,

                    class_name: formData.get('class_name'),

                    email: formData.get('email') || undefined

                };

     

                try {

                    const response = await fetch(`${API_URL}/students`, {

                        method: 'POST',

                        headers: {

                            'Content-Type': 'application/json',

                        },

                        body: JSON.stringify(studentData)

                    });

                   

                    const result = await response.json();

                   

                    if (response.ok) {

                        showMessage('学生添加成功');

                        clearForm();

                        loadAllStudents();

                    } else {

                        showMessage(result.message || '添加失败', 'error');

                    }

                } catch (error) {

                    showMessage('添加失败: ' + error.message, 'error');

                }

            });

     

            // 编辑学生

            async function editStudent(student_id) {

                try {

                    const response = await fetch(`${API_URL}/students/${student_id}`);

                    const data = await response.json();

                   

                    if (response.ok) {

                        const student = data.student;

                        document.getElementById('student_id').value = student.student_id;

                        document.getElementById('name').value = student.name;

                        document.getElementById('age').value = student.age || '';

                        document.getElementById('class_name').value = student.class_name;

                        document.getElementById('email').value = student.email || '';

                       

                        currentEditingId = student.student_id;

                        document.getElementById('student_id').readOnly = true;

                    } else {

                        showMessage(data.message, 'error');

                    }

                } catch (error) {

                    showMessage('加载学生信息失败: ' + error.message, 'error');

                }

            }

     

            // 更新学生

            async function updateStudent() {

                if (!currentEditingId) {

                    showMessage('请先选择要编辑的学生', 'error');

                    return;

                }

               

                const studentData = {

                    name: document.getElementById('name').value,

                    age: document.getElementById('age').value ? parseInt(document.getElementById('age').value) : undefined,

                    class_name: document.getElementById('class_name').value,

                    email: document.getElementById('email').value || undefined

                };

     

                try {

                    const response = await fetch(`${API_URL}/students/${currentEditingId}`, {

                        method: 'PUT',

                        headers: {

                            'Content-Type': 'application/json',

                        },

                        body: JSON.stringify(studentData)

                    });

                   

                    const result = await response.json();

                   

                    if (response.ok) {

                        showMessage('学生信息更新成功');

                        clearForm();

                        loadAllStudents();

                    } else {

                        showMessage(result.message || '更新失败', 'error');

                    }

                } catch (error) {

                    showMessage('更新失败: ' + error.message, 'error');

                }

            }

     

            // 删除学生

            async function deleteStudent(student_id) {

                if (!confirm('确定要删除这个学生吗?')) {

                    return;

                }

               

                try {

                    const response = await fetch(`${API_URL}/students/${student_id}`, {

                        method: 'DELETE'

                    });

                   

                    const result = await response.json();

                   

                    if (response.ok) {

                        showMessage('学生删除成功');

                        loadAllStudents();

                    } else {

                        showMessage(result.message || '删除失败', 'error');

                    }

                } catch (error) {

                    showMessage('删除失败: ' + error.message, 'error');

                }

            }

     

            // 清空表单

            function clearForm() {

                document.getElementById('studentForm').reset();

                document.getElementById('student_id').readOnly = false;

                currentEditingId = null;

            }

     

            // 页面加载时获取学生列表

            window.onload = loadAllStudents;

        </script>

    </body>

    </html>

    • 保存 HTML 文件

    将上述 HTML 代码保存为主页文件名称:index.html。

    • 上传静态 HTML 文件到 S3 存储桶

    返回 S3 控制台页面,默认打开“对象”选项卡。

    需要上传静态网站文件,点击“上传”选择指定文件夹,找到之前保存好的 index.html 文件。上传后勾选该文件。

    点击“上传”按钮。

     

    很快上传成功!

第七步 配置和测试

全部打开

    打开 API Gateway,找到创建的 API;在“阶段”里,复制调用 URL。

    将复制的 URL,替换主页面文件 index.html 的相应位置。

    使 const 变量 API_URL 更新,保存 index.html。

    在 S3 重新上传更新后的 index.html.

    需要永久删除之前上传的文件。

    点击“关闭”。回到 S3 存储桶,重新上传新的 index.html.

    再次上传文件成功!

     

    按照 S3 存储桶 URL,访问学生学籍管理系统。

    可以按照 Web 页面框架逐步完成学生信息填写注册等操作 。至此,由 AWS Lambda 构建无服务器基于 Web 的学生学籍注册管理系统正式发布。

第八步 总结

全部打开

    本教程系统演示了如何基于 AWS Lambda 构建一套完整的无服务器学生学籍管理系统,体现了现代云原生应用的典型架构思路。系统采用事件驱动设计,前端通过 Amazon S3 托管静态网页,后端使用 AWS Lambda 处理业务逻辑,数据存储借助 Amazon DynamoDB 实现高性能的 NoSQL 持久化,并通过 API Gateway 对外提供 RESTful API 接口,整体实现了解耦、弹性伸缩和按需付费的优势。

    教程的实现路径清晰、层次分明:从账户准备、IAM 权限配置,到数据库表设计与 Lambda 函数编写,再到 API 网关的路由整合与前端页面的部署测试,逐步推进并注重实操细节。其技术特点突出无服务器架构的轻量化、自动化运维和成本可控性,适合中小型应用快速搭建与迭代。通过本教程,开发者不仅能掌握 AWS 核心服务的联动使用,更能理解如何以松耦合、高可用的方式构建可扩展的 Web 应用。