[JAVA] Schreiben wir eine Lambda-Funktion, die Amazon API Gateway in die Spring Cloud-Funktion integriert.

Einführung

Das Implementieren von Lambda-Funktionen in Java kann mühsam sein. Wenn Sie die Spring Cloud-Funktion verwenden, scheint das Framework die Komplexität dieses Bereichs auf nette Weise zu absorbieren. Also habe ich versucht zu sehen, ob es wirklich gut aufgenommen wurde und ich konnte es schnell schreiben.

Übrigens gibt es viele Beispiele für Spring Cloud Function, die nicht in den Proxy integriert sind, aber ich konnte die integrierte Version nicht finden, daher hoffe ich, dass es hilfreich ist, sie in Betracht zu ziehen.

Verfassung

Erstellen Sie ein Maven-Projekt wie das folgende.

SpringCloudFunctionTest
├── pom.xml
├── serverless.yml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── springcloudfunctiontest
    │   │           ├── AWSLambdaHandler.java
    │   │           ├── Hello.java
    │   │           └── SpringCloudFunctionExampleApplication.java
    │   └── resources
    │       └── application.properties
    └── test
        └── java
            └── com
                └── springcloudfunctiontest
                    └── SpringCloudFunctionExampleApplicationTests.java

pom.xml sollte so aussehen.

pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.techprimers.serverless</groupId>
    <artifactId>spring-cloud-function-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-function-test</name>
    <description>Demo project for Spring Boot with Spring Cloud Function</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-adapter-aws</artifactId>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-events</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR2</version>
                <type>pom</type>
                <scope>import</scope>
                </dependency>
            </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.boot.experimental</groupId>
                        <artifactId>spring-boot-thin-layout</artifactId>
                        <version>1.0.10.RELEASE</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <shadedArtifactAttached>true</shadedArtifactAttached>
                    <shadedClassifierName>aws</shadedClassifierName>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Handler-Code

Erstellen Sie eine Klasse, die SpringApplication.run wie eine normale Spring Boot-App ausführt.

SpringCloudFunctionExampleApplication.java


package com.springcloudfunctiontest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringCloudFunctionExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudFunctionExampleApplication.class, args);
    }

}

Erstellen Sie also einen Ereignishandler für Lambda. Um ehrlich zu sein, bin ich mir nicht sicher, warum diese Klasse leer ist ... Da es sich am Back-End des API-Gateways befindet, legen Sie für Eingabe und Ausgabe "APIGatewayProxyRequestEvent" und "APIGatewayProxyResponseEvent" fest.

AWSLambdaHandler.java


package com.springcloudfunctiontest;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler;

public class AWSLambdaHandler extends SpringBootRequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
}

