最近公司组织了次培训,感觉受益匪浅啊!
第一天讲的是异常:
下面写一个平时最长用的写法 :
public List<Student> getAllStudent(){ List<Student> result = new ArrayList<Student>(); try{ //TODO }catch(Exception ex){ logger.error(ex); } return result; }
或者public List<Student> getAllStudent(){ List<Student> result = null; try{ //TODO }catch(Exception ex){ logger.error(ex); } return result; }
第一,第二种方法都是错误的,因为如果出错误了,出异常了,前台就会很容易出现灵异事件! 比如说查询总人数是0 但是呢 根据id能查询出人来!如果报错了,调用该接口的人 就会把它当做 没有学生一样处理! 但是其实是不一样的!
如果不是查询学生呢 而是查询收益呢~~
public double getProfit(){ double result; try{ //TODO }catch(Exception ex){ logger.error(ex); } return result; }
我们就不能设置一个不存在的值 来表示错误了!
其实我们不应该害怕异常,有异常就应该抛出去,异常就是不能解决的问题! 不能解决 那我们 try-catch 之后就能把它当做什么都没发生吗? 这种做法显然是错误的!
所以这个方法 我们应该大胆的抛出异常!
那异常到底怎么抛呢?抛什么异常呢?
http协议 里面 返回码 2xx表示成功 4xx,5xx表示错误了! 为什么没有6xx呢~ 4xx,5xx到底有什么区别呢~ 因为http介于 浏览器 跟 服务器之间~ 浏览器是人去操作的 也就是说 http是介于 人与服务器二者的中间,那么显然错误要么是浏览器这边犯的 要么就是服务器那边犯的错误! 400 是没有所需要的页面,403是没有权限,这些都是用户的非法操作导致的错误,500是系统异常,503是系统忙,这些不是说是用户操作不对,都是用户在合理的操作下 服务器犯的错误!
在java世界里面,我们也有2类异常, 一类是普通异常,一类是运行时异常,显然 5系列是 运行时异常 因为这个异常你无法处理,你也处理不了!而4系列的异常就是我们需要处理的 !
那现在我们看下面的例子:
public void sellItem(String itemId,int amount){ try{ // TODO }catch(Exception ex){ logger.error(ex); } }
这个我们需要抛哪些异常呢?itemId为空?amount无效? 或者说参数异常?
其实如果你用我的接口,那么就应该懂我的接口,不然你就别用! 所以参数错误,我们是不鸟他的 ! 直接给他 5系列的错误, 那这么说是不是这个方法就不需要抛4系列的异常呢?
那如果商品客户买的时候还在,但是呢不知道怎么被人删了,这个也算是程序错误吗? 进入errorPage?
如果商品买的时候有3个 ,下单2个,但是执行的时候已经被别人抢了2个 只剩下1个了, 商品数量不足,这个也算是 5系列的错误,也要进errorPage?
显然这样是不行的, 所以对于这些高级错误,我们应该把它们都列举出来,然后作为显式异常抛出, 显式异常 其实是可枚举的!
所以应该如下
public void sellItem(String itemId,int amount) throws 商品不存在异常,商品数量不足异常{ try{ // TODO if(..){ throws 商品不存在异常; } if(..){ throws 商品数量不足异常; } }catch(Exception ex){ logger.error(ex); throws new RuntimeException(ex.getMessage()); } }
4系列的错误,客户是可以处理的! 比如说商品不存在了, 那么客户可以买一个相似的商品代替,比如数量不足,那客户可以少买点,或者买其他的! 但是5系列的错误 客户怎么处理, 数据库没启动,你告诉客户,客户能咋办!
反正就一句话,碰到异常 一定不能 try-catch log 一下 就搞定了 log只是给程序员看的! 而且也是补救措施! 这么处理,会参数很多,现象跟原因差了十万八千里的错误,这个是最坑爹的! 所以异常不要怕,该抛就抛!
对了 还有一种做法 那就是返回 Map 用code表示状态,但是其实这个做法很不好, 第一让接口很不易于一目了然,别人拿到你的接口 不能知道你的接口到底干嘛,而且你用code 用的人用CODE 这个又被坑了! 最后一点就是异常 其实是少数的 ,这样做的话,正常情况也要判断,其实这是很不合理的!
我们的web项目 一般是这样的 :
js -- action -- serverice1 -- [service2]--dao;
我们假设有2层service
如果第二层service抛出一个显示异常 怎么办? 是try-catch 然后log一下 然后就直接抛出去吗?
这个做法是错误的,action 只懂service1的业务,根本不懂service2的业务,你抛一个service2的错误,它怎么可能知道什么意思,所以我们一定要把这个错误装换成一个action能理解的,service1跟action约定的异常! (这里画图更好理解,但是画图太蛋疼)
这就是培训的主要内容了! 呵呵,一个星期前的东西,一直懒的写! 写的没有培训讲的好,很多精彩的东西没法描述! 反正呢,只能意会了,呵呵!