一、异常处理的原则

1、调用方法的时候返回布尔值来代替返回null,这样可以 NullPointerException。由于空指针是java异常里最恶心的异常。

2、 catch块里别不写代码。空catch块是异常处理里的错误事件,因为它只是捕获了异常,却没有任何处理或者提示。通常你起码要打印出异常信息,当然你最好根据需求对异常信息进行处理。

3、能抛受控异常(checked Exception)就尽量不抛受非控异常(unchecked Exception[Error或者RuntimeException的异常])。通过去掉重复的异常处理代码,可以提高代码的可读性。

4、 绝对不要让你的数据库相关异常显示到客户端。由于绝大多数数据库和SQLException异常都是受控异常,在Java中,你应该在DAO层把异常信息处理,然后返回处理过的能让用户看懂并根据异常提示信息改正操作的异常信息。

5、 在Java中,一定要在数据库连接,数据库查询,流处理后,在finally块中调用close()方法。

二、示例说明

本示例以“前后端分离模式”进行演示,调试用的异常信息通过日志的形式打印出来,代码并不完整,仅从异常处理进行部分代码示例。

1、创建异常类

 @Getter //通过lombok插件实现省写setter或者getter方法
public class SellException extends RuntimeException { private Integer code;
private String message; public SellException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
} public SellException(Integer code,String message) {
this.code = code;
this.message = message;
}
}

2、使用Handler类捕获异常,统一格式返回给前端

 @ControllerAdvice
public class SellExceptionHandler { @ExceptionHandler(value = SellException.class)
@ResponseBody
public ResultVO handlerSellerException(SellException e){
return ResultVOUtil.error(e.getCode(),e.getMessage());
} }

  统一格式类:

 public class ResultVOUtil {

     public static ResultVO success(Object object) {
ResultVO resultVO = new ResultVO();
resultVO.setData(object);
resultVO.setCode(0);
resultVO.setMsg("成功");
return resultVO;
} public static ResultVO success() {
return success(null);
} public static ResultVO error(Integer code,String msg) {
ResultVO resultVO = new ResultVO();
resultVO.setCode(code);
resultVO.setMsg(msg);
return resultVO;
} }
 @Data
public class ResultVO<T> implements Serializable{ private static final long serialVersionUID = 8960474786737581150L; /**
* 错误码
*/
private Integer code;
/**
*提示信息
*/
private String msg;
/**
* 具体内容
*/
private T data; }

3、异常的信息通过枚举统一定义,方便定义管理

 @Getter
public enum ResultEnum { SUCCESS(0,"成功"), PARAM_ERROR(1,"参数不正确"), PRODUCT_NOT_EXIST(10,"商品不存在"), PRODUCT_STOCK_ERROR(11,"商品库存不正确"), ORDER_NOT_EXIST(12,"订单不存在"), ORDERDETAIL_NOT_EXIST(13,"订单详情不存在"), ORDER_STATUS_ERROR(14,"订单状态不正确"), ORDER_UPDATE_FAIL(15,"订单更新失败"), ORDER_DETAIL_EMPTY(16,"订单详情为空"), CART_EMPTY(18,"购物车为空"), ORDER_OWNER_ERROR(19,"该订单不属于当前用户"),
; private Integer code;
private String message; ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
} }

4、使用异常类

① controller层处理页面传来参数的校验,如参数不正确,抛出自定义异常,由handler捕获返回给页面。

 @RestController
@RequestMapping("/buyer/order")
@Slf4j
public class BuyerOrderController { @Autowired
private OrderService orderService; @Autowired
private BuyerService buyerService; //创建订单
@PostMapping("/create")
public ResultVO<Map<String,String>> create(@Valid OrderForm orderForm,
BindingResult bindingResult){
if (bindingResult.hasErrors()){
log.error("[创建订单] 参数不正确,orderForm={}",orderForm);
throw new SellException(ResultEnum.PARAM_ERROR.getCode(),
bindingResult.getFieldError().getDefaultMessage());
}
OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm);
if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){
log.error("[创建订单] 购物不能为空");
throw new SellException(ResultEnum.CART_EMPTY);
} OrderDTO createResult = orderService.create(orderDTO);
Map<String,String> map = new HashMap<>();
map.put("orderId",createResult.getOrderId()); return ResultVOUtil.success(map); }
//订单列表
@GetMapping("/list")
public ResultVO<List<OrderDTO>> list(@RequestParam("openid") String openid,
@RequestParam(value = "page",defaultValue = "0") Integer page,
@RequestParam(value = "size",defaultValue = "10") Integer size){
if (StringUtils.isEmpty(openid)){
log.error("[查询订单列表] openid为空");
throw new SellException(ResultEnum.PARAM_ERROR);
}
PageRequest request = new PageRequest(page, size);
Page<OrderDTO> orderDTOPage = orderService.findList(openid, request); return ResultVOUtil.success(orderDTOPage.getContent());
} //订单详情
@GetMapping("/detail")
public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
@RequestParam("orderId") String orderId){ OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
return ResultVOUtil.success(orderDTO);
} //取消订单
@PostMapping("/cancel")
public ResultVO<OrderDTO> cancel(@RequestParam("openid") String openid,
@RequestParam("orderId") String orderId) { buyerService.cancelOrderOne(openid, orderId);
return ResultVOUtil.success();
}
}

② service处理返回的结果的异常,抛出自定义异常,由handler捕获返回给页面。

 @Service
