异常

1.概念

程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。

Java的基本理念:结构不佳的代码不能运行。发现代码的理想时机是在编译阶段,也就是你试图运行程序之前。然而,编译期间并不能找到所有的错误,余下的问题必须要在运行期间解决。这就需要错误源能通过某种方式,把错误信息传给接收者。

异常处理机制就是这样的错误报告机制。

2.异常体系

image.png

2.1Throwable

(1)getMessage():获取detail message即相关的错误描述信息。

(2)toString():返回包含异常类名+getMessage()。

(3)printStackTrace():打印详细异常信息和异常抛出路径(不推荐使用,可使用log代替)。

2.2Error

Error是Throwable的子类之一,包含的方法主要来自于继承自Throwable的那些。Error我们开发者接触到的不多,一般都是和虚拟机相关的问题,如:系统崩溃、虚拟机错误、系统资源如内存不足等,如:OutOfMemoryError等。

Error靠程序自身是无法解决的,一般JVM会选择终止程序。

2.3Exception

Exception大致分为两类:

(1)可检查异常(checked exceptions)

Exception子类中除去RuntimeException以及其子类的异常都是可检查异常。

程序经过编译时,编译器会要求对此类异常进行处理(throws/try-catch)。

处理方式也就是:throws/try-catch。

(2)不可检查异常(unchecked exceptions)

RuntimeException以及他的子类。

程序经过编译时,编译器不会要求对此类异常进行处理(throws/try-catch)。RuntimeException以及他的子类和Error都属于不可检查异常。

对于RuntimeException的子类我们开发者要特别注意,因为编译器不会提示我们,我们要给与合适的处理(但像空指针、数组下标越界等异常都可以通过代码规避掉,还有些如NumberFormatException等在不确定的情况下要使用异常处理机制,举例:在解析JSON字符串形式的数字时,可能存在数字格式错误)。

3.自定义异常

注意以下要点:
(1)所有异常都必须是 Throwable 的子类。
(2)果希望写一个检查性异常类,则需要继承 Exception 类。
(3)如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

4.异常处理

4.1声明异常

在方法上通过throws关键字声明异常:

public getInfo(String name) throws FileNotFoundException

4.2抛出异常

向方法栈上方抛出异常,让调用者去处理异常

throw new MyException();

4.3捕获异常

通过try-catch语句捕获异常

try{  
    code  more code
}catch(Exception){
    handler for this type
}

4.4再次抛出异常(异常链)

语句中再次抛出异常(异常链)在catch中可以再抛出一个异常,这样做的目的是改变异常的类型。

比如:执行servlet的代码可能不想知道发生错误的细节原因,但希望明确的知道servlet是否又问题。这时,可以用ServletException去封装原始异常。

try
{
  access the database
}
catch(SQLExeption e)
{
  Throwable se = new ServletException();
  se.initCause(e);
  throw se;
}

这样做在捕获到异常时就可以使用如下方式,重新得到原始异常而补丢失细节:

Throwable e = se.getCause();

5.异常拦截与统一处理

使用拦截器拦截、处理异常

@ControllerAdvice:将会拦截Controller的相应异常

@ControllerAdvice
public class MyExceptionHandler {

//    Annotation for handling exceptions in specific handler classes and/or handler methods.
//    转发到系统的错误处理
//    @ExceptionHandler(TestException.class)
//    public String handleException(Exception e, HttpServletRequest request) {
//        Map map = new HashMap<>();
//        /*对异常信息进行处理*/
//        //传入我们自己的错误状态码  4xx 5xx
//        Integer statusCode = (Integer) request
//                .getAttribute("javax.servlet.error.status_code");
//        request.setAttribute("javax.servlet.error.status_code", 400);
//        map.put("code", "user.notexist");
//        map.put("message", "用户出错啦");
//        request.setAttribute("ext", map);
//
//        //转发到/error
//        return "forward:/error";
//    }

    //    Annotation for handling exceptions in specific handler classes and/or handler methods.
    @ExceptionHandler(TestException.class)
    @ResponseBody
    public Map handleException(Exception e, HttpServletRequest request) {
        Map map = new HashMap<>();
        /*对异常信息进行处理*/
        //传入我们自己的错误状态码  4xx 5xx
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        map.put("code", statusCode);
        map.put("message", "自定义异常出错了!");

        //转发到/error
        return map;
    }
}


    //调用
    @RequestMapping({"/errorTest"})
    public String errorTest() {
        throw new TestException("测试自定义异常");
    }

6. springboot自定义异常数据和页面

templates文件或static静态资源目录下创建对应的目录和文件即可,springboot会默认先从templates目录下寻找,其次在static目录下寻找,如果还是没有则使用系统默认的。

你可能感兴趣的:(异常)