一、问题描述

做黑马旅游网项目的时候在从数据库中获取分类条目(category)的时候抛出如下异常:
异常
这个反射异常出现的位置是BaseServlet文件,刚开始不知道这个异常产生的原因一直以为是BaseServlet里面的问题,却忽略了其他的文件。由于项目中间搁置了一段时间后才继续跟着做导致前面的某些操作就忘了,重新看了一遍视频才发现问题所在。

二、问题分析

1. 页面加载完成、向服务器端发送Ajax异步请求(请求路径:"category/findAll")
2. 服务器端的servlet操作是先让CategoryServlet继承BaseServlet,BaseServlet的功能就是继承
HttpServlet对CategoryServlet进行一个方法的分发。CategoryServlet的注解配置就是category/*
3. Servlet中调用service中的findAll方法查询类别返回一个list集合
4. service同样调用CategoryDao中的findAll方法返回一个list集合

问题就出现在第三步里面,由于之前在service中进行了一个数据库访问的优化,即:在service层先判断redis数据库中是否有数据,有的话直接访问redis获得数据,没有的话再进度dao访问数据库,避免了频繁访问数据造成的压力。因此就需要在开启服务器的同时,redis服务器也必须开启,否则就会报这样的错!

三、异常产生原因

那么为什么会在这里报错呢?我的做法是分别在Servlet和service文件里打上断点,进行一步一步的调试,发现进不去service层异常就会产生,其实就是service里面的问题只是断点位置打在了异常抛出之后了。这里加一个小记录:在service的最前面加一个输出语句,断点打在这行就知道是否进去了。上网查了一下InvocationTargetException异常,大概总结一下。

1、InvocationTargetException异常

首先InvocationTargetException异常由Method.invoke(obj, args…)方法抛出。当被调用的方法的内部抛出了异常而没有被捕获时,将由此异常接收!这里显然是在service里面的抛出异常后没有捕获到返回到BaseServlet中由这个异常接收到了。

2、附一个例子

示例:

package com.zzj.test.reflect;  
  
public class Reflect {  
    public void run(int i) throws ZeroException {  
        B b = new B();  
        b.run(i);  
    }  
}  
  
class B {  
    public void run(int i) throws ZeroException {  
        if (i < 0) {  
            throw new ZeroException("参数不能小于零!");  
        }  
        System.out.println("参数:" + i);  
  
    }  
}  
  
class ZeroException extends Exception {  
    private static final long serialVersionUID = 1L;  
  
    private String detailMessage;  
  
    public ZeroException(String detailMessage) {  
        this.detailMessage = detailMessage;  
    }  
  
    public String getMessage() {  
        return detailMessage;  
    }  
}  

测试:

package com.zzj.test.reflect;  
  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
  
public class Test {  
    public static void main(String[] args) {  
        try {  
            Class<?> clazz = Class.forName("com.zzj.test.reflect.Reflect");  
            Method method = clazz.getMethod("run", int.class);  
            method.invoke(clazz.newInstance(), -1);  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        } catch (SecurityException e) {  
            e.printStackTrace();  
        } catch (NoSuchMethodException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            System.out.println("此处接收被调用方法内部未被捕获的异常");  
            e.printStackTrace();  
        } catch (InstantiationException e) {  
            e.printStackTrace();  
        }  
    }  
}  

输出:

此处接收被调用方法内部未被捕获的异常  
java.lang.reflect.InvocationTargetException  
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)  
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)  
    at java.lang.reflect.Method.invoke(Unknown Source)  
    at com.zzj.test.reflect.Test.main(Test.java:11)  
Caused by: com.zzj.test.reflect.ZeroException: 参数不能小于零!  
    at com.zzj.test.reflect.B.run(Reflect.java:13)  
    at com.zzj.test.reflect.Reflect.run(Reflect.java:6)  
    ... 5 more  

参考: Java异常处理之InvocationTargetException(反射异常)

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