AWS实战:S3 Cloud Watch Event 触发Lambda

news2024/9/24 15:21:38

架构

既然是S3 Cloud Watch Event 触发Lambda,首先就需要三个AWS的service:

  • S3
  • Event Bridge
  • Lambda

S3有event产生时向Event Bridge发送event,Event Bridge通过event rule的配置过滤event,将符合规则的event发送给lambda进行处理。

S3如何向Event Bridge发送Event

  • S3默认情况下是不会主动向Event Bridge发送event的,需要enable Amazon EventBridge的配置,才会将event发送给Event Bridge,可以通过一下三种方式进行配置
    • AWS Web Console:bucket页面->Properties->Event notifications ->Amazon EventBridge -> on
    • AWS CLI
      • 打开
        • aws s3api put-bucket-notification-configuration --bucket DOC-EXAMPLE-BUCKET1 --notification-configuration '{ "EventBridgeConfiguration": {} }'
      • 关闭
      • aws s3api put-bucket-notification-configuration --bucket DOC-EXAMPLE-BUCKET1 --notification-configuration '{}'
    • Serverless

    • SourceEventBucket:
        Type: AWS::S3::Bucket
        Properties:
          BucketName: !Sub com.jessica.${self:provider.stage}-source-event-bucket
          NotificationConfiguration:
            EventBridgeConfiguration:
              EventBridgeEnabled: true
  • enable Amazon EventBridge之后,默认情况下,S3会将所有的event发送给Amazon EventBridge,S3的event类型如下:
  • Event typeDescription

    Object Created

    An object was created.

    The reason field in the event message structure indicates which S3 API was used to create the object: PutObject, POST Object, CopyObject, or CompleteMultipartUpload.

    Object Deleted (DeleteObject)

    Object Deleted (Lifecycle expiration)

    An object was deleted.

    When an object is deleted using an S3 API call, the reason field is set to DeleteObject. When an object is deleted by an S3 Lifecycle expiration rule, the reason field is set to Lifecycle Expiration. For more information, see Expiring objects.

    When an unversioned object is deleted, or a versioned object is permanently deleted, the deletion-type field is set to Permanently Deleted. When a delete marker is created for a versioned object, the deletion-type field is set to Delete Marker Created. For more information, see Deleting object versions from a versioning-enabled bucket.

    Object Restore Initiated

    An object restore was initiated from S3 Glacier or S3 Glacier Deep Archive storage class or from S3 Intelligent-Tiering Archive Access or Deep Archive Access tier. For more information, see Working with archived objects.

    Object Restore Completed

    An object restore was completed.

    Object Restore Expired

    The temporary copy of an object restored from S3 Glacier or S3 Glacier Deep Archive expired and was deleted.

    Object Storage Class Changed

    An object was transitioned to a different storage class. For more information, see Transitioning objects using Amazon S3 Lifecycle.

    Object Access Tier Changed

    An object was transitioned to the S3 Intelligent-Tiering Archive Access tier or Deep Archive Access tier. For more information, see Amazon S3 Intelligent-Tiering.

    Object ACL Updated

    An object's access control list (ACL) was set using PutObjectACL. An event is not generated when a request results in no change to an object’s ACL. For more information, see Access control list (ACL) overview.

    Object Tags Added

    A set of tags was added to an object using PutObjectTagging. For more information, see Categorizing your storage using tags.

    Object Tags Deleted

    All tags were removed from an object using DeleteObjectTagging. For more information, see Categorizing your storage using tags.

  • S3向EventBridge发送event不需要额外的权限配置

