Spring MVC аннотированные методы контроллера, неспособные "найти" метод для операции DELETE

Вот фактический код:

@RequestMapping(value = "/competitors/{id}", method = RequestMethod.GET)
public Competitor getCompetitor(@PathVariable("id") long id)
{
    Competitor competitor = competitorService.getCompetitorById(id);

    if (null == competitor)
    {
        EmptyResultDataAccessException e = new EmptyResultDataAccessException(1);
        logger.log(Level.WARN, e.getMessage());
        throw e;
    }

    return competitor;
}

@RequestMapping(value = "/competitors/{id}", method = RequestMethod.DELETE)
public String deleteCompetitor(@PathVariable("id") long id)
{
    Competitor competitor = new Competitor();
    competitor.setId(id);
    competitorService.deleteCompetitor(competitor);

    return "Solid gone!";
}

Отправка запроса DELETE/конкурентам/200 приводит к ошибке:

"HTTP Status 405 - Метод запроса" DELETE "не поддерживается"

Запись из Spring подтверждает, что путь к этому методу не найден:

5559 [tomcat-http--3] DEBUG org.springframework.web.servlet.DispatcherServlet  - DispatcherServlet with name 'dispatcher' processing DELETE request for [/vrsboserver/competitors/200] 5562 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
- Matching patterns for request [/competitors/200] are [/competitors/{id}] 5565 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
- Mapping [/competitors/200] to handler '[email protected]' 5565 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.WebContentInterceptor  - Looking up cache seconds for [/competitors/200] 5565 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.WebContentInterceptor  - Applying default cache seconds to [/competitors/200] 5566 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver
- Resolving exception from handler [[email protected]]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'DELETE' not supported 5567 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
- Resolving exception from handler [[email protected]]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'DELETE' not supported 5568 [tomcat-http--3] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
- Resolving exception from handler [[email protected]]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'DELETE' not supported 5568 [tomcat-http--3] WARN  org.springframework.web.servlet.PageNotFound  - Request method 'DELETE' not supported

На что мой ответ "BUH?".

Ответ 1

У меня была такая же проблема. Что помогает, и это, вероятно, не окончательное решение, а работает для меня:

Изменение аннотаций и параметров метода deleteCompetitors. Удалите id (параметр метода тоже). Прочитайте параметр id из HttpServletRequest.

@RequestMapping(value = "/competitors", method = RequestMethod.DELETE)
public String deleteCompetitor(HttpServletRequest request)
{
    String idHeader = request.getHeader("id");

    Integer id = Integer.valueOf(idHeader).intValue();

    Competitor competitor = new Competitor();
    competitor.setId(id);
    competitorService.deleteCompetitor(competitor);

    return "Solid gone!";
}

Параметр id передается заголовком таким образом (код клиента - не завершен):

DefaultHttpClient httpClient = new DefaultHttpClient();

HttpDelete httpDelete = new HttpDelete...

...

httpDelete.setHeader("id", "123");

...

httpClient.execute(httpDelete);

Я использую Apache HttpClient.

Ответ 2

Поддержка только обычного браузера get/post.

Spring разрешил это с помощью скрытого параметра, чтобы включить его, добавьте ниже к вашему web.xml:

<filter>
    <filter-name>httpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>httpMethodFilter</filter-name>
    <servlet-name>springDispatcher</servlet-name>
</filter-mapping>

Ответ 3

Попробуйте изменить его на method = RequestMethod.GET и посмотрите, работает ли он.

Ответ 4

Попробовал ли вы http://www.codereye.com/2010/12/configure-tomcat-to-accept-http-put.html? Это будет работать, конечно, только на Tomcat. Похоже, что большинство серверов приложений отключили возможность обработки запросов PUT и DELETE по умолчанию.

Конечно, включение этого, вероятно, откроет вам новые дыры в безопасности.

Ответ 5

Недавно я столкнулся с этой проблемой. Вот несколько моих выводов/комментариев:

Я запускаю tomcat 7.0.42 с Spring 3.2.2

В журнале всех этих случаев выводится следующее сообщение. 405 "Метод не разрешен" возвращается клиенту.

org.springframework.web.servlet.PageNotFound  - Request method 'DELETE' not supported
  • URL-адрес REST, который вы используете, неверен. Хотя конечной точки нет, вы все равно получаете 405.
  • Вы не авторизованы и не имеете права выполнять какие-либо действия, не говоря уже о DELETE
  • DELETE фактически не поддерживается, потому что нет функции с методом = RequestMethod.GET
  • Tomcat блокирует операции, такие как DELETE, PUT и т.д. из-за того, что init-param для readonly установлен на true
  • Метод присутствует, DELETE разрешен, все в порядке, за исключением того, что в методе было исключено исключенное исключение во время выполнения (например, исключение Null Pointer)

За исключением 3 и 4, показанное сообщение и ответ очень вводят в заблуждение. Он посылает вам исследования кроличьих отверстий, которые заканчиваются бесплодными.

В результате моя проблема в том, что у нас был такой метод:

public void deleteSomething(HttpServletRequest request, HttpServletResponse response, @PathVariable("id") long id, @RequestParam String objectName);

СЛЕДУЕТ это:

public void deleteSomething(HttpServletRequest request, HttpServletResponse response, @PathVariable("id") long id, @RequestParam("objectName") String objectName);

Посмотрите разницу? Это отсутствует ( "objectName" ) после @RequestParam. Он компилируется и работает нормально в STS, но при его непосредственном развертывании на сервере tomcat он не работает.

Спасибо @fmelan за сообщение выше, потому что он помог нам найти эту маленькую опечатку.

Это не похоже на то, что это была ваша проблема, но для тех, кто застрял, пытаясь понять, почему "DELETE" не поддерживается...