本文爲翻譯發表,轉載需要註明來自公衆號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¶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的值。有關本教程,請參閱下面的示例:
- 格式: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上開發無服務器的微服務。
白小白:
爲了避免破壞原文的結構,小白的補充內容都是沒有添加截圖的,如果有什麼地方沒說明白,大家可以關注公衆號 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