如何让子类使用父类?受保护的方法?

发布于 2024-11-25 09:16:53 字数 2931 浏览 0 评论 0原文

我正在为 web 应用程序编写一个前端控制器 servlet 类。前端控制器旨在区分三种基本情况:

  1. 文件请求(调用 FileRequestHandler 实例)
  2. 数据请求(调用 DataRequestHandler 实例)
  3. Servlet 请求(调用 ServletRequestHandler 实例)

为了测试,我想使用 Tomcat 的 DefaultServletjavadoc,源代码)来提供文件,但我不能让它发挥作用。问题是,即使我的 FileRequestHandler 类应该正确扩展 DefaultServlet ,我也无法访问其受保护的方法(特别是用于处理 GET 请求的 doGet )。顺便说一句,这些类位于不同的包中。


代码:

public class FileRequestHandler extends DefaultServlet {

// fields

    private static final long serialVersionUID = 1L;

// methods

    public void setResponse(HttpServletRequest request , HttpServletResponse response, URI uri) 
            throws IOException, ServletException 
    {
                                                                                                                                    /* DEBUG */try {
            System.out.println("(!!) doGet >> " + DefaultServlet.class.getMethod("doGet",new Class[]{HttpServletRequest.class,HttpServletResponse.class}) ) ;
            doGet(request,response) ;
                                                                                                                                    /* DEBUG */}
                                                                                                                                    /* DEBUG */catch(Exception e) { System.out.println("(!) " + this.getClass( ).getName( ) + " >> buildResponse >> " + e.toString( ) ) ; }
    }

 }

堆栈跟踪:

(通向 NullPointer 的部分)

位于 org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:741) 在 org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:398) 在 org.pulse.web.FileRequestHandler.buildResponse(FileRequestHandler.java:39)


更新:

我可能必须澄清前端控制器 servlet 将拦截所有 HttpRequest,(;/ in web.xml),据我所知,servlet 容器实例化的 DefaultServlet 将不会收到任何请求。 我现在在前端控制器类中明确调用了 DefaultServlet#init

 FileRequestHandler fileRequestHandler = new FileRequestHandler( ) ;
 fileRequestHandler.init( ) ;

现在我最终得到 404 Servlet 不可用。

更新2:事实证明,这个问题实际上是扩展类使用不当的后续问题,而不是继承的直接问题。


我添加的用于检测问题根源的日志帖子将引发 NoSuchMethodException。如果我省略它,我将得到一个 NullPointerException 异常。

它看起来是如此简单。我仍然无法让它按照我想要的方式工作。有什么想法、建议或见解吗?

蒂亚、

FK

I'm writing a front controller servlet class for webapps. The front controller is designed to differentiate between three basic cases:

  1. File request (calling a FileRequestHandler instance)
  2. Data request (calling a DataRequestHandler instance)
  3. Servlet request (calling a ServletRequestHandler instance)

For testing I wanted to use Tomcat's DefaultServlet (javadoc,source code) to serve files but I cannot get it to work. The problem is that even though my FileRequestHandler class should properly extend the DefaultServlet I cannot access its protected methods (specifically doGet for handling GET requests). The classes are in different packages btw.


Code:

public class FileRequestHandler extends DefaultServlet {

// fields

    private static final long serialVersionUID = 1L;

// methods

    public void setResponse(HttpServletRequest request , HttpServletResponse response, URI uri) 
            throws IOException, ServletException 
    {
                                                                                                                                    /* DEBUG */try {
            System.out.println("(!!) doGet >> " + DefaultServlet.class.getMethod("doGet",new Class[]{HttpServletRequest.class,HttpServletResponse.class}) ) ;
            doGet(request,response) ;
                                                                                                                                    /* DEBUG */}
                                                                                                                                    /* DEBUG */catch(Exception e) { System.out.println("(!) " + this.getClass( ).getName( ) + " >> buildResponse >> " + e.toString( ) ) ; }
    }

 }

Stack trace:

(part leading up to the NullPointer)

at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:741)
at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:398)
at org.pulse.web.FileRequestHandler.buildResponse(FileRequestHandler.java:39)


Update:

I maybe have to clarify that the front controller servlet will intercept all HttpRequests, (<url-pattern>/</url-pattern> in web.xml) to the effect that DefaultServlet instantiated by the servlet container will not receive any requests, as far as I can tell.
I have now explicitely called DefaultServlet#init in the front controller class:

 FileRequestHandler fileRequestHandler = new FileRequestHandler( ) ;
 fileRequestHandler.init( ) ;

Now I end up with a 404 Servlet is not available.

Update2: The problem -- as turns out -- actually is a follow-up problem with inadequate use of the extended class rather than a direct problem with inheritance.


The post to the Log which I added to detect the problem's root will provoke a NoSuchMethodException.. If I omit it I'll get a NullPointerException.

It looks ever so simple. Still I can't get it to work the way I want it to. Any ideas, suggestions or insights?

TIA,

FK

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南巷近海 2024-12-02 09:16:53

Class.getMethod 返回 public 方法 - 没有这样的 public 方法,因此出现异常。您可以使用 getDeclaredMethod 来获取非公共方法。

目前尚不清楚为什么在没有日志记录的情况下尝试时会收到 NullPointerException - 如果您可以发布更完整的堆栈跟踪,情况可能会更清楚。

编辑:根据 DefaultServlet 的源代码 看起来这是抛出异常的行:

CacheEntry cacheEntry = resources.lookupCache(path);

但这没有多大意义,因为在这种情况下 init() 应该抛出异常...您的日志中还有其他报告错误的内容吗?

Class.getMethod returns public methods - there's no such public method, hence the exception. You can use getDeclaredMethod to get non-public methods.

It's not clear why you were getting a NullPointerException when you tried it without the logging - if you can post a fuller stack trace, it may be clearer.

EDIT: Judging by the source code for DefaultServlet it looks like this is the line throwing the exception:

CacheEntry cacheEntry = resources.lookupCache(path);

That doesn't make much sense though, as init() should have thrown an exception in that case... is there anything else reporting an error in your logs?

余生一个溪 2024-12-02 09:16:53

您不必执行任何特殊操作即可从超类调用受保护的方法。事实上,由于您没有在 servlet 中重写 doGet(),因此它的 doGet() 方法实际上应该是超类方法。除了正常调用之外,您不必做任何特殊的事情,例如:

public void setResponse(HttpServletRequest request , HttpServletResponse response, URI uri) 
        throws IOException, ServletException  {

        doGet(request,response) ;
}

如果您愿意,可以将 doGet(request,response) 替换为 super.doGet(request,response) code>,但在这种情况下没有什么区别,因为您没有在子类中重写 doGet()

You shouldn't have to do anything special in order to call a protected method from the superclass. In fact, since you haven't overridden doGet() in your servlet, its doGet() method should literally be the superclass method. You shouldn't have to do anything special, beyond calling it normally, like:

public void setResponse(HttpServletRequest request , HttpServletResponse response, URI uri) 
        throws IOException, ServletException  {

        doGet(request,response) ;
}

If you want you can replace doGet(request,response) with super.doGet(request,response), but it will make no difference in this case because you have not overridden doGet() in your subclass.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文