Event Bridge如何对Event进行过滤

  • Event Bridget通过在event rule中指定event pattern来对event进行过滤
  • 这是一个S3 put object的event示例
    • {
        "version": "0",
        "id": "17793124-05d4-b198-2fde-7ededc63b103",
        "detail-type": "Object Created",
        "source": "aws.s3",
        "account": "123456789012",
        "time": "2021-11-12T00:00:00Z",
        "region": "ca-central-1",
        "resources": ["arn:aws:s3:::example-bucket"],
        "detail": {
          "version": "0",
          "bucket": {
            "name": "example-bucket"
          },
          "object": {
            "key": "example-key",
            "size": 5,
            "etag": "b1946ac92492d2347c6235b4d2611184",
            "version-id": "IYV3p45BT0ac8hjHg1houSdS1a.Mro8e",
            "sequencer": "00617F08299329D189"
          },
          "request-id": "N4N7GDK58NMKJ12R",
          "requester": "123456789012",
          "source-ip-address": "1.2.3.4",
          "reason": "PutObject"
        }
      }
  • 以下为event pattern示例

    • 过滤所有s3event

    • {
        "source": ["aws.s3"]
      }
    • 过滤指定账号下所有s3event

    • {
        "source": ["aws.s3"],
        "account": ["123456789012"],
      }
    • 过滤指定账号下某个bucket所有s3event

    • {
        "source": ["aws.s3"],
        "account": ["123456789012"],
        "resources": ["arn:aws:s3:::example-bucket"]
      }
    • 过滤指定账号下某个bucket所有s3 put object event

    • {
        "source": ["aws.s3"],
        "account": ["123456789012"],
        "detail-type": ["Object Created"],
        "resources": ["arn:aws:s3:::example-bucket"]
      }
    • 过滤指定账号下某个bucket指定prefix的所有s3 put object event

      {
        "source": ["aws.s3"],
        "account": ["123456789012"],
        "detail-type": ["Object Created"],
        "resources": ["arn:aws:s3:::example-bucket"],
        "detail": {
          "object" : {
            "key":[{"prefix":"example"}]
          }
        }
      }
    • event pattern 除了支持精确匹配外还支持一些简单的规则匹配,比如prefix,支持列表如下

    • ComparisonExampleRule syntaxSupported by Pipes

      Null

      UserID is null

      "UserID": [ null ]

      Yes

      Empty

      LastName is empty

      "LastName": [""]

      Yes

      Equals

      Name is "Alice"

      "Name": [ "Alice" ]

      Yes

      Equals (ignore case)

      Name is "Alice"

      "Name": [ { "equals-ignore-case": "alice" } ]

      No

      And

      Location is "New York" and Day is "Monday"

      "Location": [ "New York" ], "Day": ["Monday"]

      Yes

      Or

      PaymentType is "Credit" or "Debit"

      "PaymentType": [ "Credit", "Debit"]

      Yes

      Or (multiple fields)

      Location is "New York", or Day is "Monday".

      "$or": [ { "Location": [ "New York" ] }, { "Day": [ "Monday" ] } ]

      No

      Not

      Weather is anything but "Raining"

      "Weather": [ { "anything-but": [ "Raining" ] } ]

      Yes

      Numeric (equals)

      Price is 100

      "Price": [ { "numeric": [ "=", 100 ] } ]

      Yes

      Numeric (range)

      Price is more than 10, and less than or equal to 20

      "Price": [ { "numeric": [ ">", 10, "<=", 20 ] } ]

      Yes

      Exists

      ProductName exists

      "ProductName": [ { "exists": true } ]

      Yes

      Does not exist

      ProductName does not exist

      "ProductName": [ { "exists": false } ]

      Yes

      Begins with

      Region is in the US

      "Region": [ {"prefix": "us-" } ]

      Yes

      Ends with

      FileName ends with a .png extension.

      "FileName": [ { "suffix": ".png" } ]

      No

Event Bridge如何触发Lambda调用

  • Event Bridge想要触发lambda,则Event Bridge Service(events.amazonaws.com)必须要有调用lambda的权限,可以通过创建lambda permission来实现
  •     LambdaInvokePermission:
          Type: AWS::Lambda::Permission
          Properties:
            FunctionName: !GetAtt S3EventHandlerLambdaFunction.Arn
            Action: lambda:InvokeFunction
            Principal: events.amazonaws.com
            SourceArn: !GetAtt S3EventRule.Arn