Erstellen Sie schließlich eine Klasse von Geschäftslogik. ``APIGatewayProxyRequestEventWannAPIGatewayProxyResponseEvent```Spezifikationen sindjavadocLass uns nachsehen.

Obwohl die Spring Cloud-Funktion mit mehreren Clouds kompatibel ist, handelt es sich bei Verwendung einer solchen Schnittstelle um eine vollständig AWS-spezifische Implementierung.

Machen Sie sich keine Sorgen über den unordentlichen Umgang mit dem JSON im letzten setBody.

Hello.java


package com.springcloudfunctiontest;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import org.springframework.stereotype.Component;

import java.util.function.Function;
import java.util.Map;

@Component
public class Hello implements Function<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
    @Override
    public APIGatewayProxyResponseEvent apply(APIGatewayProxyRequestEvent input) {
        Map<String, String> queryStringParameter = input.getQueryStringParameters();

        String id = queryStringParameter.get("id");
        String name = null;

        if( id.equals("11111") ) {
          name = "\"Taro\"";
        } else {
          name = "\"Nanashi\"";
        }

        APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent();
        responseEvent.setStatusCode(200);
        responseEvent.setBody("{\"name\":" + name + "}");
        return responseEvent;
    }
}

#Testcode Sie können Testcode normal schreiben.

SpringCloudFunctionExampleApplicationTests.java


package com.springcloudfunctiontest;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringCloudFunctionExampleApplicationTests {

    @Test
    public void HelloTest1() {
        Hello hello = new Hello();
        APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent();

        Map<String,String> queryStringParameter = new HashMap<>();
        queryStringParameter.put("id", "11111");
        request.setQueryStringParameters(queryStringParameter);

        APIGatewayProxyResponseEvent response = hello.apply(request);

        assertThat(response.getBody()).isEqualTo("{\"name\":\"Taro\"}");
    }

    @Test
    public void HelloTest2() {
        Hello hello = new Hello();
        APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent();

        Map<String,String> queryStringParameter = new HashMap<>();
        queryStringParameter.put("id", "22222");
        request.setQueryStringParameters(queryStringParameter);

        APIGatewayProxyResponseEvent response = hello.apply(request);

        assertThat(response.getBody()).isEqualTo("{\"name\":\"Nanashi\"}");
    }
}

#Bereitstellen Das manuelle Hochladen in S3 oder das Warten auf die Erstellung der Pipeline ist mühsam. Stellen Sie sie daher mit dem Serverless Framework in Texto bereit, da es sich nicht um eine offizielle Version der App handelt.

serverless.yml


service: test

provider:
  name: aws
  runtime: java8
  timeout: 30

  region: ap-northeast-1

package:
  artifact: target/spring-cloud-function-test-0.0.1-SNAPSHOT-aws.jar

functions:
  hello:
    handler: org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler
    events:
      - http:
          path: testapi
          method: get
          integration: lambda-proxy
          request:
            template:
              application/json: '$input.json("$")'

Wenn Sie damit bereitstellen, wird die REST-API wie folgt ordnungsgemäß zurückgegeben!

$ curl -X GET https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/testapi?id=11111; echo
{"name":"Taro"}

#Fazit Nun, ich habe das Spring-Framework überhaupt nicht genutzt, daher scheint es der gleiche Aufwand zu sein wie bei der Erstellung eines normalen Lambda-Ereignishandlers. Wäre es wünschenswert, wenn wir mehr Funktionen des Frameworks nutzen könnten?

Dieses Mal ist es meines Erachtens einfacher, die Implementierung mit APIGatewayProxyRequestEvent zu implementieren und das Serverless Framework einfacher bereitzustellen, wenn Sie Lambda-Funktionen in Java schreiben.

Recommended Posts

Schreiben wir eine Lambda-Funktion, die Amazon API Gateway in die Spring Cloud-Funktion integriert.
[Anfänger] Versuchen Sie, die REST-API für die Todo-App mit Spring Boot zu schreiben
Konfigurieren Sie Microservices mit Spring Cloud (4): API Gateway
Implementieren wir eine Funktion, um die Anzahl der Zugriffe auf die API mit SpringBoot + Redis zu begrenzen
Erstellen wir eine einfache API mit EC2 + RDS + Spring Boot ①
Erstellen Sie einen SlackBot mit AWS Lambda & API Gateway in Java
Oauth2-Authentifizierung mit Spring Cloud Gateway
Schreiben wir einen Testcode für die Anmeldefunktion mit Spring Boot
Lassen Sie uns Spring Cloud Gateway ausführlich erklären
Senden Sie nach eindeutiger Authentifizierung mit Spring Cloud Gateway eine Anfrage an das Backend
Lassen Sie uns eine Suchfunktion mit Rails (Ransack) machen
Erstellen Sie einen Web-API-Server mit Spring Boot
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 1 (API Edition)
[JUnit 5-kompatibel] Schreiben Sie einen Test mit JUnit 5 mit Spring Boot 2.2, 2.3
Implementieren Sie eine einfache Rest-API mit Spring Security mit Spring Boot 2.0
[JUnit 5] Schreiben Sie einen Validierungstest mit Spring Boot! [Parametrisierungstest]
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 2 (Client Edition)
Lassen Sie uns herausfinden, wie Sie mit Request Body mit der REST-API von Spring Boot empfangen können