欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-22 18:21:46
...

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


目录




内容

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

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,发送正常测试数据,返回结果,如图:全栈项目-乐优商场-通用工具服务-通用异常处理

发送错误测试数据,结果:全栈项目-乐优商场-通用工具服务-通用异常处理

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

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();
      	}
      }
    

整体包结构如图:全栈项目-乐优商场-通用工具服务-通用异常处理

重新reiport工程,重新运行’ly-item-service’模块,如果报错就重新install下’leyou‘一级工程,重新发送错误数据,返回结果图示:全栈项目-乐优商场-通用工具服务-通用异常处理

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

后记

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

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