[英]AWS Lambda - Java Beans
我有一個如下要求:
package pricing
import scala.beans.BeanProperty
class Request(@BeanProperty var name: String, @BeanProperty var surname: String) {
def this() = this(name="defName", surname="defSurname")
}
處理程序如下:
package pricing
import com.amazonaws.services.lambda.runtime.{Context, RequestHandler}
import scala.collection.JavaConverters
import spray.json._
class ApiGatewayHandler extends RequestHandler[Request, ApiGatewayResponse] {
import DefaultJsonProtocol._
def handleRequest(input: Request, context: Context): ApiGatewayResponse = {
val headers = Map("x-foo" -> "coucou")
val msg = "Hello " + input.name
val message = Map[String, String]("message" -> msg )
ApiGatewayResponse(
200,
message.toJson.toString(),
JavaConverters.mapAsJavaMap[String, Object](headers),
true
)
}
}
已記錄為:
functions:
pricing:
handler: pricing.ApiGatewayHandler
events:
- http:
path: pricing/test
method: get
documentation:
summary: "submit your name and surname, the API says hi"
description: ".. well, the summary is pretty exhaustive"
requestBody:
description: "Send over name and surname"
queryParams:
- name: "name"
description: "your 1st name"
- name: "surname"
description: ".. guess .. "
methodResponses:
- statusCode: "200"
responseHeaders:
- name: "x-foo"
description: "you can foo in here"
responseBody:
description: "You'll see a funny message here"
responseModels:
"application/json": "HelloWorldResponse"
好吧,這是其中一個教程的復制和粘貼。 而且它不起作用。 我猜想BeanProperty
是指主體對象的屬性。 這就是我從here
的示例中可以猜到的。
如果我想查詢字符串?
嘗試是:
package pricing
import scala.beans.BeanProperty
import spray.json._
abstract class ApiGatewayGetRequest(
@BeanProperty httpMethod: String,
@BeanProperty headers: Map[String, String],
@BeanProperty queryStringParameters: Map[String, String])
abstract class ApiGatewayPostRequest(
@BeanProperty httpMethod: String,
@BeanProperty headers: Map[String, String],
@BeanProperty queryStringParameters: Map[String, String])
class HelloWorldRequest(
@BeanProperty httpMethod: String,
@BeanProperty headers: Map[String, String],
@BeanProperty queryStringParameters: Map[String, String]
) extends ApiGatewayGetRequest(httpMethod, headers, queryStringParameters) {
private def getParam(param: String): String =
queryStringParameters get param match {
case Some(s) => s
case None => "default_" + param
}
def name: String = getParam("name")
def surname: String = getParam("surname")
def this() = this("GET", Map.empty, Map.empty)
}
結果是:
{
"message":"Hello default_name"
}
提示該類已用一個空映射代替了queryStringParameters
初始化,但是已正確提交
Mon Sep 25 20:45:22 UTC 2017 : Endpoint request body after
transformations:
{"resource":"/pricing/test","path":"/pricing/test","httpMethod":"GET","headers":null,"queryStringParameters":{"name":"ciao", "surname":"bonjour"},"pathParameters":null,"stageVariables":null,
...
注意:我遵循這條路徑,因為我覺得將@BeanProperty queryStringParameters: Map[String, String]
的Map
替換為類型T會很方便且富有表現力
case class Person(@beanProperty val name: String, @beanProperty val surname: String)
但是,上面的代碼將{"name":"ciao", "surname":"bonjour"}
視為String
,而沒有弄清楚它應該反序列化該String。
編輯
我也嘗試用java.util.Map[String, String]
替換scala映射,但沒有成功
默認情況下,Serverless啟用lambda和API Gateway之間的代理集成 。 對您來說,這意味着API Gateway將把包含有關請求的所有元數據的對象傳遞到處理程序中,如您所注意到的:
Mon Sep 25 20:45:22 UTC 2017:轉換后的端點請求主體:{“資源”:“ /定價/測試”,“路徑”:“ /定價/測試”,“ httpMethod”:“ GET”,“標題“:null,” queryStringParameters“:{” name“:” ciao“,” surname“:” bonjour“},” pathParameters“:null,” stageVariables“:null,...
這顯然不會映射到僅包含字段name
和surname
模型。 有幾種方法可以解決此問題。
如果通過使字段可變(從而為它們創建設置器)使您的類成為適當的POJO,則對HelloWorldRequest
類的嘗試實際上可以起作用:
class HelloWorldRequest(
@BeanProperty var httpMethod: String,
@BeanProperty var headers: java.util.Map[String, String],
@BeanProperty var queryStringParameters: java.util.Map[String, String]
) extends ApiGatewayGetRequest(httpMethod, headers, queryStringParameters) {
AWS Lambda文檔指出 :
為了使POJO與AWS Lambda的內置JSON序列化器一起使用,需要get和set方法。
另外請記住,不支持Scala的地圖。
如果不需要元數據,則可以使用映射模板使API Gateway僅將所需的數據傳遞給lambda,而無需更改模型。
為此,您需要告訴Serverless使用純lambda集成(而不是proxy)並指定一個自定義請求模板 。
Amazon API Gateway文檔提供了一個示例請求模板 ,該模板幾乎可以完美解決您的問題。 量身定制,我們得到了
functions:
pricing:
handler: pricing.ApiGatewayHandler
events:
- http:
path: pricing/test
method: get
integration: lambda
request:
template:
application/json: |
#set($params = $input.params().querystring)
{
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
此模板將從查詢字符串參數中生成JSON,現在它將作為lambda的輸入:
轉換后的端點請求主體:{“ name”:“ ciao”}
哪個可以正確映射到您的模型。
請注意,禁用代理集成也會更改響應格式。 您會注意到,現在您的API直接返回了響應模型:
{“ statusCode”:200,“ body”:“ {\\” message \\“:\\” Hello ciao \\“}”,“ headers”:{“ x-foo”:“ coucou”},“ base64Encoded”:true}
您可以通過修改代碼以僅返回正文或添加自定義響應模板來解決此問題:
response:
template: $input.path('$.body')
這會將輸出轉換為您期望的結果,但會公然忽略statusCode
和headers
。 您將需要進行更復雜的響應配置以處理這些問題。
您可以擴展RequestStreamHandler
, 而不是擴展 RequestHandler
並讓AWS Lambda將JSON映射到POJO,這將為您提供InputStream
和OutputStream
,因此您可以使用您選擇的JSON序列化器進行(反序列化)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.