小白也能看懂的Java异常处理机制
异常处理是开发过程中不可或缺的一部分,用户希望看到一个可以接受的错误信息,开发运维人员也希望可以看到详细的错误信息。因此在开发过程中,应重视异常处理。异常处理过程中有几个常见的乱象,例如没有固定的规范,定义名称不同导致前后端各一套异常处理逻辑,重复代码增多。或者后端直接捕获异常,将日志打印到控制台。后台一旦出错,用户得不到任何提示信息。如果没有人特意去查看服务端的日志,甚至都不会有人发现异常。因此,我们要学会设计异常处理,避免发生乱象。设计异常处理设计好异常处理后,用户可以清晰的读懂错误原因。后端返回给前端的数据有统一的规范。后端只需要捕获异常并将异常转换成自定义异常对外抛出。运维将异常信息合理规范的持久化,以日志的形式存储起来,方便查询。(自定义异常就要求程序员对运行时异常进行解释)规范拦截异常转换为自定义异常必须全部抛出统一数据响应代码,使用http状态码,不能自定义不能对父类Excetion统一catch,要分小类catch在自定义异常的过程中要有好的描述异常情况在com.javafamily.familydemo下创建exception文件夹枚举异常的类型为了防止开发人员各有各的异常处理标准,我们需要规定好枚举异常类型:package com.javafamily.familydemo.exception;public enum PetsExceptionType { USER_INPUT_ERROR(400, "输入的数据错误"), SYSTEM_ERROR(500, "系统出现异常"), OTHER_ERROR(999, "系统出现未知异常"); // code private int code; // 异常类型中文描述 private String desc; public int getCode() { return code; } public String getDesc() { return desc; } PetsExceptionType(int code, String desc) { this.code = code; this.desc = desc; }}1234567891011121314151617181920212223242526复制代码类型:[java]自定义异常自定义异常继承RuntimeException:package com.javafamily.familydemo.exception;public class PetsException extends RuntimeException { // 错误编码 private int code; // 异常信息,提供友好的描述 private String message; // 所有的异常创建都是通过固化下来的枚举创建的,开发者不能随意创建,所以这里使用private的无参构造 private PetsException() { } public PetsException(PetsExceptionType exceptionTypeEnum) { this.code = exceptionTypeEnum.getCode(); this.message = exceptionTypeEnum.getDesc(); } public PetsException(PetsExceptionType exceptionTypeEnum, String message) { this.code = exceptionTypeEnum.getCode(); this.message = message; } public int getCode() { return code; } @Override public String getMessage() { return message; }}1234567891011121314151617181920212223242526272829303132复制代码类型:[java]请求接口统一响应数据结构解决不同的开发人员使用不同的结构来响应给前端,导致规范不统一,开发混乱的问题:package com.javafamily.familydemo.exception;import lombok.Data;@Datapublic class ExceptionResponse { // 请求是否处理成功 private boolean isok; // 请求响应状态码 private int code; // 请求结果描述信息 private String message; // 请求结果数据(通常用于查询操作) private Object data; private ExceptionResponse() { } // 出现异常时响应数据封装 public static ExceptionResponse error(PetsException e) { ExceptionResponse resultBean = new ExceptionResponse(); resultBean.setIsok(false); resultBean.setCode(e.getCode()); resultBean.setMessage(e.getMessage()); return resultBean; } public static ExceptionResponse error(PetsExceptionType petsExceptionType, String errorMessage) { ExceptionResponse resultBean = new ExceptionResponse(); resultBean.setIsok(false); resultBean.setCode(petsExceptionType.getCode()); resultBean.setMessage(errorMessage); return resultBean; } // 请求成功的响应,不带查询数据(增删改) public static ExceptionResponse success() { ExceptionResponse exceptionResponse = new ExceptionResponse(); exceptionResponse.setIsok(true); exceptionResponse.setCode(200); exceptionResponse.setMessage("SUCCESS!"); return exceptionResponse; } // 请求成功的响应(查) public static ExceptionResponse success(Object obj) { ExceptionResponse exceptionResponse = new ExceptionResponse(); exceptionResponse.setIsok(true); exceptionResponse.setCode(200); exceptionResponse.setMessage("SUCCESS!"); exceptionResponse.setData(obj); return exceptionResponse; } // 请求成功的响应(查) public static ExceptionResponse success(Object obj, String message) { ExceptionResponse exceptionResponse = new ExceptionResponse(); exceptionResponse.setIsok(true); exceptionResponse.setCode(200); exceptionResponse.setMessage(message); exceptionResponse.setData(obj); return exceptionResponse; }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566复制代码类型:[java]请求成功的情况下,ExceptionResponse.success()构建返回结果给前端。查询/请求等返回业务数据请求成功的情况下使用ExceptionResponse.success(data)构建返回结果给前端。请求处理过程发生异常,将异常转换为PetsException,在控制层使用ExceptionResponseerror(PetsException)构建返回结果给前端。判断某些条件为请求失败使用ExceptionResponseerror(petsExceptionType,errorMessage)构建响应结果。