產品經理教你寫代碼—用JAVA寫一個阿裏雲VPC Open API調用程序
引言
VPC提供了豐富的API接口,讓網絡工程是可以通過API調用的方式管理網絡資源。用程序和軟件管理自動化管理網絡資源是一件顯著提升運維效率和網絡生產力的事情。產品經理教你寫代碼係列文章的目標是不懂代碼的網絡工程師能一步一步的學會用API管理網絡。
另外通過文章標題大家也可以看出來,產品經理教你寫代碼肯定是一個業餘班,裏麵的代碼很多寫的都不規範,可能也有很多Bug。專業選手可以參考的有限,請適度噴,手下留情。
其實如果隻是想用單個API調用,可以用下麵這個線上工具: https://api.aliyun.com/
第一步:利其器
工欲善其事必先利其器,對於工程師來講,一定要有得心應手的工具。我個人十分推薦Eclipse作為我們的開發IDE。
從如下鏈接即可下載:
https://www.eclipse.org/downloads/
第二步:創建一個Java工程
第三步:創建代碼文件
在工程的SRC中創建代碼的源文件,比如ApiDemo.java
第四步:導入一個核心的jar包
很多同學再使用API的時候都會遇到一個特別大的問題,就是API URL拚接完成要按阿裏雲的格式生成一個“簽名”,阿裏雲有一個規定的簽名實現算法,類似於下麵這種:https://help.aliyun.com/document_detail/35735.html
這個東東肯定會難倒一片初學者。 第一個文章其實就是告訴大家,怎麼把這個簽名生成出來,怎麼把API URL生成出來。
簽名的生成涉及到加密算法,需要將一個核心的JAR導入到工程中。
下載 org.apache.commons.codec.binary.Base64
可以在百度中直接搜索“org.apache.commons.codec.binary.Base64”
或者通過如下URL下載:
https://commons.apache.org/proper/commons-codec/download_codec.cgi
或者在本文末尾的附件中下載
build path中添加外部JAR包
第五步:將下麵的代碼拷貝到源文件ApiDemo.java中
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Arrays;
import org.apache.commons.codec.binary.Base64;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.*;
import javax.swing.*;import java.awt.event.*;
public class ApiDemo extends JFrame {
private static final String ENCODING = "UTF-8";
private static final String ALGORITHM = "HmacSHA1";
private static final String HTTP_METHOD = "GET";
//不同的產品API version不一樣
private static final String urlAPIVersion = "2016-04-28";
private static final String urlSecALG = "HMAC-SHA1";
private static final String urlSecVer = "1.0";
private String urlAccKeyID = "";
private String ulrSeckey = "";
private static String urlSecNonce = UUID.randomUUID().toString();
private static final String urlFromat = "xml";
private String ulrTimeStamp =formatIso8601Date(new Date());
private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private static String formatIso8601Date(Date date) {
SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
df.setTimeZone(new SimpleTimeZone(0, "GMT"));
return df.format(date);
}
public String CreatApiURL(String strAccKeyID,String strSeckey,String strcmd) throws Exception {
urlAccKeyID=strAccKeyID;
ulrSeckey =strSeckey;
ulrSeckey = ulrSeckey+"&";
String urlNonce = UUID.randomUUID().toString();
String phrase =strcmd;
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
df.setTimeZone(new SimpleTimeZone(0, "GMT"));
ulrTimeStamp = df.format(date);
Map<String, String> parameters = new HashMap<String, String>();
// 加入公共請求參數
parameters.put("Format", urlFromat);
parameters.put("Version", urlAPIVersion);
parameters.put("SignatureMethod", urlSecALG);
parameters.put("SignatureNonce", urlNonce);
parameters.put("SignatureVersion", urlSecVer);
parameters.put("AccessKeyId", urlAccKeyID);
parameters.put("Timestamp", ulrTimeStamp);
String delims1 = ";";
String[] tokens1 = phrase.split(delims1);
for (int i = 0; i < tokens1.length; i++)
{
String delims2 = "=";
String[] tokens2 = tokens1[i].split(delims2);
parameters.put(tokens2[0], tokens2[1]);
}
// 對參數進行排序
String[] sortedKeys = parameters.keySet().toArray(new String[]{});
Arrays.sort(sortedKeys);
final String SEPARATOR = "&";
// 生成stringToSign字符串
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(HTTP_METHOD).append(SEPARATOR);
String value = "/";
try {
value = URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
stringToSign.append(value).append(SEPARATOR);
StringBuilder canonicalizedQueryString = new StringBuilder();
for(String key : sortedKeys) {
// 這裏注意對key和value進行編碼
String value1 = key;
try {
value1 = URLEncoder.encode(value1, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String value2 = parameters.get(key);
try {
value2 = URLEncoder.encode(value2, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
canonicalizedQueryString.append("&")
.append(value1).append("=")
.append(value2);
}
// 這裏注意對canonicalizedQueryString進行編碼
String value3 = canonicalizedQueryString.toString().substring(1);
try {
value3 = URLEncoder.encode(value3, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
stringToSign.append(value3);
Mac mac = null;
try {
mac = Mac.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
mac.init(new SecretKeySpec(ulrSeckey.getBytes(ENCODING), ALGORITHM));
} catch (InvalidKeyException | UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] signData = null;
try {
signData = mac.doFinal(stringToSign.toString().getBytes(ENCODING));
} catch (IllegalStateException | UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String signature = new String(Base64.encodeBase64(signData));
value = signature;
try {
value = URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String urlSignature = value;
StringBuilder urlReq = new StringBuilder();
//vpc的調用入口,如果是雲監控的入口,則是https://metrics.cn-beijing.aliyuncs.com/的形式
urlReq.append("https://vpc.aliyuncs.com");
urlReq.append("?Signature=");
urlReq.append(urlSignature);
for(String key : sortedKeys) {
urlReq.append("&")
.append(key)
.append("=")
.append(parameters.get(key));
}
System.out.println(urlReq.toString());
return urlReq.toString();
}
public ApiDemo() throws Exception {
setSize(400,700);
setLayout(new FlowLayout(FlowLayout.CENTER,10,30));
JPanel panel=new JPanel();
JTextField textField_AccID=new JTextField(30);
JTextField textField_Acckey=new JTextField(30);
JTextField textField_Cmd=new JTextField(30);
JTextField textField_URL=new JTextField(30);
JButton button=new JButton(" 生成OPEN API URL ");
JLabel AccID=new JLabel("請輸入Access Key ID:");
JLabel AccKey=new JLabel("請輸入Access Key Secret:");
JLabel Cmd=new JLabel("請輸入命令:");
JLabel Cmd_tishi1=new JLabel("格式為: 參數名稱1=參數描述1;參數名稱2=參數描述2 ");
JLabel Cmd_tishi2=new JLabel("如:Action=DescribeEipAddresses;RegionId=cn-beijing");
JLabel URLResult=new JLabel(" Open API URL生成結果: ");
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自動生成的方法存根
urlAccKeyID=textField_AccID.getText();
ulrSeckey =textField_Acckey.getText();
String strCmd = textField_Cmd.getText();
String strApiUrl = "";
try {
strApiUrl = CreatApiURL(urlAccKeyID,ulrSeckey,strCmd);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
textField_URL.setText(strApiUrl);
}
});
getContentPane().add(panel);
getContentPane().add(AccID);
getContentPane().add(textField_AccID);
getContentPane().add(AccKey);
getContentPane().add(textField_Acckey);
getContentPane().add(Cmd);
getContentPane().add(Cmd_tishi1);
getContentPane().add(Cmd_tishi2);
getContentPane().add(textField_Cmd);
getContentPane().add(button);
getContentPane().add(URLResult);
getContentPane().add(textField_URL);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(3);
}
public static void main(String[] args) throws Exception {
ApiDemo API_GEN = new ApiDemo();
}
}
第六步:運行程序
要使用Open API 必須要用AK。具體的AK如何獲取,參考下圖的入口進到AK管理界麵獲取。
查詢命令必須要按 :參數名稱1=參數描述1;參數名稱2=參數描述2 這種格式,;需要在英文狀態下輸入,輸入不要有空格
將生成的URL粘貼到瀏覽器後回車,顯示效果如下:
第七步:導出一個可以運行的JAR包
最後更新:2017-10-18 09:03:21