Serverless部署资源

  • 以下为本文用到的所有资源的serverless部署文件,有两个版本,serverless.yml和serverless-manual.yml
  • serverless.yml为利用serverless framework的一些规则自动创建event rule和lambda permission,比较适合新手入门,不清楚有哪些资源需要创建的时候使用,serverless framework会将所有需要的资源创建自动加入cloudformation文件,缺点是用户无法自定义资源名称
    • service: event-bridge-trigger-lambda
      
      custom:
        bucketNamePrefix: "bucketName"
      
      provider:
        name: aws
        runtime: java8
        memorySize: 512
        timeout: 900
        deploymentBucket:
          name: com.${self:custom.bucketNamePrefix}.deploy-bucket
          serverSideEncryption: AES256
        stackName: ${self:service}
        region: ${opt:region, 'ap-southeast-1'}
        stage: ${opt:stage, 'develop'}
        versionFunctions: false
      
      resources:
        Resources:
          SourceEventBucket:
            Type: AWS::S3::Bucket
            Properties:
              BucketName: com.jessica.${self:provider.stage}-source-event-bucket
              NotificationConfiguration:
                EventBridgeConfiguration:
                  EventBridgeEnabled: true
          LambdaRole:
            Type: AWS::IAM::Role
            Properties:
              RoleName: ${self:provider.stage}_LambdaRole
              AssumeRolePolicyDocument:
                Version: "2012-10-17"
                Statement:
                  - Effect: Allow
                    Principal:
                      Service:
                        - lambda.amazonaws.com
                    Action: sts:AssumeRole
              ManagedPolicyArns:
                - arn:aws:iam::aws:policy/AmazonS3FullAccess
                - arn:aws:iam::aws:policy/CloudWatchFullAccess
          S3EventRule:
            Type: AWS::Events::Rule
            Properties:
              Description: event rule for s3 event
              EventPattern:
                source:
                  - aws.s3
                detail-type:
                  - Object Created
                  - Object Deleted
                detail:
                  bucket:
                    name:
                      - com.jessica.${self:provider.stage}-source-event-bucket
              Name: s3-event
              State: ENABLED
              Targets:
                - Arn: !GetAtt S3EventHandlerLambdaFunction.Arn
                  Id: s3-event-handler
          LambdaInvokePermission:
            Type: AWS::Lambda::Permission
            Properties:
              FunctionName: !GetAtt S3EventHandlerLambdaFunction.Arn
              Action: lambda:InvokeFunction
              Principal: events.amazonaws.com
              SourceArn: !GetAtt S3EventRule.Arn
      package:
        artifact: target/event-bridge-trigger-lambda.jar
      
      functions:
        S3EventHandler:
          name: ${self:provider.stage}-S3EventHandler
          handler: com.jessica.aws.lambda.S3EventHandler
          role: !GetAtt LambdaRole.Arn
          maximumRetryAttempts: 0
          description: s3 event handler
      
  • serverless-manual.yml则在serverless文件中指定需要创建的event rule和lambda permission,自己进行创建
service: event-bridge-trigger-lambda

custom:
  bucketNamePrefix: "bucketName"

provider:
  name: aws
  runtime: java8
  memorySize: 512
  timeout: 900
  deploymentBucket:
    name: com.${self:custom.bucketNamePrefix}.deploy-bucket
    serverSideEncryption: AES256
  stackName: ${self:service}
  region: ${opt:region, 'ap-southeast-1'}
  stage: ${opt:stage, 'develop'}
  versionFunctions: false

resources:
  Resources:
    SourceEventBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: !Sub com.jessica.${self:provider.stage}-source-event-bucket
        NotificationConfiguration:
          EventBridgeConfiguration:
            EventBridgeEnabled: true
    LambdaRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: !Sub "${self:provider.stage}_LambdaRole"
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/AmazonS3FullAccess
          - arn:aws:iam::aws:policy/CloudWatchFullAccess
package:
  artifact: target/event-bridge-trigger-lambda.jar

