使用Lambda和API网关在Java中开发RESTful微服务
导言
AWS Lambda和AmazonAPI-Gateway可用于在Java中创建RESTfulWeb服务,而无需进行复杂的Java框架配置或设置和维护Web服务器(如Tomcat、WebSphere等)。Lambda和APIGateway的结合使得开发API变得非常容易,并且还可以轻松地管理API的暂存环境,比如开发、测试和Prod。
AWS Lambda是一个高度可伸缩和高度可用的无服务器计算平台,您可以使用它运行Java代码来提供服务的主要功能。有关Lambda的更多信息,请访问链接
(https://aws.amazon.com/documentation/lambda/).
AmazonAPI网关是由AWS提供的一种网络服务,允许开发人员轻松地构建和部署API端点。它使开发人员非常容易地创建HTTPS端点并将其与Lambda函数集成。数据从API端点传递到Lambda函数,并由API网关处理。欲了解更多关于API网关的内容,请访问链接
(https://aws.amazon.com/documentation/apigateway/).
本文提供了关于如何使用Lambda和API网关在Java中开发RESTful微服务的循序渐进的指南。
先决条件
首先,您需要准备一台开发机器,为此您需要Java 8、Eclipse IDE和AWSToolkit for Eclipse。有关如何完成此操作的详细信息,请参阅
(https://www.bluestackcloud.com/insights/2018/5/7/getting-started-with-aws-development-using-java).
白小白:
如果Marketplace闪退,在Eclipse的 Help –> Install New Software,通过在Work with处输入 http://download.eclipse.org/mpc/photon/重新安装。注意,在后续步骤有一个安装组件选择的勾选列表,如果本机没有安装RDS数据库,把关于RDS这一项勾选去掉,否则后续步骤会报错。
步骤1:(环境:Eclipse本地)创建Lambda函数
1. 一旦您准备好使用Eclipse IDE,AWS图标将出现在主工具栏中。点击它并选择“新AWS Lambda项目.”
2.提供适当的项目名称和Maven配置。选择“Stream Request Handler”作为输入类型。
3. 在点击“Finish”之后,示例代码将被加载到您新创建的项目中。打开主处理程序函数并更新以下代码。
package com.amazonaws.lambda.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.Writer;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
public class LambdaFunctionHandler implements RequestStreamHandler
{
JSONParser parser = new JSONParser();
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException
{
LambdaLogger logger = context.getLogger();
logger.log("Loading Java Lambda handler of ProxyWithStream");
String proxy = null;
String param1 = null;
String param2 = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
JSONObject responseJson = new JSONObject();
String responseCode = "200";
JSONObject event = null;
try {
event = (JSONObject)parser.parse(reader);
if (event.get("pathParameters") != null) {
JSONObject pps = (JSONObject)event.get("pathParameters");
if ( pps.get("proxy") != null) {
proxy = (String)pps.get("proxy");
}
}
if (event.get("queryStringParameters") != null)
{
JSONObject qps = (JSONObject)event.get("queryStringParameters");
if ( qps.get("param1") != null)
{
param1 = (String)qps.get("param1");
}
}
if (event.get("queryStringParameters") != null)
{
JSONObject qps = (JSONObject)event.get("queryStringParameters");
if ( qps.get("param2") != null)
{
param2 = (String)qps.get("param2");
}
}
}
catch(Exception pex)
{
responseJson.put("statusCode", "400");
responseJson.put("exception", pex);
}
// Implement your logic here
int output = 0;
if (proxy.equals("sum"))
{
output = sum(Integer.parseInt(param1), Integer.parseInt(param2));
}
else if (proxy.equals("subtract"))
{
output = subtract(Integer.parseInt(param1), Integer.parseInt(param2));
}
JSONObject responseBody = new JSONObject();
responseBody.put("input", event.toJSONString());
responseBody.put("message", "Output is" + output);
JSONObject headerJson = new JSONObject();
headerJson.put("x-custom-header", "my custom header value");
headerJson.put("Access-Control-Allow-Origin", "*");
responseJson.put("isBase64Encoded", false);
responseJson.put("statusCode", responseCode);
responseJson.put("headers", headerJson);
responseJson.put("body", responseBody.toString());
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
writer.write(responseJson.toJSONString());
writer.close();
}
public int sum(int a, int b)
{
return a+b;
}
public int subtract(int a, int b)
{
return a-b;
}
}
(左右滑动可查看全部代码)
白小白:
首先是代码中的类名,需要修改为第2步中的Class name,。其次是可能会遇到JSON无法解析的错误。需要下载JSON的包然后引入项目。引入的方法是将JSON包下载到本地,然后在项目上右键 –> Build Path –> Add External Achives 选择本地包添加即可。JSON包的下载地址(http://www.java2s.com/Code/JarDownload/json-simple/json-simple-1.1.jar.zip)。如果遇到 Fatal error compiling: tools.jar not found 的报错,从Eclipse菜单中选择 Windows -> Preferences -> Java -> Installed JREs –> Execution Environment -> JavaSE1.x -> JDE 1.x 勾选即可。至于那个.x,我选择的是最低版本号1.6
4. 构建并部署此Lambda函数。有关部署Java Lambda函数的完整信息可以找到这里
(https://docs.aws.amazon.com/lambda/latest/dg/java-create-jar-pkg-maven-and-eclipse.html).
白小白:
构建部署的方法其实很简单,就是在项目上右键 –> Amazon Web Services –> Upload function to AWS Lambda。但是前提是你需要有一个AWS的账号,并需要提供给Eclipse客户端一个Access Key ID和Secret Access Key。这需要你在AWS的控制台创建一个用户,并为用户添加 AdministratorAccess 权限,创建过程中可得到这两个值。但要及时保存,否则在创建后,Secret Access Key是不可见的,除非在安全证书页面重新创建访问密钥。上传函数的过程,可能会有部分输入框提示not found,此时只需要点击其右侧的create即可。
在这个例子中,我们用“REST_API_HelloWorld”的名称在AWS控制台中创建了Lambda函数。
步骤2:(环境:AWS控制台/网页)创建API网关端点
1.转到AWS控制台并启动API-网关服务。
2.点击“创建API”。
3.选择“新API”并提供“API名称”
4.在创建API之后,添加一个资源,如下所示:
5. 确保勾选“配置为代理资源”选项。
在下一个显示“Any”方法设置的屏幕上,选择“Lambda Function”作为集成类型。同时选中“Use Lambda Proxy integration”。选择部署Lambda函数的区域,并输入Lambda名称。
白小白:上面的Lambda Function输入框,可以输入刚才上传的函数名称,会出现下拉列表选择。在下一个部署API的步骤前,其实已经可以测试API是否可以正常工作,即点击 资源 - ANY 再点击测试,方法选择GET ,在 路径 处输入 sum ,在查询字串处输入 param1=100¶m2=100 ,点击测试,在右侧的响应正文部分,message的值应该为 "Output is 200"。如果很不幸,测试不成功,右侧显示的错误是:Malformed Lambda proxy response (正如第一次部署时小白所遇到的情况),可以尝试以下方法:1、确认第4步中的Enable API Gateway CORS是否已经勾选。;2、在代码中注释掉 headerJson.put("Access-Control-Allow-Origin", "*"); 这句话。6.现在,我们将把这个API部署到一个暂存环境中。为此,单击“Action”并选择“Deploy API”。
8.复制“Invoke URL”,并在其上添加代理资源名称和参数,其中包含要发送给Lambda的值。有关本教程,请参阅下面的示例:
● 格式:https://5yv20hbz44.execute-api.eu-west-1.amazonaws.com/Dev/{proxy}?{set_of_params_separated_by_&}● 示例:https://5yv20hbz44.execute-api.eu-west-1.amazonaws.com/Dev/sum?param1=100¶m2=100
输出如下:
像AWS Lambda这样的无服务器计算平台最近非常流行。许多组织要求他们的DevOps工程师能够开发无服务器应用程序,因为它减少了设置硬件/软件基础结构所需的时间,从而减少了项目交付时间。遵循这个简单的教程,您应该能够开始使用Java在AWS上开发无服务器的微服务。
原文发布时间为:2018-08-29
本文作者:白小白
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一个高频面试题,考考大家对 Java String 常量池的理解。
近日,有一个网友在小密圈提了一个问题,我本来觉得这个问题应该挺简单的,没想到这个问题在圈子里引起了广泛的讨论。 问题:前辈,请教个问题,下面两行代码,会在JAVA字符串常量池中产生几个字符串。 String str1 = "ab"; String str2 = str1 + "c"; 对这个引起热烈讨论的问题,我本来想写一篇深度讲解的文章,结果在网上发现了一篇很优秀的关于此题原理的文章,先分享给大家。 String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字符串常量池的设计意图是什么? 字符串常量池在哪里? 如何操作字符串常量池? 字符串常量池的设计思想 字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能 JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化 为字符串开辟一个字符串常量池,类似于缓存区 创建字符串常量时,首先坚持字符串常量池是否存...
- 下一篇
iOS objc_msgSend尾调用优化详解
这篇文章将认真彻底地分析 OC对objc_msgSend的尾调用优化。 Q1:什么是尾调用? 尾调用(Tail Call):某个函数的最后一步仅仅只是调用了一个函数(可以是自身,可以是另一个函数)。提醒:注意 “仅仅” 两个字。 尾调用例子: // 尾调用: - (NSInteger)funcA:(NSInteger)num { /* Some codes... */ if (num == 0) { return [self funcA:num];// 尾调用->自身 } if (num > 0) { return [self funcB:num];// 尾调用->函数funcB } return [self funcC:num];// 尾调用->函数funcC } 正例解释:funcA的最后一步仅仅调用了另一个函数。不论是调用funcA、funcB还是funcC都属于尾调用。~(不论调用函数的位置在哪,只要最后一步仅仅调用一个函数就行)~ 反例:不是尾调用的例子 // 不是尾调用1: - (NSInteger)funcA:(NSInteger)num { NS...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7,CentOS8安装Elasticsearch6.8.6