Статус HTTP 405 — метод HTTP не поддерживается этим URL-адресом

У меня есть следующий сервлет:

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() регистрируется на консоли, и мой поток работает правильно, однако я не вижу "Это работает" от doGet(), регистрируемого, и я получаю следующую ошибку в браузер:

HTTP-метод GET не поддерживается этим URL-адресом

Чем это вызвано и как я могу это решить?


person CeccoCQ    schedule 20.03.2011    source источник


Ответы (2)


Это ответ по умолчанию стандартной реализации метода HttpServlet#doXxx() (doGet(), doPost(), doHead(), doPut() и т. д.). Это означает, что когда метод doXxx() не является должным образом @Overriden в вашем классе сервлета или когда он явно вызывается через super, вы столкнетесь с ошибкой HTTP 405 "Метод не разрешен".

Итак, вам нужно убедиться, что у вас правильно объявлен метод doXxx(), соответствующий API, включая аннотацию @Override, чтобы убедиться, что вы не сделали никаких опечаток. Например.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // ...
}

И вам также нужно убедиться, что вы никогда не вызываете super.doXxx() в своем методе сервлета:

super.doGet(request, response);

В вашем сервлете есть это. Просто избавьтесь от этой строки, и ваша проблема исчезнет.

HttpServlet в основном следует шаблону метода шаблона, где все непереопределенные методы HTTP возвращают эту ошибку HTTP 405. "Метод не поддерживается". Когда вы переопределяете такой метод, вам не следует не вызывать метод super, поскольку в противном случае вы все равно получите ошибку HTTP 405. То же самое происходит и с вашим методом doPost().

Кстати, это также применимо к service(), но технически это не вредит этой конструкции, поскольку вам нужно это, чтобы позволить реализации по умолчанию выполнять правильные методы. На самом деле весь метод service() вам не нужен, вы можете просто удалить весь метод из своего сервлета.

super.init(); также не нужен. Это необходимо только тогда, когда вы переопределяете init(ServletConfig), иначе ServletConfig не будет установлено. Это также явно упоминается в javadoc. Это единственный метод, который требует вызова super.


Не связанный с конкретной проблемой, создание потока в таком сервлете — плохая идея. Для правильного подхода перейдите к How запустить фоновую задачу в веб-приложении на основе сервлета?

person BalusC    schedule 20.03.2011
comment
Большое Вам спасибо. Я использовал ServletContextListener. Один вопрос: почему использование Thread в сервлете — плохая идея? - person CeccoCQ; 21.03.2011
comment
Это не обязательно плохо, но то, как вы написали код, потребляет 100% ресурсов ЦП навсегда. Вам лучше использовать пул потоков и планировщик, как указано в связанном ответе. И ServletContextListener — это просто подходящее место для глобальной инициализации и очистки во время запуска и завершения работы веб-приложения. - person BalusC; 21.03.2011

вы переопределили метод service, который отвечает за делегирование вызова doGet или doPost. подробнее см. здесь
Также избавьтесь от super.doxxx (..) вызовы из каждого метода. Не переопределяйте метод service, и вы должны увидеть «Это работает» от doGet.

person Premraj    schedule 20.03.2011