这是我在Lambda中处理SNS事件的方式:
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
public class SnsHandler implements RequestHandler<SNSEvent, Object> {
public Object handleRequest(SNSEvent event, Context context) {
System.out.println("sns event");
System.out.println(event.getRecords().get(0).getSNS().getMessage());
return null;
}
}
我已经有了一个使用API网关HTTP请求与SpringLambdaContainerHandler
配合工作的Spring应用程序。这是我如何将其与lambda集成:
import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.internal.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.internal.model.AwsProxyResponse;
import com.amazonaws.serverless.proxy.spring.SpringLambdaContainerHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.maciejsobala.aws.webpush.AwsWebPushApp;
public class HttpHandler implements RequestHandler<AwsProxyRequest, AwsProxyResponse> {
SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context context) {
awsProxyRequest.setPath("/" + awsProxyRequest.getPathParameters().get("proxy")); //because I am using {proxy} in my API gateway
if (handler == null) {
try {
handler = SpringLambdaContainerHandler.getAwsProxyHandler(AwsWebPushApp.class);
} catch (ContainerInitializationException e) {
e.printStackTrace();
return null;
}
}
return handler.proxy(awsProxyRequest, context);
}
}
现在我希望能够在SnsHandler中重用我的Spring应用程序(其中包含一些存储库和其他逻辑)。
我的第一种方法是重用与HttpHandler类似的代码(如果可以的话,我想创建一个单独的端点用于sns操作,并以某种方式保护它,只能从SnsHandler中执行)。
public class SnsHandler implements RequestHandler<SNSEvent, Object> {
SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
AwsProxyRequest awsProxyRequest = new AwsProxyRequest();
ApiGatewayRequestContext requestContext = new ApiGatewayRequestContext();
ApiGatewayRequestIdentity identity = new ApiGatewayRequestIdentity();
{
awsProxyRequest.setPath("/ping");
awsProxyRequest.setHttpMethod("GET");
identity.setSourceIp("someIp");
requestContext.setIdentity(identity);
awsProxyRequest.setRequestContext(requestContext);
}
public Object handleRequest(SNSEvent event, Context context) {
System.out.println("sns event");
System.out.println(event.getRecords().get(0).getSNS().getMessage());
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(AwsWebPushApp.class);
if (handler == null) {
try {
handler = SpringLambdaContainerHandler.getAwsProxyHandler(AwsWebPushApp.class);
} catch (ContainerInitializationException e) {
e.printStackTrace();
return null;
}
}
handler.proxy(awsProxyRequest, context);
return null;
}
}
不幸的是,我得到了
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
... some stack trace...
Caused by: java.lang.NullPointerException
at org.springframework.web.util.UrlPathHelper.getRemainingPath(UrlPathHelper.java:245)
...rest of the stack trace...
我有两个问题:
- 如何正确地将SNS与Spring应用程序集成到Lambda函数中(我正在尝试实现的只是一个解决方法)?
- 如果没有更好的方法,如何获取给定异常的原始信息。换句话说:如何适当地伪造http请求?
我查看了http://cloud.spring.io/spring-cloud-aws/spring-cloud-aws.html,但据我所知,它不适用于Lambda环境。