使用Lambda和API网关在Java中开发RESTful微服务

本文为翻译发表,转载需要注明来自公众号EAWorld。

作者:Muhammad Ali

译者:白小白

原题:Developing RESTful APIs in Java using Amazon APIGateway and AWS Lambda

全文2294字,阅读约需要10分钟

白小白:

记得之前有一位兄弟说过,写代码的同学最恨的就是按照一个教程一步步做,结果卡在那里做不下去。保险起见,作为Java零基础的小白对本文的实例进行了验证。一些遇到卡壳的地方,以注释的形式对原文进行了补充,当然,相关异常也可能不出现,那说明你脸比较白,自然要恭喜。小白的验证的环境如下:Win10(64位)+Eclipse(Photon)+JavaSE8(64位)。全文的实践要在两个环境中进行,一是Eclipse客户端(本地),一是在AWS的控制台(远程/浏览器访问 https://console.aws.amazon.com/console/home )。

导言

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&param2=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”。

7.选择[NewStage]并提供一个staging名称和描述。在本教程中,我们使用“Dev”作为名称。一旦部署完成,控制台将带您到staging页。

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&param2=100

输出如下:

结语

像AWS Lambda这样的无服务器计算平台最近非常流行。许多组织要求他们的DevOps工程师能够开发无服务器应用程序,因为它减少了设置硬件/软件基础结构所需的时间,从而减少了项目交付时间。遵循这个简单的教程,您应该能够开始使用Java在AWS上开发无服务器的微服务。

白小白:

为了避免破坏原文的结构,小白的补充内容都是没有添加截图的,如果有什么地方没说明白,大家可以关注公众号 EAWorld 戳 “加群”,然后在群内提问,只要是我遇到过的问题,我会再作进一步的解释。

原文链接:

https://www.bluestackcloud.com/insights/2018/6/14/developing-restful-apis-in-java-using-amazon-api-gateway-and-aws-lambda

关于作者:Muhammad Ali,DevOps Engineer,BluestackCloud

原文发布于微信公众号 - EAWorld(eaworld)

原文发表时间:2018-08-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏黑泽君的专栏

SolrCloud搭建 + zookeeper集群搭建 + 搜索功能切换到集群版 + httpclient学习 + 全局异常处理器

索引集合包括两个Shard(Shard1和Shard2),Shard1和Shard2分别由三个Core组成,其中一个Leader两个Replication,L...

1982
来自专栏Jed的技术阶梯

zookeeper编程01-循环监听

客户端发起对节点的事务操作(以NodeChildrenChanged事件为例) 服务端监听到对应的事件后进行相应的操作

4372
来自专栏c#开发者

Asp.Net MVC +EntityFramework主从表新增编辑操作的实现(删除操作怎么实现?)

Asp.Net MVC +EntityFramework主从表新增编辑操作的实现 对于MVC中同时对主从表的表单操作在网上现有的解决很少,而这样的操作在做业务系...

4188
来自专栏极乐技术社区

小程序支付详解+源码(客户端+服务端)

小程序的支付调通,和大家分享下(坑) 包括小程序端、java服务器端 和其他方式的微信支付方式区别不大,也都需要经过统一下单、支付结果通知(回调),具体流程如...

2475
来自专栏DOTNET

ASP.NET MVC编程——验证、授权与安全

1 验证 一般采用表单验证完成登陆验证,建议结合SSL使用。为限制控制器只能执行HTTPS,使用RequireHttpsAttribute 2 授权 对账户的...

3686
来自专栏程序你好

不同的.Net版本客户端软件调用Java Web Service区别

最近的系统中需要.Net开发的离线端软件通过Web Service技术和Java开发的在线系统进行数据交互。

1183
来自专栏一个爱瞎折腾的程序猿

在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制

在此之前的接口项目中,若使用了 Swashbuckle.AspNetCore,都是控制其只在开发环境使用,不会就这样将其发布到生产环境(安全第一) 。 那么,...

1741
来自专栏木宛城主

基于Socket的网络聊天室编程(第一版)

一:什么是套接字 在网络编程中最常用的方案便是Client/Server (客户机/服务器)模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常...

2905
来自专栏林德熙的博客

C# 配置文件存储 各种序列化算法性能比较

本文比较多个方式进行配置文件的存储,对比各个不同算法的读写性能。 在应用软件启动的时候,需要读取配置文件,但是启动的性能很重要,所以需要有一个很快的读取配置文件...

2232
来自专栏恰童鞋骚年

设计模式的征途—19.命令(Command)模式

在生活中,我们装修新房的最后几道工序之一是安装插座和开关,通过开关可以控制一些电器的打开和关闭,例如电灯或换气扇。在购买开关时,用户并不知道它将来到底用于控制什...

682

扫码关注云+社区

领取腾讯云代金券