无聊系列 - 教你怎么正确处理异常
Posted chongsha
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无聊系列 - 教你怎么正确处理异常相关的知识,希望对你有一定的参考价值。
在工作中,常遇见乱处理Exception的情况:
- 要么吞掉异常,不打印任何日志;
- 要么记录日志时,日志级别不对、或者把重要的出错堆栈信息干掉,在做生产问题排查时,简直让人抓狂。
我这篇博文,也是对记录的一个开源组件,对异常自行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 }
该段代码主要的问题是:
- 吃掉了异常,因为是公共类,连日志记录都没有
- 出现异常后,仍然返回了一个null值。
这个方法在我们平时使用时,如果不读源码,直接使用,第一直觉是,返回正确结果,如果不正确,那就会抛出异常。但是这段代码却返回了null,使用者遇到时,会抓狂,这是什么情况啊,为啥不对,明明没有报错,万般无奈,进代码一看。。。原来是把异常给干掉了。
对此代码做出的改进建议是:
- 在方法上声明throws是
- 如果你觉得1方案不爽,可以直接一个大的catch Exception,然后throw new RuntimeException(e.getMessage(), e);
- 出错了就是出错了,不能把错误自己干掉,然后返回一个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)标明了出错位置,可以快速定位是在什么地方。所以在记录日志的时候,请不要把错误堆栈信息干掉了。
以上是关于无聊系列 - 教你怎么正确处理异常的主要内容,如果未能解决你的问题,请参考以下文章
PCL异常处理:pcl 1.8.13rdpartyoostincludeoost-1_64oost ypeofmsvc ypeof_impl.hpp(125): error(代码片段