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(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
コメント