無聊系列 - 教你怎么正確處理異常


在工作中,常遇見亂處理Exception的情況:

  1. 要么吞掉異常,不打印任何日志;
  2. 要么記錄日志時,日志級別不對、或者把重要的出錯堆棧信息干掉,在做生產問題排查時,簡直讓人抓狂。

我這篇博文,也是對記錄的一個開源組件,對異常自行K掉,造成我排查耗費了好久的時間--。https://www.cnblogs.com/chongsha/p/11931109.html

下面我們用一段代碼對1進行舉例,該代碼是網上隨便搜的,原作者請勿見怪。

 1  /*
 2    * 加密
 3    * 1.構造密鑰生成器
 4    * 2.根據ecnodeRules規則初始化密鑰生成器
 5    * 3.產生密鑰
 6    * 4.創建和初始化密碼器
 7    * 5.內容加密
 8    * 6.返回字符串
 9    */
10     public static String AESEncode(String encodeRules,String content){
11         try {
12             //1.構造密鑰生成器,指定為AES算法,不區分大小寫
13             KeyGenerator keygen=KeyGenerator.getInstance("AES");
14             //2.根據ecnodeRules規則初始化密鑰生成器
15             //生成一個128位的隨機源,根據傳入的字節數組
16             keygen.init(128, new SecureRandom(encodeRules.getBytes()));
17               //3.產生原始對稱密鑰
18             SecretKey original_key=keygen.generateKey();
19               //4.獲得原始對稱密鑰的字節數組
20             byte [] raw=original_key.getEncoded();
21             //5.根據字節數組生成AES密鑰
22             SecretKey key=new SecretKeySpec(raw, "AES");
23               //6.根據指定算法AES自成密碼器
24             Cipher cipher=Cipher.getInstance("AES");
25               //7.初始化密碼器,第一個參數為加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二個參數為使用的KEY
26             cipher.init(Cipher.ENCRYPT_MODE, key);
27             //8.獲取加密內容的字節數組(這里要設置為utf-8)不然內容中如果有中文和英文混合中文就會解密為亂碼
28             byte [] byte_encode=content.getBytes("utf-8");
29             //9.根據密碼器的初始化方式--加密:將數據加密
30             byte [] byte_AES=cipher.doFinal(byte_encode);
31           //10.將加密后的數據轉換為字符串
32             //這里用Base64Encoder中會找不到包
33             //解決辦法:
34             //在項目的Build path中先移除JRE System Library,再添加庫JRE System Library,重新編譯后就一切正常了。
35             String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
36           //11.將字符串返回
37             return AES_encode;
38         } catch (NoSuchAlgorithmException e) {
39             e.printStackTrace();
40         } catch (NoSuchPaddingException e) {
41             e.printStackTrace();
42         } catch (InvalidKeyException e) {
43             e.printStackTrace();
44         } catch (IllegalBlockSizeException e) {
45             e.printStackTrace();
46         } catch (BadPaddingException e) {
47             e.printStackTrace();
48         } catch (UnsupportedEncodingException e) {
49             e.printStackTrace();
50         }
51         
52         //如果有錯就返加nulll
53         return null;         
54     }

該段代碼主要的問題是:

  1. 吃掉了異常,因為是公共類,連日志記錄都沒有
  2. 出現異常后,仍然返回了一個null值。

這個方法在我們平時使用時,如果不讀源碼,直接使用,第一直覺是,返回正確結果,如果不正確,那就會拋出異常。但是這段代碼卻返回了null,使用者遇到時,會抓狂,這是什么情況啊,為啥不對,明明沒有報錯,萬般無奈,進代碼一看。。。原來是把異常給干掉了。

對此代碼做出的改進建議是:

  1. 在方法上聲明throws是
  2. 如果你覺得1方案不爽,可以直接一個大的catch Exception,然后throw new RuntimeException(e.getMessage(), e);
  3. 出錯了就是出錯了,不能把錯誤自己干掉,然后返回一個null。

要么記錄日志時,日志級別不對、或者把重要的出錯堆棧信息干掉,在做生產問題排查時,簡直讓人抓狂。

在用log4j記錄日志時,請正確使用logger.error()來記錄日志,請注意該方法的重載,不要使用 Exception的getMessage()方法只記錄異常的消息,而把異常的錯誤堆棧給拋棄,異常的錯誤堆棧是很有用的信息,會告訴你在哪行代碼出錯了,這樣你可以快速的定位錯誤。

 1 package com.demo;
 2 
 3 public class Test {
 4 
 5     public static void main(String[] args) {
 6         try {
 7             int a = 0;
 8             int b = 1;
 9 
10             System.out.println(b / a);
11         } catch (Exception e) {
12             e.printStackTrace();
13         }
14     }
15 
16 }

 

這段代碼的錯誤堆棧信息:

java.lang.ArithmeticException: / by zero
at com.demo.Test.main(Test.java:10)

這行錯誤信息at com.demo.Test.main(Test.java:10)標明了出錯位置,可以快速定位是在什么地方。所以在記錄日志的時候,請不要把錯誤堆棧信息干掉了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM