1. 程式人生 > >總想自己動動手系列·1·本地和外網(Liunx伺服器上部署的web專案)按照自定義的報文格式進行互動(一)

總想自己動動手系列·1·本地和外網(Liunx伺服器上部署的web專案)按照自定義的報文格式進行互動(一)

一、準備工作

(1)有一臺屬於自己的雲伺服器,併成功部署和釋出一個web專案(當然,本質上來說Java-Project也沒問題),通過外網IP可以正常訪問該web專案。

  需要說明的是:任何web專案,只要成功部署後在外網上能訪問到即可。本案例注重修改web對請求的監聽和過濾的處理(下個版本在弄這個啦!)。

(2)本地新建Java-project,需要準備一些jar包,比如:AES加密相關的包,BASE64加相關的包,至於通訊相關的類,JDK的java.io和java.net自帶。

 二、Code部分

(1)第一步:首先建立一個介面,先定義好規則(比如:需要用到哪些方法等)

 

 1 package com.xfwl.message.serverMsg;
 2 
 3 import java.net.URL;
 4 import java.net.URLConnection;
 5 import java.util.Map;
 6 
 7 /**
 8  * 通訊類介面
 9  * @function  
10  * @author 小風微涼
11  * @time  2018-11-8 下午2:03:39
12  */
13 public interface IHttpClient {
14     /**
15      * 預設編碼格式
16      */
17 static final String CHARTER_ENCODE="UTF-8"; 18 //建立報文傳送物件 19 public URLConnection getClient(String url); 20 //建立傳送報文方法 21 public boolean sendDataMsg(URLConnection url,String encygen); 22 //建立接收報文方法 23 public StringBuffer receiveDataMsg(URLConnection url,String encygen); 24 //
建立報文加密方法 25 public StringBuffer encryptMsg(String data,String encygen); 26 //建立報文解密方法 27 public StringBuffer deCioherMsg(String data,String encygen); 28 }

 (2)第二步:準備要用到的工具類,比如報文的加密、解密等,下面用到的時AES加密(加解密時都需要加密因子,中間使用了Base64改變編碼格式) 

  1 package com.xfwl.message.serverMsg;
  2 
  3 import java.security.NoSuchAlgorithmException;
  4 import java.security.SecureRandom;
  5 import java.util.logging.Level;
  6 import java.util.logging.Logger;
  7 
  8 import javax.crypto.Cipher;
  9 import javax.crypto.KeyGenerator;
 10 import javax.crypto.SecretKey;
 11 import javax.crypto.spec.SecretKeySpec;
 12 import org.apache.commons.codec.binary.Base64;
 13 /**
 14  * AES加密、解密處理工具(加密因子+base64的加解密)
 15  * @function  
 16  * @author 小風微涼
 17  * @time  2018-11-8 下午2:35:15
 18  */
 19 public class AESUtil {
 20     //預設加密祕鑰
 21     private static final String KEY_ALGORITHM = "AES";
 22     //預設的加密演算法
 23     private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
 24     /**
 25      * AES 加密操作
 26      *
 27      * @param content 待加密內容
 28      * @param password 加密密碼
 29      * @return 返回Base64轉碼後的加密資料
 30      */
 31     public static String encrypt(String content, String password) {
 32         try {
 33             Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 建立密碼器
 34 
 35             byte[] byteContent = content.getBytes("utf-8");
 36 
 37             cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化為加密模式的密碼器
 38 
 39             byte[] result = cipher.doFinal(byteContent);// 加密
 40 
 41             return Base64.encodeBase64String(result);//通過Base64轉碼返回
 42         } catch (Exception ex) {
 43             Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
 44         }
 45 
 46         return null;
 47     }
 48 
 49     /**
 50      * AES 解密操作
 51      *
 52      * @param content 資料
 53      * @param password 加密因子
 54      * @return
 55      */
 56     public static String decrypt(String content, String password) {
 57         try {
 58             //例項化
 59             Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
 60 
 61             //使用金鑰初始化,設定為解密模式
 62             cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
 63 
 64             //執行操作
 65             byte[] result = cipher.doFinal(Base64.decodeBase64(content));
 66 
 67             return new String(result, "utf-8");
 68         } catch (Exception ex) {
 69             Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
 70         }
 71         
 72         return null;
 73     }
 74 
 75     /**
 76      * 生成加密祕鑰
 77      * @param   password 加密因子
 78      * @return
 79      */
 80     private static SecretKeySpec getSecretKey(final String password) {
 81         //返回生成指定演算法金鑰生成器的 KeyGenerator 物件
 82         KeyGenerator kg = null;
 83         try {
 84             kg = KeyGenerator.getInstance(KEY_ALGORITHM);
 85             //AES 要求金鑰長度為 128
 86             kg.init(128, new SecureRandom(password.getBytes()));
 87             //生成一個金鑰
 88             SecretKey secretKey = kg.generateKey();
 89 
 90             return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 轉換為AES專用金鑰
 91         } catch (NoSuchAlgorithmException ex) {
 92             Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
 93         }
 94         return null;
 95     }
 96     /**
 97      * 測試
 98      * @param args
 99      */
100     public static void main(String[] args) {
101         String s = "hello,xfwl";
102         System.out.println("明文(加密前):" + s);
103         //加密
104         String s1 = AESUtil.encrypt(s, "xfwl");
105         System.out.println("加密後:" + s1);
106         //解密
107         System.out.println("解密後:"+AESUtil.decrypt(s1, "xfwl"));
108     }
109 }

 (3)第三步:開始實現步驟一中定義的規則  

  1 package com.xfwl.message.serverMsg;
  2 
  3 import java.io.BufferedOutputStream;
  4 import java.io.BufferedReader;
  5 import java.io.IOException;
  6 import java.io.InputStream;
  7 import java.io.InputStreamReader;
  8 import java.io.OutputStream;
  9 import java.io.OutputStreamWriter;
 10 import java.net.MalformedURLException;
 11 import java.net.URL;
 12 import java.net.URLConnection;
 13 import java.util.HashMap;
 14 import java.util.Iterator;
 15 import java.util.Map;
 16 import java.util.Set;
 17 import java.util.Map.Entry;
 18 
 19 public class HTTPServerClient implements IHttpClient {    
 20     /**
 21      * 報文上送資料集合
 22      */
 23     private Map<String,Object> sendMap=null;
 24     /**
 25      * 構造器
 26      */
 27     public HTTPServerClient(Map<String,Object> sendMap){
 28         this.sendMap=sendMap;
 29     }
 30     /**
 31      * 獲取連線物件
 32      */
 33     public URLConnection getClient(String url) {
 34         URL u=null;
 35         try {
 36              u= new URL(url);
 37         } catch (MalformedURLException e) {
 38             e.printStackTrace();
 39         }
 40         System.out.println("建立["+url+"]連結....");
 41         //獲取連線物件
 42         URLConnection uc=null;
 43         try {
 44             uc = u.openConnection();
 45         } catch (IOException e) {
 46             e.printStackTrace();
 47         }
 48         return uc;
 49     }
 50     /**
 51      * 傳送報文
 52      */
 53     public boolean sendDataMsg(URLConnection uc,String encygen) {
 54         //開啟輸出流
 55         uc.setDoOutput(true);
 56         //獲取輸出流物件
 57         OutputStream raw=null;
 58         OutputStream buffered = null;
 59         OutputStreamWriter out=null;
 60         try {
 61             raw = uc.getOutputStream();
 62             buffered = new BufferedOutputStream(raw);
 63             out = new OutputStreamWriter(buffered, CHARTER_ENCODE);
 64             StringBuffer data=createMsgFormat(sendMap);
 65             System.out.println("傳送報文:"+data);
 66             out.write(encryptMsg(data.toString(),encygen).toString());
 67             out.flush();
 68             System.out.println("關閉連線");
 69             out.close();
 70         } catch (IOException e) {
 71             e.printStackTrace();
 72             return false;
 73         }
 74         return true;
 75     }
 76     /**
 77      * 接收報文
 78      */
 79     public StringBuffer receiveDataMsg(URLConnection uc,String deciogen) {
 80         //獲取到返回資料的輸入流
 81         InputStream is=null;
 82         BufferedReader br=null;
 83         StringBuffer blzRspXml = new StringBuffer();
 84         try {
 85             is = uc.getInputStream();
 86             br = new BufferedReader(new InputStreamReader(is,CHARTER_ENCODE));
 87             String line = "";
 88             System.out.println("獲取返回資料:");
 89             while((line = br.readLine()) != null){
 90                 //讀取返回資料,分行讀取
 91                 //System.out.println(deCioherMsg(line.trim(),deciogen));//解密
 92                 System.out.println(line.trim());
 93                 blzRspXml.append(line.trim());
 94             }
 95         } catch (IOException e) {
 96             e.printStackTrace();
 97         }
 98         return blzRspXml;
 99     }
100     /**
101      * 加密資料
102      */
103     public StringBuffer encryptMsg(String data,String encygen) {
104         return new StringBuffer(AESUtil.encrypt(data, encygen));
105     }
106     /**
107      * 解析資料
108      */
109     public StringBuffer deCioherMsg(String data,String deciogen) {
110         return new StringBuffer(AESUtil.decrypt(data, deciogen));
111     }
112     
113     /**
114      * 生成送報文:
115      *     上送報文和響應報文都需要約定一種報文格式
116      */
117     private  StringBuffer createMsgFormat(Map<String,Object> dataMap){
118         StringBuffer msg=new StringBuffer();
119         msg.append("<service>");
120         msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
121         msg.append("<SYS_HEAD>");
122         //存放:業務型別碼
123         msg.append("<HEAD_BSNCODE>100001</HEAD_BSNCODE>");
124         msg.append("</SYS_HEAD>");
125         msg.append("<BODY>");
126         //存放:業務資料
127         Set<Entry<String, Object>> set = dataMap.entrySet();
128         Iterator<Entry<String, Object>> it = set.iterator();
129         while (it.hasNext()) {
130             Entry<String, Object> ey = it.next();
131             String key = ey.getKey();
132             String value = (String) ey.getValue();
133             msg.append("<"+key+">"+value+"</"+key+">");
134         }
135         msg.append("</BODY>");
136         msg.append("</service>");
137         return msg;
138     }
139     /**
140      * 解析響應報文:
141      * @param args
142      */
143     private StringBuffer parseRecMsgFormat(String data){
144         //...待續...
145         
146         
147         
148         return null;
149     }
150     public static void main(String[] args) {
151         Map<String,Object> sendMap =new HashMap<String, Object>();
152         sendMap.put("ADMIN", "小風微靈");
153         sendMap.put("PWD", "xfwl123");
154         //System.out.println(createMsgFormat(sendMap));
155     }
156 }

  (4)第四步:開始測試一下

 1 package com.xfwl.message.test;
 2 
 3 import java.net.URLConnection;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 
 7 import com.xfwl.message.serverMsg.HTTPServerClient;
 8 
 9 public class TestAction3 {
10     public static void main(String[] args) {
11         Map<String,Object> sendMap =new HashMap<String, Object>();
12         sendMap.put("ADMIN", "小風微靈");
13         sendMap.put("PWD", "xfwl123");
14         
15         HTTPServerClient client=new HTTPServerClient(sendMap);
16         URLConnection uc=client.getClient("http://47.105.58.153:3000");
17         client.sendDataMsg(uc,"lvjun");
18         client.receiveDataMsg(uc,"lvjun");
19     }
20 }

  看一下測試結果:

 1 建立[http://47.105.58.153:3000]連結....
 2 傳送報文[明文]:<service><?xml version="1.0" encoding="UTF-8"?><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><ADMIN>小風微靈</ADMIN><PWD>xfwl123</PWD></BODY></service>
 3 傳送報文[密文]:UCr7pP6rDXPVlZzhcTRD20JHzoQSI7/Tb82YL6m6O25tD37RE6lW062yoRvdAv4eWxKWT2shrt97
 4 t2ZN+kjNVqkhLRaEw96yr1arAWtxri0pX0W3LYXw0Gw4LoTWsPb09a0JRv5p35Dt0QICN/Ve0+mP
 5 ayN+jCSFE3DKk5xusgSzua3adfnEdELhxbR33+CL09yI+Rc8In2NjYrsg24kkM29dJaWSRGm+ahn
 6 26OUQnI=
 7 
 8 關閉連線
 9 獲取返回資料:
10 {"status":"1","msg":"未登入!","result":""}

  三、接下來準備要做的事情

  從上面的測試結果來看,已經成功完成了第一步,即將本地的請求(用自定義的報文格式處理請求資料)傳送到雲伺服器上部署的web工程服務上,接下來要做的就是在web工程上動手,監聽這類請求,根據約定的加密因子和

報文規則,解密和解析析xml報文,獲取其中的請求資料,經行業務邏輯處理後按照約定的加密方式和報文規則,生成對應的響應報文,返回給本地的Java-Project,本地Java-Project再解密解析響應報文,獲取響應資料,從而經行本

地的業務邏輯處理。

     一步步來吧,只要腳步不停下,就是在進步......