@Slf4j
public class BuyerServiceImpl implements BuyerService { @Autowired
private OrderService orderService; @Override
public OrderDTO findOrderOne(String openid, String orderId) {
return checkOrderOwner(openid, orderId);
} @Override
public OrderDTO cancelOrderOne(String openid, String orderId) {
OrderDTO orderDTO = checkOrderOwner(openid, orderId);
if (orderDTO == null){
log.error("[取消订单] 查不到该订单,orderDTO={}",orderId);
throw new SellException(ResultEnum.ORDER_NOT_EXIST);
}
return orderService.cancel(orderDTO);
} private OrderDTO checkOrderOwner(String openid, String orderId) {
OrderDTO orderDTO = orderService.findOne(orderId);
if (orderDTO == null){
return null;
}
if (!orderDTO.getBuyerOpenid().equalsIgnoreCase(openid)){
log.error("[查询订单] 订单的openid不一致,openid={},orderDTO={}",openid,orderDTO);
throw new SellException(ResultEnum.ORDER_OWNER_ERROR);
}
return orderDTO;
} }

Spring Boot统一异常处理方案示例的更多相关文章

  1. Spring Boot统一异常处理实践

    摘要: SpringBoot异常处理. 原文:Spring MVC/Boot 统一异常处理最佳实践 作者:赵俊 前言 在 Web 开发中, 我们经常会需要处理各种异常, 这是一件棘手的事情, 对于很多 ...

  2. spring boot 统一异常处理

    需求源自于任何一个业务的编写总会有各种各样的条件判断,需要时时手动抛出异常,又希望让接口返回友好的错误信息. spring boot提供的帮助是自动将异常重定向到路由为/error的控制器 但是我们又 ...

  3. Spring Boot☞ 统一异常处理

    效果区:  代码区: package com.wls.integrateplugs.exception.dto; public class ErrorInfo<T> { public st ...

  4. js构建ui的统一异常处理方案(四)

    上一篇我们介绍了统一异常处理方案的设计方案,这一篇我们将直接做一个小例子,验证我们的设计方案. 例子是一个todo的列表界面(页面代码参考于https://github.com/zongxiao/Dj ...

  5. js构建ui的统一异常处理方案(三)

    笔者之前分析了如何实现js的责任链异常处理的方法,通过promise这个异步模型,我们能够对同步方法和异步方法的两种情况,均可以实现责任链模式.有了这些武器,我们就可以开始设计ui的统一异常处理方案了 ...

  6. Spring MVC 统一异常处理

    Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或 ...

  7. 编程小白入门分享三:Spring AOP统一异常处理

    Spring AOP统一异常处理 简介 在Controller层,Service层,可能会有很多的try catch代码块.这将会严重影响代码的可读性."美观性".怎样才可以把更多 ...

  8. Spring Boot全局异常处理

    本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下 1.后台处理异常 a.引入thymeleaf依赖 <!-- thymeleaf模板插件 --> <dep ...

  9. Spring Boot Ftp Client 客户端示例支持断点续传

    本章介绍 Spring Boot 整合 Ftpclient 的示例,支持断点续传 本项目源码下载 1 新建 Spring Boot Maven 示例工程项目 注意:是用来 IDEA 开发工具 File ...

随机推荐

  1. 内置装饰器二:@property

    property 装饰器的作用 property 装饰器将方法包装成属性,将私有属性公有化,此属性只能被读取.相当于实现get方法的对象 class People: def __init__(self ...

  2. FunDA(5)- Reactive Streams:Play with Iteratees

    FunDA的设计目标就是把后台数据库中的数据搬到内存里,然后进行包括并行运算的数据处理,最后可能再对后台数据库进行更新.如果需要把数据搬到内存的话,那我们就必须考虑内存是否能一次性容纳所有的数据,有必 ...

  3. Android应用安全防护和逆向分析 ——apk反编译

    概述 最近一直在学习Android应用安全相关和逆向分析的知识.现在移动app在安全方面是越来越重视了,特别是那些巨头企业涉及到钱的应用,那加密程度,简直是丧心病狂,密密麻麻.从这里可以看出,对于应用 ...

  4. 大数据技术之_19_Spark学习_01_Spark 基础解析小结(无图片)

    1.准备安装包 2.Spark Standalone 即独立模式  2.1.解压安装包到你安装的目录.  2.2.拷贝 conf 目录下的 slaves 文件,将 slave 节点的 hostname ...

  5. django框架--中间件系统

    目录 零.参考 一.中间件的基本理解 二.中间件的系统定位 三.中间件的配置 四.中间件的执行流程 五.中间件与装饰器之间的思考 六.中间件的应用场景 七.内置中间件 八.总结 零.参考 https: ...

  6. Cygwin安装配置

    1.下载安装Cygwin   我们可以到Cygwin的官方网站下载Cygwin的安装程序,地址是: http://www.cygwin.com/ 或者直接使用下载连接来下载安装程序,下载连接是: ht ...

  7. SocketIo+SpringMvc实现文件的上传下载

    SocketIo+SpringMvc实现文件的上传下载 socketIo不仅可以用来做聊天工具,也可以实现局域网(当然你如果有外网也可用外网)内实现文件的上传和下载,下面是代码的效果演示: GIT地址 ...

  8. [转]Elasticsearch Java API总汇

    http://blog.csdn.net/changong28/article/details/38445805#comments 3.1 集群的连接 3.1.1 作为Elasticsearch节点 ...

  9. CentOS6.5下Ambari安装搭建部署大数据集群(图文分五大步详解)(博主强烈推荐)

    第一步: Ambari安装之Ambari安装前准备(CentOS6.5)(一) 第二步: Ambari安装之部署本地库(镜像服务器)(二) 第三步: Ambari安装之安装并配置Ambari-serv ...

  10. Nodejs学习笔记(十五)—Node.js + Koa2 构建网站简单示例

    前言 前面一有写到一篇Node.js+Express构建网站简单示例:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp.html 这篇还 ...