functions:
  S3PutObjectHandler:
    name: ${self:provider.stage}-S3EventHandler
    handler: com.jessica.aws.lambda.S3EventHandler
    role: !GetAtt LambdaRole.Arn
    maximumRetryAttempts: 0
    description: s3 event handler
    events:
      - eventBridge:
          pattern:
            source:
              - aws.s3
            detail-type:
              - Object Created
              - Object Deleted
            detail:
              bucket:
                name:
                  - !Sub com.jessica.${self:provider.stage}-source-event-bucket
              object:
                key:
                  - prefix: "event/"

Event的数据结构

  • 对于不同的源,event包含的内容是不一样的,对于S3来说,event结构如下:EventBridge event message structure - Amazon Simple Storage Service
    • version — Currently 0 (zero) for all events.

    • id — A Version 4 UUID generated for every event.

    • detail-type — The type of event that's being sent. See Using EventBridge for a list of event types.

    • source — Identifies the service that generated the event.

    • account — The 12-digit AWS account ID of the bucket owner.

    • time — The time the event occurred.

    • region — Identifies the AWS Region of the bucket.

    • resources — A JSON array that contains the Amazon Resource Name (ARN) of the bucket.

    • detail — A JSON object that contains information about the event.

      • 根据event类型的不同,detail可能包含一下字段

      • version — Currently 0 (zero) for all events.

      • bucket — Information about the Amazon S3 bucket involved in the event.

      • object — Information about the Amazon S3 object involved in the event.

      • request-id — Request ID in S3 response.

      • requester — AWS account ID or AWS service principal of requester.

      • source-ip-address — Source IP address of S3 request. Only present for events triggered by an S3 request.

      • reason — For Object Created events, the S3 API used to create the object: PutObject, POST Object, CopyObject, or CompleteMultipartUpload. For Object Deleted events, this is set to DeleteObject when an object is deleted by an S3 API call, or Lifecycle Expiration when an object is deleted by an S3 Lifecycle expiration rule. For more information, see Expiring objects.

      • deletion-type — For Object Deleted events, when an unversioned object is deleted, or a versioned object is permanently deleted, this is set to Permanently Deleted. When a delete marker is created for a versioned object, this is set to Delete Marker Created. For more information, see Deleting object versions from a versioning-enabled bucket.

      • restore-expiry-time — For Object Restore Completed events, the time when the temporary copy of the object will be deleted from S3. For more information, see Working with archived objects.

      • source-storage-class — For Object Restore Initiated and Object Restore Completed events, the storage class of the object being restored. For more information, see Working with archived objects.

      • destination-storage-class — For Object Storage Class Changed events, the new storage class of the object. For more information, see Transitioning objects using Amazon S3 Lifecycle.

      • destination-access-tier — For Object Access Tier Changed events, the new access tier of the object

  • Object created event示例

  • {
      "version": "0",
      "id": "17793124-05d4-b198-2fde-7ededc63b103",
      "detail-type": "Object Created",
      "source": "aws.s3",
      "account": "111122223333",
      "time": "2021-11-12T00:00:00Z",
      "region": "ca-central-1",
      "resources": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET1"
      ],
      "detail": {
        "version": "0",
        "bucket": {
          "name": "DOC-EXAMPLE-BUCKET1"
        },
        "object": {
          "key": "example-key",
          "size": 5,
          "etag": "b1946ac92492d2347c6235b4d2611184",
          "version-id": "IYV3p45BT0ac8hjHg1houSdS1a.Mro8e",
          "sequencer": "617f08299329d189"
        },
        "request-id": "N4N7GDK58NMKJ12R",
        "requester": "123456789012",
        "source-ip-address": "1.2.3.4",
        "reason": "PutObject"
      }
    }  
  • Object deleted (using DeleteObject)

  • {
      "version": "0",
      "id": "2ee9cc15-d022-99ea-1fb8-1b1bac4850f9",
      "detail-type": "Object Deleted",
      "source": "aws.s3",
      "account": "111122223333",
      "time": "2021-11-12T00:00:00Z",
      "region": "ca-central-1",
      "resources": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET1"
      ],
      "detail": {
        "version": "0",
        "bucket": {
          "name": "DOC-EXAMPLE-BUCKET1"
        },
        "object": {
          "key": "example-key",
          "etag": "d41d8cd98f00b204e9800998ecf8427e",
          "version-id": "1QW9g1Z99LUNbvaaYVpW9xDlOLU.qxgF",
          "sequencer": "617f0837b476e463"
        },
        "request-id": "0BH729840619AG5K",
        "requester": "123456789012",
        "source-ip-address": "1.2.3.4",
        "reason": "DeleteObject",
        "deletion-type": "Delete Marker Created"
      }
    }
                
  • Object deleted (using lifecycle expiration)

  • {
      "version": "0",
      "id": "ad1de317-e409-eba2-9552-30113f8d88e3",
      "detail-type": "Object Deleted",
      "source": "aws.s3",
      "account": "111122223333",
      "time": "2021-11-12T00:00:00Z",
      "region": "ca-central-1",
      "resources": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET1"
      ],
      "detail": {
        "version": "0",
        "bucket": {
          "name": "DOC-EXAMPLE-BUCKET1"
        },
        "object": {
          "key": "example-key",
          "etag": "d41d8cd98f00b204e9800998ecf8427e",
          "version-id": "mtB0cV.jejK63XkRNceanNMC.qXPWLeK",
          "sequencer": "617b398000000000"
        },
        "request-id": "20EB74C14654DC47",
        "requester": "s3.amazonaws.com",
        "reason": "Lifecycle Expiration",
        "deletion-type": "Delete Marker Created"
      }
    }
                
  • Object restore completed

  • {
      "version": "0",
      "id": "6924de0d-13e2-6bbf-c0c1-b903b753565e",
      "detail-type": "Object Restore Completed",
      "source": "aws.s3",
      "account": "111122223333",
      "time": "2021-11-12T00:00:00Z",
      "region": "ca-central-1",
      "resources": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET1"
      ],
      "detail": {
        "version": "0",
        "bucket": {
          "name": "DOC-EXAMPLE-BUCKET1"
        },
        "object": {
          "key": "example-key",
          "size": 5,
          "etag": "b1946ac92492d2347c6235b4d2611184",
          "version-id": "KKsjUC1.6gIjqtvhfg5AdMI0eCePIiT3"
        },
        "request-id": "189F19CB7FB1B6A4",
        "requester": "s3.amazonaws.com",
        "restore-expiry-time": "2021-11-13T00:00:00Z",
        "source-storage-class": "GLACIER"
      }
    }

