在進行系統整合時,系統間不管是透過網路、檔案傳送訊息資料,常會遇到訊息字串的各個欄位是固定長度的,這種情況下程式怎麼寫會比較簡潔易懂? 這裡是我提供的一個方法,使用 annotation 將訊息字串欄位的設定值直接寫在程式上,而不是寫在設定檔裡,這樣應該會比較直覺。
假設有個程式,要顯示中華民國總統的任期和歷史評價,其訊息格式如下:
首先,我們定義一個 annotation,可以設定欄位的開始位置和長度,如下:
1 package idv.steven; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7 8 @Retention(RetentionPolicy.RUNTIME) 9 @Target(ElementType.FIELD) 10 public @interface MsgField { 11 public int start(); 12 public int length(); 13 }
接著定義一個 POJO,並且於類別裡的各個欄位上設定開始位置、長度,因為訊息有四個欄位,當然這個類別也有相對應的四個欄位。
1 package idv.steven.pojo; 2 3 import idv.steven.MsgField; 4 5 public class Message { 6 @MsgField(start=0,length=4) 7 private String startYear; 8 @MsgField(start=4,length=4) 9 private String endYear; 10 @MsgField(start=8,length=10) 11 private String name; 12 @MsgField(start=18,length=30) 13 private String evaluate; 14 15 /** 16 * @return 任期開始的年份 17 */ 18 public String getStartYear() { 19 return startYear; 20 } 21 public void setStartYear(String startYear) { 22 this.startYear = startYear; 23 } 24 25 /** 26 * @return 任期結束的年份 27 */ 28 public String getEndYear() { 29 return endYear; 30 } 31 public void setEndYear(String endYear) { 32 this.endYear = endYear; 33 } 34 35 /** 36 * @return 姓名 37 */ 38 public String getName() { 39 return name; 40 } 41 public void setName(String name) { 42 this.name = name; 43 } 44 45 /** 46 * @return 評價 47 */ 48 public String getEvaluate() { 49 return evaluate; 50 } 51 public void setEvaluate(String evaluate) { 52 this.evaluate = evaluate; 53 } 54 }
下面就是剖析訊息的程式了…
1 package idv.steven; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Method; 6 import java.util.Arrays; 7 8 import idv.steven.pojo.Message; 9 10 /** 11 * 剖析固定欄位長度的訊息 12 * @author Steven 13 */ 14 public class Parser { 15 private Message parsing(byte[] msg) 16 throws IllegalArgumentException, IllegalAccessException, 17 NoSuchMethodException, SecurityException, 18 InvocationTargetException, ClassNotFoundException { 19 20 Message message = new Message(); 21 22 Class<?> aClass = Class.forName(Message.class.getName()); 23 Field[] fields = aClass.getDeclaredFields(); 24 for(Field field:fields) { 25 MsgField msgField = field.getAnnotation(MsgField.class); 26 if (msgField != null) { 27 byte[] subMsg = Arrays.copyOfRange(msg, msgField.start(), msgField.start() + msgField.length()); 28 29 Method method = aClass.getMethod(getSetterName(field.getName()), String.class); 30 method.invoke(message, new String(subMsg)); 31 //field.set(message, new String(subMsg)); 32 } 33 } 34 35 return message; 36 } 37 38 private String getSetterName(String fieldName) { 39 return String.format("set%s%s", fieldName.substring(0, 1).toUpperCase(), fieldName.substring(1)); 40 } 41 42 public void run(byte[] msg) { 43 try { 44 Message message = parsing(msg); 45 46 System.out.println("任期: " + message.getStartYear() + " ~ " + message.getEndYear()); 47 System.out.println("總統姓名: " + message.getName()); 48 System.out.println("歷史評價: " + message.getEvaluate()); 49 } catch (Exception e) { 50 e.printStackTrace(); 51 } 52 } 53 54 public static void main(String[] args) { 55 56 new Parser().run("20082016馬英九 一個自私的笨蛋、禍國殃民! ".getBytes()); 57 } 58 }
執行結果如下:
任期: 2008 ~ 2016 總統姓名: 馬英九 歷史評價: 一個自私的笨蛋、禍國殃民!
剖析固定長度欄位的訊息字串
时间: 2024-10-11 10:04:16