实际springMVC项目中自定义异常、spring事务与异常的简单应用
来源:互联网 发布:为知笔记积分 编辑:程序博客网 时间:2024/04/29 10:08
一、异常相关知识:
非运行时异常(Checked Exception)
Java中凡是继承自Exception但不是继承自RuntimeException的类都是非运行时异常。运行时异常(Runtime Exception/Unchecked Exception)
RuntimeException类直接继承自Exception类,称为运行时异常。Java中所有的运行时异常都直接或间接的继承自RuntimeException。
3、Java中所有的异常类都直接或间接的继承自Exception。
4、spring事务回滚机制只处理运行时异常,发生非运行时异常则不会回滚操作。
二、自定义异常的大体思路
1、通过上面异常相关知识介绍,在实际的springmvc项目中自定义异常采用继承RuntimeException类的方式;
2、为了防止注解了spring事务的service方法中发生非运行其异常,导致的事务不回滚操作,service层触发事务相关代码主动用try{}catch(){}包裹,最后的catch捕获Exception异常(即包含了运行期和非运行期异常),
catch内部抛出自定义的运行期异常,以达到把非运行其异常转换为运行期异常的效果,保证所有异常spring事务都执行回滚操作。
三、自定义异常实例
自定义基类异常:
/** * 所有秒杀相关异常(运行期异常) * spring事务,只接收运行期异常,执行回滚操作 */public class SeckillException extends RuntimeException{ private static final long serialVersionUID = 1L; //重载构造函数 public SeckillException(String message, Throwable cause) { super(message, cause); } //重载构造函数 public SeckillException(String message) { super(message); }}
自定义两个子类异常:
/** * 秒杀关闭异常:可能未开启,可能已结束(时间到期,库存为0),可能执行失败等 * 秒杀异常的子类型异常 */public class SeckillClosedException extends SeckillException{ private static final long serialVersionUID = 1L; //重载构造函数 public SeckillClosedException(String message, Throwable cause) { super(message, cause); } //重载构造函数 public SeckillClosedException(String message) { super(message); }}
/** * 重复秒杀异常,秒杀异常的子类型异常 */public class RepeatSeckillException extends SeckillException{ private static final long serialVersionUID = 1L; //重载构造函数 public RepeatSeckillException(String message){ super(message); } //重载构造函数 public RepeatSeckillException(String message,Throwable cause){ super(message, cause); }}
service层事务方法:
@Transactional@Overridepublic SeckillExecution executeSeckill(。。。) throws SeckillException, SeckillClosedException,RepeatSeckillException { //将所有操作用try{}catch(){}包裹,然后在catch中抛出运行期异常,以便发生异常时spring事务回滚操作 try{ //insert语句并没有触发事务操作,但是inset要保证与update事务的一致性 int insertCount = successkilledDao.insertSuccessKilled(seckillId, userPhone); //重复秒杀 if(insertCount <= 0){ throw new RepeatSeckillException(SeckillStateEnum.REPEAT_KILL.getStateInfo()); }else{ //减库存 Date nowTime = new Date(); //开启事务,获取updateCount值,提交并关闭事务;如果抛出异常则回滚事务 int updateCount = seckillDao.reduceNumber(seckillId, nowTime); //没有更新数据,秒杀结束 if(updateCount <= 0){ throw new SeckillClosedException(SeckillStateEnum.END.getStateInfo()); }else{ //秒杀成功,获取当前购买明细实体 SuccessKilled successKilled = successkilledDao.querySuccessKilledWithSeckill(seckillId, userPhone); return new SeckillExecution(seckillId,SeckillStateEnum.SUCCESS,successKilled); } } //将try中抛出的已知异常用已知异常捕获,然后再次抛出 //为的是避免被最后的用于处理未知异常的Exception e捕获,让调用者获取最为准确的信息 }catch(SeckillClosedException se){ logger.error(se.getMessage()); throw se; }catch(RepeatSeckillException re){ logger.error(re.getMessage()); throw re; //最后捕获所有未知异常(相对于上面两个已知异常),然后再主动抛出自定义运行期异常 }catch(Exception e){ logger.error(e.getMessage(),e); //将检查(编译期)异常转换为运行期异常,spring事务回滚只负责运行期异常 throw new SeckillException(SeckillStateEnum.INSERT_ERROR.getStateInfo()+" : "+e.getMessage()); }}
上述方式的弊端是,如果业务线比较多,自定义的异常子类也会比较多,完全可以定义为一个通用的UncheckedException异常,如下:
/** * @Description:通用的UncheckedException异常,继承RuntimeException,为运行期异常 */public class UncheckedException extends RuntimeException { private static final long serialVersionUID = 1L; /** 错误Key,用于唯一标识错误类型 */ private String errorCode = null; /** 错误信息 */ private String errorMessage; /** 传递给变量的错误值 */ private Object[] errorParam = null; /** * 构造函数 * @param errorCode 异常编码 */ public UncheckedException(String errorCode) { this.errorCode = errorCode; } /** * 构造函数 * @param errorCode 异常编码 * @param errorParam Object[] 异常信息用到的参数 */ public UncheckedException(String errorCode, Object[] errorParam) { this.errorCode = errorCode; this.errorParam = errorParam; } /** * 重载构造函数 * @param errorCode 异常编码 * @param errorParam 异常信息用到的参数 * @param t 异常实例 */ public UncheckedException(String errorCode, Object[] errorParam, Throwable t) { super(t); this.errorCode = errorCode; this.errorParam = errorParam; } /** * 重载构造函数 * @param message 异常信息 * @param t 异常实例 */ public UncheckedException(String message, Throwable t) { super(message, t); setErrorMessage(message); } /** * 异常编码 * @return String */ public String getErrorCode() { return this.errorCode; } /** * 异常信息用到的参数 * @return Object[] */ public Object[] getErrorParam() { return this.errorParam; } /** * 错误信息 * * @return */ public String getErrorMessage() { return errorMessage; } /** * 错误信息 * * @param errorMessage */ public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } /** * 覆盖方法:getMessage * @return String */ @Override public String getMessage() { if (errorMessage != null) { return errorMessage; } //异常信息以资源文件的形式保存,并且支持国际化,此处通过errorCode去读取国际化异常信息 if (errorCode != null && !errorCode.trim().equals("")) { setErrorMessage(AppLang.getLU().getMessage(errorCode, errorParam,Locale.SIMPLIFIED_CHINESE)); } return getErrorMessage(); }}
1 0
- 实际springMVC项目中自定义异常、spring事务与异常的简单应用
- spring中异常的使用--事务
- 关于java异常在实际应用中经验与总结
- 实际应用中JSP页面的异常处理
- 抛出自定义异常,spring AOP事务不回滚的解决方案
- 抛出自定义异常,spring AOP事务不回滚的解决方案
- 自定义异常类(SpringMVC的异常处理)
- 项目应用:自定义异常处理
- 在springMVC+mybatis+Ajax+JSON+jQuery easyui的项目中,自定义全局异常处理器
- springmvc的自定义异常处理
- 项目中自定义异常的使用
- 实验spring事务回滚与异常的关系
- spring的注解事务与try catch 异常处理
- 项目异常统一处理-spring+springmvc
- Spring中发生异常的事务回滚问题
- spring中@Transactional对于事务异常的处理
- spring事务控制的方法中抛出异常不回滚
- 在springMVC中使用自定义的异常处理
- 数据结构第一次作业(学生信息管理系统-顺序表&&链表)
- 加入多线程:
- 中兴对华为NB-IoT的大反击 - CLAA
- eclipse 在debugger的时候有时候会卡住不动,既不报错也不向下走代码
- Android事件传递
- 实际springMVC项目中自定义异常、spring事务与异常的简单应用
- 【总结】fatal error CVT1100: duplicate resource. type:manifest 错误提示
- 极客学院Hadoop学习【MapReduce的体系结构】
- linux中yum配置
- pdf转换成word格式的方法,需要的速度来
- Linux下shell编程学习
- SystemServer启动流程之Zygote启动(一)
- 基于UDP协议的网络编程:
- DEBUG in background task