首页

Java基本框架设计之后台异常处理

标签:异常处理     发布时间:2023-04-16   

一、前言

在开发过程中,不可避免的是需要处理各种异常,异常处理方法随处可见,所以代码中就会出现大量的'try {...} catch {...} finally {...}' 代码块,不仅会造成大量的冗余代码,而且还影响代码的可读性,所以对异常统一处理非常有必要。

二、方案说明

1)我们定义了一个统一的异常类'YamiShopBindException' 与异常管理类 'DefaultExceptionHandlerConfig'。

@Getter@b@public class YamiShopBindException extends RuntimeException{@b@@b@    /**@b@     *@b@     */@b@    private static final long serialVersionUID = -4137688758944857209L;@b@@b@    /**@b@     * http状态码@b@     */@b@    private String code;@b@@b@    private Object object;@b@@b@    private ServerResponseEntity<?> serverResponseEntity;@b@@b@    public YamiShopBindException(ResponseEnum responseEnum) {@b@        super(responseEnum.getMsg());@b@        this.code = responseEnum.value();@b@    }@b@    /**@b@     * @param responseEnum@b@     */@b@    public YamiShopBindException(ResponseEnum responseEnum, String msg) {@b@        super(msg);@b@        this.code = responseEnum.value();@b@    }@b@@b@    public YamiShopBindException(ServerResponseEntity<?> serverResponseEntity) {@b@        this.serverResponseEntity = serverResponseEntity;@b@    }@b@@b@@b@    public YamiShopBindException(String msg) {@b@        super(msg);@b@        this.code = ResponseEnum.SHOW_FAIL.value();@b@    }@b@@b@    public YamiShopBindException(String msg, Object object) {@b@        super(msg);@b@        this.code = ResponseEnum.SHOW_FAIL.value();@b@        this.object = object;@b@    }@b@@b@}

2)ResponseEnum类 - 为我们自定义的返回状态码的枚举类,定义为一个枚举类,更直观处理异常返回的状态码及异常内容,以后每增加一种异常情况,只需增加一个枚举实例即可,不用每一种异常都定义一个异常类。

public enum ResponseEnum {@b@@b@    /**@b@     * ok@b@     */@b@    OK("00000", "ok"),@b@    SHOW_FAIL("A00001", ""),@b@@b@    /**@b@     * 用于直接显示提示用户的错误,内容由输入内容决定@b@     */@b@@b@    /**@b@     * 用于直接显示提示系统的成功,内容由输入内容决定@b@     */@b@    SHOW_SUCCESS("A00002", ""),@b@@b@    /**@b@     * 未授权@b@     */@b@    UNAUTHORIZED("A00004", "Unauthorized"),@b@@b@    /**@b@     * 服务器出了点小差@b@     */@b@    EXCEPTION("A00005", "服务器出了点小差"),@b@    /**@b@     * 方法参数没有校验,内容由输入内容决定@b@     */@b@    METHOD_ARGUMENT_NOT_VALID("A00014", "方法参数没有校验");@b@@b@    private final String code;@b@@b@    private final String msg;@b@@b@    public String value() {@b@        return code;@b@    }@b@@b@    public String getMsg() {@b@        return msg;@b@    }@b@@b@    ResponseEnum(String code, String msg) {@b@        this.code = code;@b@        this.msg = msg;@b@    }@b@@b@    @Override@b@    public String toString() {@b@        return "ResponseEnum{" + "code='" + code + '\'' + ", msg='" + msg + '\'' + "} " + super.toString();@b@    }@b@@b@}

3)'DefaultExceptionHandlerConfig'类

@Slf4j@b@@RestController@b@@RestControllerAdvice@b@public class DefaultExceptionHandlerConfig {@b@@b@    @ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })@b@    public ResponseEntity<ServerResponseEntity<List<String>>> methodArgumentNotValidExceptionHandler(Exception e) {@b@        log.error("methodArgumentNotValidExceptionHandler", e);@b@        List<FieldError> fieldErrors = null;@b@        if (e instanceof MethodArgumentNotValidException) {@b@            fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();@b@        }@b@        if (e instanceof BindException) {@b@            fieldErrors = ((BindException) e).getBindingResult().getFieldErrors();@b@        }@b@        if (fieldErrors == null) {@b@            return ResponseEntity.status(HttpStatus.OK)@b@                    .body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID));@b@        }@b@@b@        List<String> defaultMessages = new ArrayList<>(fieldErrors.size());@b@        for (FieldError fieldError : fieldErrors) {@b@            defaultMessages.add(fieldError.getField() + ":" + fieldError.getDefaultMessage());@b@        }@b@        return ResponseEntity.status(HttpStatus.OK)@b@                .body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID, defaultMessages));@b@    }@b@@b@    @ExceptionHandler(YamiShopBindException.class)@b@    public ResponseEntity<ServerResponseEntity<?>> unauthorizedExceptionHandler(YamiShopBindException e){@b@        log.error("mall4jExceptionHandler", e);@b@@b@        ServerResponseEntity<?> serverResponseEntity = e.getServerResponseEntity();@b@        if (serverResponseEntity!=null) {@b@            return ResponseEntity.status(HttpStatus.OK).body(serverResponseEntity);@b@        }@b@        // 失败返回消息 状态码固定为直接显示消息的状态码@b@        return ResponseEntity.status(HttpStatus.OK).body(ServerResponseEntity.fail(e.getCode(),e.getMessage()));@b@    }@b@@b@    @ExceptionHandler(Exception.class)@b@    public ResponseEntity<ServerResponseEntity<Object>> exceptionHandler(Exception e){@b@        log.error("exceptionHandler", e);@b@        return ResponseEntity.status(HttpStatus.OK).body(ServerResponseEntity.fail(ResponseEnum.EXCEPTION));@b@    }@b@}

4)前台异常处理  - 前端请求与相应做了封装,请求响应的内容会被拦截器所拦截,当后台返回给前台特定的状态码,前台将显示不同报错信息。请求响应非常常见,我们查看在'src\utils\httpRequest.js'里面的其中一段代码(这里将会统一拦截返回的状态码如'400',进行错误提示。)

'''javascript@b@http.interceptors.response.use(response => {@b@  return response@b@}, error => {@b@  switch (error.response.status) {@b@    case 400:@b@      Message.error(error.response.data)@b@      break@b@    case 401:@b@      clearLoginInfo()@b@      router.push({ name: 'login' })@b@      break@b@    case 405:@b@      Message.error('http请求方式有误')@b@      break@b@    case 500:@b@      Message.error('服务器出了点小差,请稍后再试')@b@      break@b@    case 501:@b@      Message.error('服务器不支持当前请求所需要的某个功能')@b@      break@b@  }@b@  return Promise.reject(error)@b@})@b@'''

总结 :我们的上述代码使用http状态码对请求进行统一响应,其中最大的 RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。