Java异常分类和统一处理

Java基础

浏览数:29

2020-5-30

AD:资源代下载服务

一,异常分类

            java异常分为”检查”和”非检查”两类,”检查”二字的意思是,代码编译时,编译器会去Check一下有没有进行异常处理(捕获或向上抛),对于归类为需要检查的异常,若没处理,编译就过不去。
            初学时常常想exception为啥要这样分类处理呢? 后来才明白,异常不过两种:主观和客观,一个大多数情况下可以避免,一个大多数情况下无法避免。
            像NullPointerException这类异常,大多跟程序员素质挂钩(开发好,测试好, 基本不会在系统运行后蹦出来), 基本是可以避免的,java语法当初把它们归类为“非检查”,也算给程序员和编译器省了不少事。
            而像IOException这类跟外在环境有关的异常,几乎是不可避免的(指不定哪一天哪一秒网络就挂了),但是当不期而遇时,程序还是要有所作为,所以编译器有必要督促一下程序员,Check一下,看看是否对这些可能不期而至的异常进行了处理。当Exception对象传递到某个节点后,程序就可以执行一些必要措施了,比如:给用户一个友好提示(”系统繁忙,请重试”)。

二,异常的统一处理

1,服务器处理

下面列举Tomcat和Nginx为例

Tomcat是Servlet容器,主要处理动态请求,在web.xml下配置,按http返回码或Exception类型来处理:

<error-page>
  <error-code>404</error-code>
  <location>/WEB-INF/views/error/404.jsp</location>
 </error-page>
 
 <error-page>
  <error-code>500</error-code>
  <location>/WEB-INF/views/error/500.jsp</location>
 </error-page> 
 
 <error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/WEB-INF/views/error/throwable.jsp</location>
 </error-page>

Nginx,也可以通过Http返回码很方便地指定异常时的返回页面:

server {  
    listen 80 ;  
    server_name xx.com ;  
    root /var/www ;  
    index index.html ;  
    error_page 404  /404.html ;  
    location = /404.html {  
       root /usr/share/nginx/html;  
    }  
}  

2,应用程序框架处理

以Spring boot为例, 在处理接口返回时, 进行全局异常的捕获

1) 自定义业务异常

/**
 * 自定义业务异常类
 */
public class BusinessException extends RuntimeException {

    private String code;

    public BusinessException(String code, String message) {
        super(message);
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return super.getMessage();
    }
}

2) 定义接口返回数据结构

/**
 * 接口返回数据对象
 * @param <T> 业务对象
 */
public class Result<T> implements Serializable {
    private String code;
    private String message;
    private T data;

    public Result(String code,String message){
        super();
        this.code=code;
        this.message=message;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

3) 全局捕获处理

@ControllerAdvice
public class ExceptionController {

    private Logger logger= LoggerFactory.getLogger(ExceptionController.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result exceptionOut(Exception e){
        logger.error("全局异常捕获,e:{}",e);
        Result result=null;
        if(e instanceof BusinessException){
            result= new Result(((BusinessException) e).getCode(),e.getMessage());
        }else{
            result= new Result("500","系统异常");
        }
        return result;
    }
}

 

作者:他城之途