HTTP状态405 - 此URL不支持HTTP方法

24

我有以下的servlet:

public class MyServlet extends HttpServlet {

    private static final long serialVersionUID = 16252534;
    private static int ping = 3000;
    private Thread t;
    private static boolean shouldStop = false;

    @Override
    public void init() throws ServletException {
        super.init();

        t = new Thread(new Runnable() { 
            @Override
            public void run() {
                while(!shouldStop) {
                    System.out.println("Now:" + System.currentTimeMillis());
                    try {
                        Thread.sleep(ping);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();

    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
        super.doGet(req, resp);
        System.out.println("doGet");
        PrintWriter out = resp.getWriter();
        out.println("<html><h1>It works!!</h1></html>");
    }

    @Override
    public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
        super.service(req, resp);
        System.out.println("service");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
        System.out.println("doPost");

    }

    @Override
    public void destroy() {
        super.destroy();
        System.out.println("Destroy servlet");
        shouldStop = true;
    }
}

以下是我在web.xml中的映射:

<display-name>MyServer</display-name>
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.myserver.MyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>      
   <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/MyServlet</url-pattern>
</servlet-mapping>

当我在Chrome浏览器中打开http://localhost:8080/MyServer/MyServlet时,控制台会记录从doService()中输出的“service”,并且我的线程可以正常工作,但是我没有看到从doGet()中输出的“It Works”的记录,浏览器中出现以下错误信息:

HTTP方法GET不受此URL支持

这是由什么引起的?我该如何解决?
2个回答

66
这是HttpServlet#doXxx()方法(doGet()doPost()doHead()doPut()等)的默认实现。这意味着当你的servlet类中的doXxx()方法没有正确地使用@Override修饰,或者当它通过super被显式调用时,你将面临HTTP 405“方法不允许”的错误。
因此,你需要确保你已经按照API正确声明了doXxx()方法,包括@Override注解,以确保你没有任何笔误。例如:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // ...
}

同时,您还需要确保在Servlet方法中不要调用super.doXxx()

super.doGet(request, response);

你的servlet有这个问题。只需删除此行,你的问题就会消失。

HttpServlet基本上遵循模板方法模式,其中所有未覆盖的HTTP方法返回此HTTP 405错误"方法不受支持"。当你覆盖这样的方法时,不应调用super方法,因为否则仍将获得HTTP 405错误。对于doPost()方法也是如此。

顺便说一下,这也适用于service(),但在这种情况下,从技术上讲并不会造成伤害,因为你需要它来让默认实现执行正确的方法。实际上,整个service()方法对你来说都是不必要的,你可以从servlet中删除整个方法。

super.init();也是不必要的。只有在覆盖init(ServletConfig)时才需要它,否则ServletConfig将不会被设置。这也在javadoc中明确提到。这是唯一需要super调用的方法。


与具体问题无关,在servlet中像这样生成线程是一个坏主意。正确的方法,请参阅如何在基于servlet的Web应用程序中运行后台任务?


非常感谢。我已经使用了ServletContextListener。有一个问题:为什么在servlet中使用Thread是个坏主意? - CeccoCQ
1
这并不一定是坏事,但你编写的代码会永久地消耗100%的CPU资源。你应该使用线程池和调度程序,就像链接答案中所概述的那样。而ServletContextListener则是在Web应用程序启动和关闭期间进行全局初始化和清理的正确位置。 - BalusC

0

您已经重写了service方法,该方法负责将调用委托给doGet或doPost。请参阅此处以获取更多详细信息
还要从每个方法中摆脱super.doxxx(..)的调用。 不要重写service方法,您应该从doGet看到"It Works"。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接