java异常处理二

前言

通过一已经初步了解了异常的一些原理和相关性质,当然在平时写程序时被各种各样的异常类型弄得叫苦不堪
Alt text

java常见异常

从api文档中可以看出,java已经为我们内置了很多异常
Alt text
先来看看RuntimeException中常见异常

1java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
5、java.lang.NegativeArraySizeException 数组长度为负异常
6、java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常
7、java.lang.SecurityException 安全性异常
8、java.lang.IllegalArgumentException 非法参数异常

IOException

IOException:操作输入流和输出流时可能出现的异常。
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常

其他异常

ClassCastException 类型转换异常类
ArrayStoreException 数组中包含不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不允许访问某类异常
InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常

自定义异常

在Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
所有异常都必须是 Throwable 的子类。
如果希望写一个检查性异常类,则需要继承 Exception 类。
如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class MyException extends Exception{
private int id;
public MyException(){
}
public MyException(String msg,int id){
super(msg);
this.id=id;
}
public int getId(){
return this.id;
}
}
public class Ttest {
public void regist(int num) throws MyException{
if(num<0){
throw new MyException("不能为负数",404);
}
System.out.println("it is"+num);
}
public void manager(){
try {
regist(-10);
} catch (MyException e) {
System.out.println("Error Code"+e.getId());
e.printStackTrace();
}
System.out.println("over");
}
public static void main(String args[]){
Ttest t=new Ttest();
t.manager();
}
}

如果有异常时运行结果如下:

com.test.QQ.MyException: 不能为负数
at com.test.QQ.Ttest.regist(Ttest.java:6)
at com.test.QQ.Ttest.manager(Ttest.java:12)
at com.test.QQ.Ttest.main(Ttest.java:21)
Error Code404
over

将regist(-10)改为regist(10),如下

it is10
over

spring异常处理

前面我们都是用try..catch来捕获异常,造成业务逻辑较多,而spring通过注解式使捕获异常更方便。核心如下:

@ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
@ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开
@ResponseStatus:可以将某种异常映射为HTTP状态码

@ExceptionHandler源码如下:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}

首先是注解的说明:
@Retention: 定义注解的保留策略
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

@Target:定义注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包

@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解

该注解作用对象为方法,并且在运行时有效,value()可以指定异常类
方法返回值可以为:
ModelAndView对象
Model对象
Map对象
View对象
String对象
还有@ResponseBody、HttpEntity<?>或ResponseEntity<?>,以及void

@ControllerAdvice //在所有的controller中执行该异常
public class DefaultExceptionHandler {
/**

 * 没有权限 异常
 * <p/>
 * 后续根据不同的需求定制即可
 */
@ExceptionHandler({UnauthorizedException.class}) //不同的异常处理
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e) {
    System.out.println("un");
    return null;

}

@ExceptionHandler(RuntimeException.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)  
public String handleUnexpectedServerError(RuntimeException ex) { 
    System.out.println("500");
    return null;
}

@ExceptionHandler(ServletException.class)
@ResponseStatus(value = HttpStatus.NOT_FOUND)  
public String handleNotFoundError() {     
       System.out.println("404");
      return null;       
}

}

如上的500和404错误,先给出错误的异常,在给出错误的状态码并且异常与状态码必须是对应的,该类的源码在org.springframework.http下,如

public enum HttpStatus {
成功
OK(200, “OK”),
创建
CREATED(201, “Created”),
/接受
ACCEPTED(202, “Accepted”),
BAD_REQUEST(400, “Bad Request”),
没有认证权限
UNAUTHORIZED(401, “Unauthorized”),

PAYMENT_REQUIRED(402, “Payment Required”),
禁止
FORBIDDEN(403, “Forbidden”),

NOT_FOUND(404, “Not Found”),

有了上述全局处理的异常,就不许要在每个类里面重复写了,同时如果我们是在页面中需要捕获异常,如页面的404和500,只需在web.xml中配置一下(在spring配置文件中注入无效,也不知道怎么回事),如下:


404
/404.jsp


500
/500.jsp

热评文章