全栈项目-乐优商场-通用工具服务-通用异常处理

全栈项目-乐优商场-通用工具服务-通用异常处理


目录




内容

项目中出现异常在所难免,那么出现异常后怎么处理呢?

1、 场景预设

1.1、场景

假如我们做新增商品,需要接收下面的参数:

price: 价格
name: 名称

对数据做简单校验:

价格不能为空

新增时,自动形成ID,然后随商品对象一起返回

1.2、代码

  • 实体类:在’ly-item-interface’模块中下java/com/leyou/item/pojo包下新建Item类

      package com.leyou.item.pojo;
    
      import lombok.Data;
    
      @Data
      public class Item {
      	private Integer id;
      	private String name;
      	private Integer price;
      }
    
  • service层:’ly-item-service’模块,java/com/leyou/item/service/ItemService

      package com.leyou.item.service;
    
      import com.leyou.item.pojo.Item;
      import org.springframework.stereotype.Service;
    
      import java.util.Random;
    
      @Service
      public class ItemService {
      	public Item saveItem(Item item) {
      		int id = new Random().nextInt(100);
      		item.setId(id);
      		return item;
      	}
    
  • web层: ’ly-item-service’模块,java/com/leyou/item/web/ItemController

      package com.leyou.item.web;
    
      import com.leyou.item.pojo.Item;
      import com.leyou.item.service.ItemService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.http.HttpStatus;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
    
      @RestController
      @RequestMapping("item")
      public class ItemController {
      	@Autowired
      	private ItemService itemService;
    
      	@PostMapping
      	public ResponseEntity<Item> saveItem(Item item) {
      		// 校验价格
      		if (item.getPrice() == null) {
      			return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
      		}
      		Item item1 = itemService.saveItem(item);
      		return ResponseEntity.status(HttpStatus.CREATED).body(item1);
      	}
      }
    

1.3、启动测试‘ly-item-service’模块

使用前后端交互测试工具,insomnia或者postman。这里我们用postman,发送正常测试数据,返回结果,如图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xaxCAv0B-1596602783754)(./images/2020-08-04_handle-exception-normal.png)]

发送错误测试数据,结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nBQq8Z6Y-1596602783756)(./images/2020-08-04_handle-exception-error.png)]

有逻辑错误,但是没有错误提示,显然很不友好,下面我们开始做改进

2、错误处理改进

2.1、发生错误,我们直接返回异常

其他不变,修改ItemController类saveItem方法如下:

public ResponseEntity<Item> saveItem(Item item) {
		// 校验价格
		if (item.getPrice() == null) {
			throw new RuntimeException("价格不能为空");
		}
		Item item1 = itemService.saveItem(item);
		return ResponseEntity.status(HttpStatus.CREATED).body(item1);
	}

在此发送错误数据,postman返回数据:

{
	"timestamp": "2020-08-04T08:22:43.966+00:00",
	"status": 500,
	"error": "Internal Server Error",
	"message": "",
	"path": "/item"
}

显示服务器内部错误,这显然有误导,只是参数传递错误。

2.2、@ControllerAdvice改进

  • @ControllerAdvice注解会拦截所有带@Controller的返回
  • @ExecptionHandler 会拦截异常
    • @ExceptionHandler(异常类字节码)拦截指定类型的异常

在’ly-common’模块 java/com/leyou/common/advice 新建CommonExceptionHandler类,用来拦截处理异常,代码如下:

package com.leyou.common.advice;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class CommonExceptionHandler {
	@ExceptionHandler(RuntimeException.class)
	public ResponseEntity<String> handleException(RuntimeException e) {
		return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
	}
}

‘ly-item-service’ pom.xml 添加ly-common依赖,如下:

 <dependency>
			<groupId>com.leyou.common</groupId>
			<artifactId>ly-common</artifactId>
			<version>1.0.0-SNAPSHOT</version>
</dependency>

重新加载工程,重启服务,重新发送错误测试,返回结果:

价格不能为空

这样的话,提示过于简单,继续改进

2.3、自定义异常类

一下类都在’ly-common’模块下 java/com/leyou/common包下创建

  • LyException.java ,自定义异常类 exception包下,代码如下:

      package com.leyou.common.exception;
    
      import com.leyou.common.enums.ExceptionEnum;
      import lombok.AllArgsConstructor;
      import lombok.Getter;
      import lombok.NoArgsConstructor;
    
      @NoArgsConstructor
      @AllArgsConstructor
      @Getter
      public class LyException extends RuntimeException {
      	private ExceptionEnum exceptionEnum;
      }
    
  • ExceptionEnum,异常枚举 enums包下,代码如下:

      package com.leyou.common.enums;
    
      import lombok.AllArgsConstructor;
      import lombok.Getter;
      import lombok.NoArgsConstructor;
    
      @NoArgsConstructor
      @AllArgsConstructor
      @Getter
      public enum ExceptionEnum {
      	PRICE_NOTNULL(400, "价格不能为空!")
      	;
      	private int code;
      	private String msg;
      }
    
  • ExceptionResult,异常结果类,封装异常结果,vo包下,代码如下:

      package com.leyou.common.vo;
    
      import com.leyou.common.enums.ExceptionEnum;
      import lombok.Data;
    
      @Data
      public class ExceptionResult {
      	private int status;
      	private String message;
      	private long timestamp;
    
      	public ExceptionResult(ExceptionEnum e) {
      		this.status = e.getCode();
      		this.message = e.getMsg();
      		this.timestamp = System.currentTimeMillis();
      	}
      }
    

整体包结构如图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2hCN77ks-1596602783758)(./images/2020-08-04_ly-common-struc.png)]

重新reiport工程,重新运行’ly-item-service’模块,如果报错就重新install下’leyou‘一级工程,重新发送错误数据,返回结果图示:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v6UgLHbX-1596602783761)(./images/2020-08-04_ly-common-exception-package.png)]

到此通用异常处理结束,如果有新的逻辑异常,比如注册用户名不能重复,只需在ExceptionEnum内添加,然后使用即可。

后记

本项目为参考某马视频开发,相关视频及配套资料可自行度娘或者联系本人。上面为自己编写的开发文档,持续更新。欢迎交流,本人QQ:806797785

前端项目源代码地址:https://gitee.com/gaogzhen/ly-bms    // 前端后台管理系统
后端JAVA源代码地址:https://gitee.com/gaogzhen/ly-backend        // 后端项目

猜你喜欢

转载自blog.csdn.net/gaogzhen/article/details/107812660