Lambda如何对event进行接收和处理

  • 需要根据需要接受的event的结构定义相应的数据结构,然后通过序列化和反序列化来得到event object
  • S3EventBridgeObject
package com.jessica.aws.lambda;

import java.util.ArrayList;

import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class S3EventBridgeObject {
    private String id;
    private String version;
    @JsonFilter(value = "detail-type")
    private String detailType;
    private String source;
    private String account;
    private String time;
    private String region;
    private ArrayList<String> resources;
    private S3EventDetail detail;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class S3EventDetail {
        private String version;
        private S3EventBucketName bucket;
        private S3EventBucketObject object;
        @JSONField(name = "request-id")
        private String requestId;
        private String requester;
        @JSONField(name = "source-ip-address")
        private String sourceIpAddress;
        private String reason;
        @JSONField(name = "deletion-type")
        private String deletionType;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class S3EventBucketName {
        private String name;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class S3EventBucketObject {
        private String key;
        private int size;
        private String etag;
        @JSONField(name = "version-id")
        private String versionId;
        private String sequencer;
    }

}
  • LambdaHandler
  • package com.jessica.aws.lambda;
    
    import com.alibaba.fastjson.JSON;
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    
    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class S3EventHandler implements RequestHandler<Object, Boolean> {
        @Override
        public Boolean handleRequest(Object s3Event, Context context) {
            log.info("Received event data: " + s3Event);
            String jsonString = JSON.toJSONString(s3Event);
            S3EventBridgeObject event = JSON.parseObject(jsonString, S3EventBridgeObject.class);
            log.info(String.format("S3event: event type: %s, bucket name:%s, file key:%s", event.getDetail().getBucket().getName(), event.getDetailType(),
                    event.getDetail().getObject().getKey()));
            return true;
        }
    }
    

完整代码

aws-in-action/event-bridge-trigger-lambda at master · JessicaWin/aws-in-action · GitHub

参考

Using EventBridge - Amazon Simple Storage Service

Amazon EventBridge event patterns - Amazon EventBridge

Serverless Framework - AWS Lambda Events - CloudWatch Event

Serverless Framework - AWS Lambda Guide - Serverless.yml Reference

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

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

相关文章

科研论文写作

科研论文写作 文章目录科研论文写作一、论文写作的重要性二、论文写作的总原则二、论文写作的注意事项数学符号上下文要保持一致英文表达存在天然的顺承关系比较级和最高级不可以轻易使用需要有甄别的使用其他论文中的句子数学符号需要有明确定义特定的缩写第一次出现需要指明全…

vue本地案例之记事本

新增 生成列表结构(v-for 数组)获取用户输入(v-model 双向数据绑定)回车&#xff0c;新增数据(v-on .enter添加数据&#xff1a;事件绑定v-on&#xff08;可缩写为后面加事件名&#xff09;&#xff0c;限定回车.enter)删除 点击删除指定内容(v-on splice索引&#xff09;数据…

posix API与网络协议栈

posix API与网络协议栈 scoket socket包含两部分&#xff1a;fd、tcb&#xff08;tcp control block&#xff09; 其中&#xff0c;fd属于文件系统&#xff0c;可在用户态进行操控&#xff1b;而tcb属于内核协议栈 三次握手 服务端API socekt()&#xff1a;创建一个tcb和f…

Linux常用命令——tput命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) tput 通过terminfo数据库对终端会话进行初始化和操作 补充说明 tput命令将通过 terminfo 数据库对您的终端会话进行初始化和操作。通过使用 tput&#xff0c;您可以更改几项终端功能&#xff0c;如移动或更改光…

关系数据库-2-[mysql8]python3操作mysql

参考文档Python-PyMysql详解 参考文档使用pandas操作MySQL数据库 1 pymysql操作mysql PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库。 PyMySQL 遵循 Python 数据库 API v2.0 规范&#xff0c;并包含了 pure-Python MySQL 客户端库。 pip install PyMySQL1.…

在线教育-谷粒学院学习笔记(八)

文章目录1 内容介绍2 微服务3 微服务实现删除nacos4 删除课程-删除视频5 Hystrix1 内容介绍 Spring Colud 删除小节-删除视频删除课程-删除视频 2 微服务 service 三个服务 service_edu 8001service_oss 8002service_vod 8003 微服务 微服务是架构风格把一个项目拆分成多个…

NUMA介绍

早期CPU访问内存结构 UMA1&#xff08;Uniform Memory Access, 一致性内存访问 &#xff09; 早期的计算机&#xff0c;内存控制器还没有整合进 CPU&#xff0c;所有的内存访问都需要经过北桥芯片来完成。 在 UMA 架构下&#xff0c;CPU 和内存之间的通信全部都要通过前端总线…

【Java|golang】2293. 极大极小游戏

给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#xff0c;如果 n 1 &#xff0c;终止 算法过程。否则&#xff0c;创建 一个新的整数数组 newNums &#xff0c;新数组长度为 n / 2 &#x…

go语言初识——数据类型

目录 go go与C语言区别 helloworld 数据类型 变量 定义 类型推导 简短声明 : 匿名变量 常量 iota 基本类型 指针 数组 结构体 go Go是2009年开源的编程语言&#xff0c;Go语言具有以下特性&#xff1a;语法简洁、并发编程、编译迅速、数组安全、丰富的内置类型…

如何在 Antd Pro 框架上实现样式自定义?

文章目录一、前言二、实操过程一、前言 Ant Design Pro 是一个企业级中后台前端/设计解决方案&#xff0c;已经有完善的 UI 组件及设计风格&#xff0c;在一些特定项目中&#xff0c;往往涉及到对其调整&#xff0c;来实现独特的 UI 设计&#xff0c;如不同的主题色、布局、卡…

帮助台技术员协助的自助服务

对于帮助台技术员例行电话带来成本高居不下的企业来说&#xff0c;最终用户自助服务是一个伟大的解决方案&#xff0c;允许用户解决自己的IT问题。然而&#xff0c;一些企业仍未部署自助服务。例如&#xff0c;即使在Active Directory中维护每个员工的最新个人资料信息是一件乏…

1. Python3的安装与环境搭建

1. 开发环境&#xff1a;Win10 Python3.10.5 PyCharm 2. 安装Python3 下载地址&#xff1a;https://www.python.org/ 运行刚下载的python-3.10.5-amd64.exe&#xff0c;并做以下操作&#xff1a; 然后Next&#xff0c;并进行以下操作&#xff1a; 最后点击Install&#…

会话跟踪技术:Cookie、Session和Token

会话跟踪技术背景&#xff1a;1. Cookie &#xff08;客户端的会话跟踪技术&#xff09;1.1 原理1.2 基本使用1.2.1 服务器发送Cookie1.2.2 服务器获取Cookie1.3 使用细节1.3.1 存活时间1.3.2 存储中文2. Session&#xff08;服务端的会话跟踪技术&#xff09;2.1 原理2.2 基本…

采用高通Qualcomm处理器的手机进EDL 9008模式的办法

由于我们有很多基于 Qualcomm 的设备&#xff0c;其中一些设备可能会古怪地猜测如何进入 EDL 模式&#xff0c;或者如何正确进入。 例如&#xff0c;对于 Alcatel&#xff0c;您必须先按住两个音量键&#xff0c;然后再按住其中一个&#xff0c;对于 CAT B35&#xff0c;您必须…

Python基础(二十六):模块和包简单介绍

文章目录 模块和包简单介绍 一、模块 1、导入模块 2、制作模块

基于Servlet+jsp+mysql开发javaWeb校园图书管理系统

你知道的越多&#xff0c;你不知道的越多 点赞再看&#xff0c;养成习惯 如果您有疑问或者见解&#xff0c;或者没有积分想获取项目&#xff0c;欢迎指教&#xff1a; 企鹅&#xff1a;869192208 文章目录一、开发背景二、 需求分析三、开发环境四、运行效果五、开发流程工程目…

【Android安全】Google Hardware-backed Keystore | SafetyNet | 远程证明Remote Attestation

Google Hardware-backed KeyStore Attestation 原理及流程 SafetyNet Hardware-backed Attestation SafetyNet Hardware-backed Attestation&#xff1a;使用了Hardware-backed Keystore SafetyNet 支持Software Attestation 和 Hardware-backed Attestation&#xff0c;根据…

五、Web应用开发模式

web应用开发模式 web应用的开发主要有两种模式&#xff1a; 前后端不分离前后端分离 前后端不分离 在互联网早期&#xff0c;web应用开发采用前后端不分离的方式。 它是以后端直接渲染模板完成响应的一种开发模式。 以前后端不分离的方式开发的web应用的架构图如下&#x…

每天15分钟JMeter进阶篇(1):JAVA 取样器的基本使用

每天15分钟JMeter进阶篇&#xff08;1&#xff09;&#xff1a;JAVA 取样器的基本使用前言准备工作创建开发工程POM文件创建根工程创建module开发JAVA取样器构建、部署运行构建JAR包部署和运行写在最后前言 JMETER官方提供了丰富的取样器&#xff0c;可以支持80%的常见测试场景…

传输层协议:UDP协议

简介 用户数据报协议&#xff08;英语&#xff1a;User Datagram Protocol&#xff0c;缩写&#xff1a;UDP&#xff1b;又称用户数据包协议&#xff09;是一个简单的面向数据包的通信协议&#xff0c;位于OSI模型的传输层。该协议由David P. Reed在1980年设计且在RFC 768中被…