API Gateway + Lambda(Java17)で複数REST APIを作成する – 【aws-serverless-java-container】
aws-serverless-java-containerを使用して、1つのLambda(Java17)で複数のREST APIを作成します。
API Gatewayのエンドポイントはすべて同じ1つのLambdaになります。
| URI | メソッド | Lambda |
|---|---|---|
| /dev/message | GET | message-lambda |
| /dev/message | POST | message-lambda |
| /dev/message | PUT | message-lambda |
| /dev/message | DELETE | message-lambda |
1つのzipをLambdaにデプロイして複数エンドポイントを作成することが可能です。
| 項目 | 値 |
|---|---|
| Spring Boot | 3.1.2 |
| Group Id | jp.co.confrage |
| Artifact Id | demo |
| Packaging Type | jar※zip |
| Java Version | 17 |
依存関係
依存関係にaws-serverless-java-container-springboot3を追加します。これでaws-serverless-java-container-core、aws-lambda-java-coreライブラリも自動的にインポートされます。
implementation 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.0-M2'
ちなみに今回Tomcatは不要なのでexcludeしておきます。
implementation ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
Lambda
RequestStreamHandlerインタフェースをimplementsしたクラスをエントリポイントとして作成します。※Lambdaプロキシ統合を使用する
Handler.java
package jp.co.confrage.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import jakarta.ws.rs.core.Application;
public class Handler implements RequestStreamHandler{
private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
static {
try {
handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class);
} catch (ContainerInitializationException e) {
e.printStackTrace();
throw new RuntimeException("Could not initialize Spring Boot application", e);
}
}
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
throws IOException {
handler.proxyStream(inputStream, outputStream, context);
}
}
REST APIを作成します。
DemoController.java
package jp.co.confrage.demo;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@RequestMapping(path = "/message",method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getHello(@RequestHeader HttpHeaders headers) throws Exception {
return new ResponseEntity<>("GET.", headers, HttpStatus.OK);
}
@RequestMapping(path = "/message",method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> postHello(@RequestHeader HttpHeaders headers) throws Exception {
return new ResponseEntity<>("POST.", headers, HttpStatus.OK);
}
@RequestMapping(path = "/message",method = RequestMethod.PUT,produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> putHello(@RequestHeader HttpHeaders headers) throws Exception {
return new ResponseEntity<>("PUT.", headers, HttpStatus.OK);
}
@RequestMapping(path = "/message",method = RequestMethod.DELETE,produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> putBye(@RequestHeader HttpHeaders headers) throws Exception {
return new ResponseEntity<>("DELETE.", headers, HttpStatus.OK);
}
}
zip作成
Lambda関数にアップロードするためのzipを作成しますがコチラを参考にgradle taskを追加します。組み込みTomcatを除外してzip作成します。
task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from(configurations.compileClasspath) {
exclude 'tomcat-embed-*'
}
}
}
build.dependsOn buildZip
buildZipタスクが追加されます。
buildZipタスクを実行するとzipが作成されます。このzipをlambdaにアップロードしてデプロイします。
ハンドラが「example.Hello::handleRequest」となっているので、「jp.co.confrage.demo.Handler::handleRequest」に変更します。
build.gradle
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.2'
id 'io.spring.dependency-management' version '1.1.2'
}
group = 'jp.co.confrage'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.0-M2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {
useJUnitPlatform()
}
task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from(configurations.compileClasspath) {
exclude 'tomcat-embed-*'
}
}
}
build.dependsOn buildZip
API Gateway
API Gatewayの設定をします。Lambda Proxy統合を使用します。
テスト
curlでテストします。
$ curl -i -X DELETE \ https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/messages HTTP/1.1 200 OK Date: Thu, 24 Aug 2023 12:24:30 GMT Content-Type: application/json Content-Length: 28 Connection: keep-alive x-amzn-RequestId: 12c59df2-effd-43ae-915b-d4c967555879 Accept: */* x-amzn-Remapped-Content-Length: 28 X-Forwarded-Proto: https x-amz-apigw-id: KKjPTFoVtjMFbVw= x-amzn-Remapped-User-Agent: curl/8.0.1 x-amzn-Remapped-Host: xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com X-Amzn-Trace-Id: Root=9-33e74bfb-57956e6h1afd8ea48c296fh7 x-amzn-Remapped-X-Forwarded-For: 60.100.40.40 X-Forwarded-Port: 443 DELETE.
同様にGET,POST,PUTでもcurlでAPIをたたくことができます。これで1つのLambdaで複数REST APIを実装できます。
HTTP API
API GatewayがHTTP APIの場合はSpringBootLambdaContainerHandler.getAwsProxyHandler()メソッドではなく、SpringBootLambdaContainerHandler.getHttpApiV2ProxyHandler()メソッドを使用します。
戻り値も以下のようにHttpApiV2ProxyRequestに変わります。
private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler; ↓ private static SpringBootLambdaContainerHandler<HttpApiV2ProxyRequest, AwsProxyResponse> handler;
ドキュメント

KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES20xx),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^





コメント