如何让子类使用父类?受保护的方法?
我正在为 web 应用程序编写一个前端控制器 servlet 类。前端控制器旨在区分三种基本情况:
- 文件请求(调用
FileRequestHandler
实例) - 数据请求(调用
DataRequestHandler
实例) - Servlet 请求(调用
ServletRequestHandler
实例)
为了测试,我想使用 Tomcat 的 DefaultServlet
(javadoc,源代码)来提供文件,但我不能让它发挥作用。问题是,即使我的 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:事实证明,这个问题实际上是扩展类使用不当的后续问题,而不是继承的直接问题。
我添加的用于检测问题根源的日志帖子将引发 。如果我省略它,我将得到一个 NullPointerException 异常。NoSuchMethodException
。
它看起来是如此简单。我仍然无法让它按照我想要的方式工作。有什么想法、建议或见解吗?
蒂亚、
FK
I'm writing a front controller servlet class for webapps. The front controller is designed to differentiate between three basic cases:
- File request (calling a
FileRequestHandler
instance) - Data request (calling a
DataRequestHandler
instance) - 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 . If I omit it I'll get a NoSuchMethodException
.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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Class.getMethod
返回 public 方法 - 没有这样的 public 方法,因此出现异常。您可以使用 getDeclaredMethod 来获取非公共方法。目前尚不清楚为什么在没有日志记录的情况下尝试时会收到
NullPointerException
- 如果您可以发布更完整的堆栈跟踪,情况可能会更清楚。编辑:根据 DefaultServlet 的源代码 看起来这是抛出异常的行:
但这没有多大意义,因为在这种情况下
init()
应该抛出异常...您的日志中还有其他报告错误的内容吗?Class.getMethod
returns public methods - there's no such public method, hence the exception. You can usegetDeclaredMethod
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:
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?您不必执行任何特殊操作即可从超类调用受保护的方法。事实上,由于您没有在 servlet 中重写
doGet()
,因此它的doGet()
方法实际上应该是超类方法。除了正常调用之外,您不必做任何特殊的事情,例如:如果您愿意,可以将
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, itsdoGet()
method should literally be the superclass method. You shouldn't have to do anything special, beyond calling it normally, like:If you want you can replace
doGet(request,response)
withsuper.doGet(request,response)
, but it will make no difference in this case because you have not overriddendoGet()
in your subclass.