本文為翻譯發表,轉載需要註明來自公眾號EAWorld。
作者:MuhammadAli
譯者:白小白
原題:Developing RESTful APIs in Java using Amazon APIGateway and AWS Lambda
白小白:
記得之前有一位兄弟說過,寫代碼的同學最恨的就是按照一個教程一步步做,結果卡在那裡做不下去。保險起見,作為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¶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」。
7.選擇[NewStage]並提供一個staging名稱和描述。在本教程中,我們使用「Dev」作為名稱。一旦部署完成,控制臺將帶您到staging頁。
8.複製「Invoke URL」,並在其上添加代理資源名稱和參數,其中包含要發送給Lambda的值。有關本教程,請參閱下面的示例:
輸出如下:
像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:微服務,DevOps,數據治理,移動架構原創技術分享,長按二維碼關注