全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

反射时竟然NoSuchMethodException了!看这篇超详细的解决方案吧

发布时间:2022-09-09 14:29:00
发布人:syq

  前几天小编在讲Servlet时,为了灵活地使用同一个Servlet来处理对同一张表的业务操作请求,我给学生讲解了BaseServlet工具类的封装,基本实现思路有如下几个步骤。

  一. 反射封装BaseServlet工具类

  使用反射封装BaseServlet工具类,无论是哪个Servlet接收到请求,都由该类完成请求分发。因此该类的主要作用就是通过反射机制,确定我们请求的到底是哪个Servlet的哪个方法。

/*

 * BaseServlet 获取客户端请求的是哪个servlet的哪个方法

 * */

public class BaseServlet extends HttpServlet {

    @Override

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //获取客户端发来请求的标识:即要执行的方法名

        String method = req.getParameter("method");

        //获取方法属于哪个Servlet类

        Class<? extends BaseServlet> clazz = this.getClass();

        //通过类字节码对象获取要执行方法的对象

        try {

            Method mh = clazz.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);

            //执行方法

            mh.invoke(this,req,resp); // this.insert(req,resp);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

  二. 继承BaseServlet父类

  以后再创建Servlet时,我们要使任意一个Servlet类,不再直接继承HttpServlet,而是要继承统一的BaseServlet,完成请求的分发管理,例如:

35

  三. 异常展现

  然而有个别同学在按照上述思路自己编写代码时,却遇到了下面的NoSuchMethodException异常。他排查许久未果,于是就来找小编帮他解决。

041

  四. 异常原因

  起初,小编以为是学生从客户端发出请求时,未携带执行方法的标识或携带的方法标识与实际方法名不匹配,从而导致通过反射机制获取方法对象时报错。因为我们知道,在通过Methodmh=clazz.getMethod(method,HttpServletRequest.class,HttpServletResponse.class)获取Method对象时,必须保证方法名、参数匹配,才能找到指定的方法,否则就会出现此类异常。

  但经过排查,发现并不是以上原因,该学生的代码如下:

@WebServlet("/stuinfo")

public class StuinfoServlet extends BaseServlet {

    //创建serivce层对象

    private StuinfoService ss = new StuinfoSerivceImpl();

    

    //查询方法

    private void findAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //调用service层查询方法

        List<Stuinfo> list = ss.findAll();

        //将list集合数据保存到域对象中

        req.setAttribute("stuList",list);

        //跳转到主页面

        req.getRequestDispatcher("index.jsp").forward(req,resp);

    }

}

  五. 异常解决

  可能你也一眼就看到了,上述代码中,查询方法使用的是private修饰符,而私有成员在该类的外部是不能被访问的!因此我们在利用反射,通过getMethod()方法获取Method对象时就会出现NoSuchMethodException异常。所以现在的解决办法,你是不是立刻就明朗了,我们直接将private改成public就可以了。

  六. 暴力反射

  上面的问题是解决了,但大家还要知道,反射机制中还有一种叫暴力反射,听起来是不是很厉害!!利用暴力反射,即使被private修饰也可以进行正常的操作。

  小编在这里给大家再补上一刀,反射里的Constructor、Field、Method三个类都有getDeclaredXxx方法(这里的Xxx表示Constructor、Field、Method),该方法可以不受权限控制,就能够获取到类中的这些成员信息。如果我们想要使用私有的构造函数、字段、方法,则会自动访问类的isAccessable,其默认值是false,表示在访问成员时需要安全检查,如果发现是私有的则不允许访问。所以,如果我们想要访问类中的私有成员时,需要调用setAccessible(boolean flag)方法,将其改为true。这样,我们就可以对类中的私有成员进行操作了。

相关文章

敏捷开发实行中各岗位职能是什么?

敏捷开发实行中各岗位职能是什么?

2023-10-14
敏捷开发在实际应用中有什么注意点?

敏捷开发在实际应用中有什么注意点?

2023-10-14
软件定制开发中的敏捷开发是什么?

软件定制开发中的敏捷开发是什么?

2023-10-14
三维重建 3D reconstruction有哪些实用算法?

三维重建 3D reconstruction有哪些实用算法?

2023-10-14

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取