一、异常处理的原则

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. php程序开销比较

    内存最快 文件次之 数据库最慢

  2. 聊聊并发(三)Java线程池的分析和使用

    1.    引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行. ...

  3. RSA的JAVA实现 及javax.crypto.IllegalBlockSizeException

    一.背景 最近工作中涉及到RSA加密的相关需求任务,之前对加密算法了解不多,开发过程中遇到了一些坑记录一下. 二.RSA原理 RSA加密是非对称加密,公开私钥,保留私钥.通信时数据通过公开的公钥加密, ...

  4. 下载一个vue项目执行npm install 后运行项目npm run dev后出错 - 问题解决

    在SVN上拉下来一个vue项目,上面没有提交项目里面的node_modules文件夹,所以要自己执行 npm install 安装,但安装完后运行项目后却报错了: $ npm run dev > ...

  5. php 常见图片处理函数封装

    <?php /** * 常见图像处理函数的封装 */ class Image{ private $info=[]; private $width;//原始图片宽度 private $height ...

  6. 多线程编程,CPU是如何解决多线程内存访问问题的

    CPU对内存变量的修改是先读取内存数据到CPU Cache中,然后再由CPU做运算,运算完成后继续写入到内存中 在单核CPU中,这完全没有问题,然而在多核CPU中,每一个CPU核心都拥有自己独立的Ca ...

  7. protocol buffers的编码原理

    protocol buffers使用二进制传输格式传递消息,因此相比于xml,json来说要轻便很多. 示例:假设定义了一个Message message Test1 { required int32 ...

  8. 基于Spring Task的定时任务调度器实现

    在很多时候,我们会需要执行一些定时任务 ,Spring团队提供了Spring Task模块对定时任务的调度提供了支持,基于注解式的任务使用也非常方便. 只要跟需要定时执行的方法加上类似 @Schedu ...

  9. php发送post请求的三种方法

    引用:http://blog.sjzycxx.cn/post/435/ 1.使用 file_get_contents() /** * 发送post请求 * @param string $url 请求地 ...

  10. 面试:C/C++常见库函数实现

    1. void *mymemcpy(void *dest, const void* src, size_t n): 内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个 ...