Сервлет возвращает "HTTP-статус 404 Запрошенный ресурс (/ сервлет) недоступен"

У меня есть HTML-форма в файле JSP в моем WebContent/jsps папка. У меня есть класс сервлетов servlet.java в моем пакете по умолчанию в src папка. В моем web.xml это отображается как /servlet,

Я пробовал несколько URL в action атрибут HTML-формы:

<form action="/servlet">
<form action="/servlet.java">
<form action="/src/servlet.java">
<form action="../servlet.java">

Но ничего из этого не работает. Все они продолжают возвращать ошибку HTTP 404, как показано ниже в Tomcat 6/7/8:

HTTP-статус 404 - / сервлет

Описание: Запрошенный ресурс (/ сервлет) недоступен.

Или как показано ниже в Tomcat 8.5 / 9:

HTTP-статус 404 - не найден

Сообщение: / сервлет

Описание. Исходный сервер не нашел текущего представления для целевого ресурса или не хочет раскрыть, что он существует.

Почему это не работает?

19 ответов

Поместите класс сервлета в package

Прежде всего, поместите класс сервлета в Java package, Вы должны всегда помещать общедоступные Java-классы в пакет, в противном случае они невидимы для классов, которые находятся в пакете, таких как сам сервер. Таким образом вы устраняете потенциальные проблемы, связанные с окружающей средой. Сервлеты без пакетов работают только в определенных комбинациях Tomcat+JDK, и на это никогда не следует полагаться.

В случае "простого" проекта IDE, класс должен быть помещен в его структуру пакета в папке "Java Resources", а не в "WebContent", это для веб-файлов, таких как JSP. Ниже приведен пример структуры папок Eclipse Dynamic Web Project по умолчанию, как видно в представлении Navigator:

EclipseProjectName
 |-- src
 |    `-- com
 |         `-- example
 |              `-- YourServlet.java
 |-- WebContent
 |    |-- WEB-INF
 |    |    `-- web.xml
 |    `-- jsps
 |         `-- page.jsp
 :

В случае проекта Maven, класс должен быть помещен в его структуру пакета внутри main/java и, таким образом, не, например, main/resources , это для неклассных файлов. Ниже приведен пример структуры папок проекта веб-приложения Maven по умолчанию, представленного в представлении Eclipse Navigator:

MavenProjectName
 |-- src
 |    `-- main
 |         |-- java
 |         |    `-- com
 |         |         `-- example
 |         |              `-- YourServlet.java
 |         |-- resources
 |         `-- webapp
 |              |-- WEB-INF
 |              |    `-- web.xml
 |              `-- jsps
 |                   `-- page.jsp
 :

Обратите внимание, что /jsps подпапка строго не нужна. Вы даже можете обойтись без него и поместить файл JSP непосредственно в корень webcontent/webapp, но я просто перенял это из вашего вопроса.

Установить URL сервлета в url-pattern

URL-адрес сервлета указывается как "шаблон URL-адреса" отображения сервлета. Это абсолютно не по определению имя класса / имя файла класса сервлета. Шаблон URL должен быть указан как значение @WebServlet аннотаций.

package com.example; // Use a package!

@WebServlet("/servlet") // This is the URL of the servlet.
public class YourServlet extends HttpServlet { // Must be public and extend HttpServlet.
    // ...
}

Если вы хотите поддерживать параметры пути, такие как /servlet/foo/bar затем используйте шаблон URL /servlet/* вместо. См. Также параметры сервлета и пути, такие как /xyz/{value}/test, как отобразить в web.xml?

@WebServlet работает только на Servlet 3.0 или новее

Для того, чтобы использовать @WebServlet, вам нужно только убедиться, что ваш web.xml файл, если таковой имеется (необязательный, начиная с Servlet 3.0), объявляется как соответствующий версии Servlet 3.0+ и, таким образом, не соответствующий, например, версии 2.5 или ниже. Ниже приведен совместимый с Servlet 3.1 (соответствует Tomcat 8+, WildFly 8+, GlassFish 4+ и т. Д.).

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1"
>
    <!-- Config here. -->
</web-app>

Или, если вы еще не используете Servlet 3.0+ (не Tomcat 7 или новее, а Tomcat 6 или старше), удалите @WebServlet аннотаций.

package com.example;

public class YourServlet extends HttpServlet {
    // ...
}

И зарегистрируйте сервлет вместо этого в web.xml как это:

<servlet>
    <servlet-name>yourServlet</servlet-name>
    <servlet-class>com.example.YourServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>yourServlet</servlet-name>
    <url-pattern>/servlet</url-pattern>  <!-- This is the URL of the servlet. -->
</servlet-mapping>

Обратите внимание, что вы не должны использовать оба способа. Используйте либо конфигурацию на основе аннотаций, либо конфигурацию на основе XML. Если у вас есть оба, конфигурация на основе XML будет переопределять конфигурацию на основе аннотаций.

Проверка сборки / развертывания

В случае, если вы используете инструмент сборки, такой как Eclipse и / или Maven, вы должны быть абсолютно уверены, что файл класса скомпилированного сервлета находится в его структуре пакета в /WEB-INF/classes папка созданного файла WAR. В случае package com.example; public class YourServlet, он должен быть расположен в /WEB-INF/classes/com/example/YourServlet.class, В противном случае вы столкнетесь в случае @WebServlet также ошибка 404, или в случае <servlet> ошибка HTTP 500, как показано ниже:

HTTP Status 500

Ошибка создания экземпляра класса сервлета com.example.YourServlet

И найти в журнале сервера java.lang.ClassNotFoundException: com.example.YourServlet с последующим java.lang.NoClassDefFoundError: com.example.YourServlet, в свою очередь, следуют javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet,

Простой способ проверить, правильно ли скомпилирован сервлет и помещен в classpath, - позволить инструменту сборки создать файл WAR (например, проект rightclick, Export> WAR-файл в Eclipse), а затем проверить его содержимое с помощью инструмента ZIP. Если класс сервлета отсутствует в /WEB-INF/classes, тогда проект неправильно настроен или некоторые значения по умолчанию для конфигурации IDE/ проекта были ошибочно возвращены (например, Project > Build Automatics отключен в Eclipse). Если у вас нет подсказки, лучше всего начать с нуля и не трогать настройки конфигурации IDE/ проекта по умолчанию.

Тестирование сервлета индивидуально

При условии, что сервер работает localhost:8080 и что WAR успешно развернут по контекстному пути /contextname (по умолчанию используется имя проекта IDE, чувствительно к регистру!), и сервлет не потерпел неудачу при инициализации (считывает журналы сервера для любых сообщений развертывания / успеха / неудачи сервлета, а также фактический путь к контексту и отображение сервлета), затем сервлет с Шаблон URL /servlet доступен на http://localhost:8080/contextname/servlet,

Вы можете просто ввести его прямо в адресной строке браузера, чтобы проверить его. Если это doGet() правильно переопределен и реализован, тогда вы увидите его вывод в браузере. Или если у вас нет doGet() или если он неправильно звонит super.doGet() затем будет отображена ошибка " HTTP 405: HTTP-метод GET не поддерживается этим URL-адресом " (что все же лучше, чем 404, поскольку 405 является доказательством того, что сам сервлет действительно найден).

Переопределение service() Это плохая практика, если только вы не переизобретаете инфраструктуру MVC - что очень маловероятно, если вы только начинаете с сервлетов и не знаете, как описать проблему, описанную в текущем вопросе;) См. также веб-приложения Design Patterns.

В любом случае, если сервлет уже возвращает 404 при тестировании в невидимом режиме, попытаться использовать HTML-форму совершенно бессмысленно. Логически, поэтому также совершенно бессмысленно включать любую форму HTML в вопросы о 404 ошибках из сервлета.

Ссылка на URL сервлета из HTML

После того, как вы убедились, что сервлет работает нормально при индивидуальном вызове, вы можете перейти к HTML. Что касается вашей конкретной проблемы с формой HTML, то <form action> значение должно быть действительным URL. То же самое относится и к <a href>, Вы должны понимать, как работают абсолютные / относительные URL. Вы знаете, URL - это веб-адрес, который вы можете ввести / увидеть в адресной строке веб-браузера. Если вы указываете относительный URL-адрес как действие формы, т.е. без http:// схема, то она становится относительно текущего URL, как вы видите в адресной строке вашего веб-браузера. Таким образом, это абсолютно не относится к расположению файла JSP/HTML в структуре папок WAR сервера, как кажется многим начинающим.

Итак, предполагая, что страница JSP с HTML-формой открывается http://localhost:8080/contextname/jsps/page.jsp, и вам нужно подчиниться сервлету, расположенному в http://localhost:8080/contextname/servlet Вот несколько случаев (обратите внимание, что вы можете смело заменить <form action> с <a href> Вот):

  • Форма действия отправляется на URL с косой чертой.

    <form action="/servlet">
    

    Ведущий слеш / делает URL-адрес относительно домена, поэтому форма будет

    http://localhost:8080/servlet
    

    Но это, вероятно, приведет к 404, поскольку это в неправильном контексте.


  • Форма действия отправляется на URL без косой черты.

    <form action="servlet">
    

    Это делает URL относительно текущей папки текущего URL, таким образом, форма будет отправлена

    http://localhost:8080/contextname/jsps/servlet
    

    Но это, скорее всего, приведет к 404, поскольку он находится не в той папке.


  • Форма действия отправляет URL-адрес, который идет на одну папку вверх.

    <form action="../servlet">
    

    Это будет на одну папку вверх (точно так же, как в пути к файловой системе локального диска!), Поэтому форма будет отправлена ​​на

    http://localhost:8080/contextname/servlet
    

    Этот должен работать!


  • Канонический подход, однако, заключается в том, чтобы сделать URL-адрес относительным к домену, чтобы вам не нужно было снова исправлять URL-адреса, когда вы перемещаете файлы JSP в другую папку.

    <form action="${pageContext.request.contextPath}/servlet">
    

    Это сгенерирует

    <form action="/contextname/servlet">
    

    Который таким образом всегда будет отправлять на правильный URL.


Используйте прямые кавычки в HTML

Вы должны быть абсолютно уверены, что вы используете прямые кавычки в таких атрибутах HTML, как action="..." или же action='...' и, таким образом, не вьющиеся кавычки, как action=”...” или же action=’...’, Фигурные кавычки не поддерживаются в HTML, и они просто станут частью значения.

Смотрите также:

Другие случаи ошибки HTTP Status 404:

Сценарий № 1: вы случайно повторно развернуты из командной строки, когда Tomcat уже запущен.

Краткий ответ: остановите Tomcat, удалите целевую папку, пакет mvn, затем повторно разверните


Сценарий № 2: request.getRequestDispatcher (" MIS_SPELLED_FILE_NAME.jsp")

Краткий ответ: Проверьте правильность написания имени файла, убедитесь, что регистр правильный.


Сценарий № 3: Исключения класса не найдены (ответ приведен здесь, потому что: Вопрос № 17982240) ( java.lang.ClassNot FoundException для сервлета в tomcat с затмением) (помечен как дубликат и направил меня сюда)

Краткий ответ #3.1: в файле web.xml указан неверный путь к пакету в теге класса сервлетов.

Краткий ответ № 3.2: у файла Java неверный оператор импорта.


Ниже приведена дополнительная информация для сценария № 1:


1: Остановить Tomcat

  • Вариант 1: через CTRL+C в терминале.
  • Вариант 2: (терминал закрыт, когда кот еще работает)
  • ------------ 2.1: нажмите: Windows + R -> введите: " services.msc "
  • ------------ 2.2: найдите "Apache Tomcat #.# Tomcat#" в столбце "Имя" списка.
  • ------------ 2.3: Правый клик -> " Стоп "

2. Удалите "целевую" папку. (MvN Clean не поможет вам здесь)

3: пакет mvn

4: YOUR_DEPLOYMENT_COMMAND_HERE

(Шахта: java -jar target/dependency/webapp-runner.jar --port 5190 target/*. War)

Full Back Story:


Случайно открыл новое окно git-bash и попытался развернуть.war-файл для моего проекта heroku через:

java -jar target / dependency / webapp-runner.jar --port 5190 target / *. war

После неудачного развертывания я понял, что у меня открыто два окна git-bash, и не использовал CTLR+C, чтобы остановить предыдущее развертывание.

Меня встретили:

HTTP Status 404 - Not Found Тип отчета о состоянии

Сообщение /if-student-test.jsp

Описание Исходный сервер не нашел текущего представления для целевого ресурса или не хочет раскрыть, что он существует.

Apache Tomcat / 8.5.31

Ниже приведена дополнительная информация для сценария № 3:


СЦЕНАРИЙ 3.1: неверный путь к пакету сервлет-класса в вашем файле web.xml.

Он должен соответствовать заявлению пакета в верхней части вашего класса сервлетов Java.

Файл: my_stuff / MyClass.java:

   package my_stuff;

Файл: PRJ_ROOT / src / main / webapp / WEB-INF / web.xml

   <servlet-class>
   my_stuff.MyClass
   </servlet-class>

СЦЕНАРИЙ 3.2:

Вы поместили неправильный оператор " package " в верхней части своего файла myClass.java.

Например:

Файл находится в папке " / my_stuff "

Вы по ошибке пишете:

package com.my_stuff

Это сложно, потому что:

1: сборка maven (пакет mvn) не будет сообщать об ошибках здесь.

2: строка класса сервлета в web.xml может иметь ПРАВИЛЬНЫЙ путь к пакету. Например:

<servlet-class>
my_stuff.MyClass
</servlet-class>

Используемые стеки: Блокнот ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10:

Если вы используете IntelliJ, вот что исправило для меня:

Заходим в конфигурацию Tomcat:

Конфигурация> Вкладка "Развертывание"

Прокрутите вниз и добавьте / в раскрывающийся список "Контекст приложения"

Убедитесь, что вы ввели правильное сопоставление URL-адресов, как указано в Web.xml.

Например:

В web.xml ваше объявление сервлета может быть:

<servlet>
        <servlet-name>ControllerA</servlet-name>
        <servlet-class>PackageName.ControllerA</servlet-class>
</servlet>

<servlet-mapping>
        <servlet-name>ControllerA</servlet-name>
        <url-pattern>/theController</url-pattern>
</servlet-mapping>

Что делает этот фрагмент <url-pattern>/theController</url-pattern>задаст имя, которое будет использоваться для вызова сервлета из внешнего интерфейса (например: форма) через URL-адрес. Поэтому, когда вы ссылаетесь на сервлет во внешнем интерфейсе, чтобы гарантировать, что запрос идет к сервлету "ControllerA", он должен ссылаться на указанный шаблон URL-адреса "theController" из формы.

например:

<form action="theController" method="POST">
</form>

Я была такая же проблема. Пробовал все это, но не помогло. Мне удалось решить эту проблему, добавив теги элементов в начало и конец файла xml. Я оставлю свой XML-файл ниже для справки.

      <?xml version="1.0" encoding="UTF-8"?>

<element>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
     
<servlet> 
    <servlet-name>InsertServlet</servlet-name> 
    <servlet-class>com.worklog.InsertServlet</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>InsertServlet</servlet-name> 
    <url-pattern>/insert</url-pattern> 
</servlet-mapping>

</web-app>

</element>

Моя проблема заключалась в том, что в моем методе отсутствовала аннотация @RequestBody. После добавления аннотации я больше не получил исключение 404.

Сделайте следующие два шага. Надеюсь, это решит проблему "404 not found" на сервере tomcat при разработке приложения java-сервлета.

Шаг 1: Right click on the server(in the server explorer tab)->Properties->Switch Location from workspace metadata to tomcat server

Шаг 2: Double Click on the server(in the server explorer tab)->Select Use tomcat installation option inside server location menu

Я удалил старую веб-библиотеку, такую ​​как библиотеки Spring Framework. И построить новый путь библиотек. Тогда это работает.

Решение для HTTP Status 404 в среде IDE NetBeans: щелкните правой кнопкой мыши свой проект и перейдите к свойствам проекта, затем нажмите "Выполнить" и введите относительный URL-адрес проекта, например index.jsp,

  1. Project-> Свойства
  2. Нажмите на Run
  3. Относительный URL:/index.jsp (выберите корневой URL вашего проекта)

Отображение в web.xml - это то, что я сделал:-

  1. Если для новой программы создан другой пакет, мы должны упомянуть:-

packagename.filename между открытием и закрытием тега класса сервлета в XML-файле.

  1. Если вы сопоставляете свои файлы в xml, и они не работают или не показывают ошибок, прокомментируйте строку аннотации кода в соответствующих файлах.

Оба метода не работают друг с другом, поэтому либо я использую метод аннотации файлов, упомянутых при создании сервлета, либо способ сопоставления, затем я удаляю или комментирую строку аннотации. Например:

 <servlet>
   <servlet-name>s1</servlet-name>
   <servlet-class>performance.FirstServ</servlet-class>
   </servlet>    
   
   <servlet-mapping>
   <servlet-name>s1</servlet-name>
   <url-pattern>/FirstServ</url-pattern>
   </servlet-mapping>
   
   <servlet>
   <servlet-name>s2</servlet-name>
   <servlet-class>performance.SecondServ</servlet-class>
   </servlet>
   
   <servlet-mapping>
   <servlet-name>s2</servlet-name>
   <url-pattern>/SecondServ</url-pattern>
   </servlet-mapping>

Комментирование строки аннотации кода в соответствующем файле, если отображение в xml выполнено.

//@WebServlet("/FirstServ")
//@WebServlet("/SecondServ")

У меня сработало исправление (если вы используете Maven): щелкните правой кнопкой мыши свой проект, Maven -> Обновить проект. Это может привести к другой ошибке с JDK и другими библиотеками (в моем случае с соединителем MySQL), но как только вы их исправите, ваша исходная проблема должна быть исправлена!

Если вы хотите открыть сервлет с помощью javascript без использования кнопки "форма" и "отправить", вот следующий код:

var button = document.getElementById("<<button-id>>");
button.addEventListener("click", function() {
  window.location.href= "<<full-servlet-path>>" (eg. http://localhost:8086/xyz/servlet)
});

Ключ:

1) button-id: тег 'id', который вы присваиваете своей кнопке в файле html/jsp.

2) полный путь сервлета: путь, который отображается в браузере, когда вы запускаете только сервлет.

Прежде всего, запустите свою IDE от имени администратора. После этого щелкните правой кнопкой мыши папку проекта -> Project Facets и убедитесь, что версия Java установлена ​​правильно. На моем ПК. (Для примера 1.8) Теперь должно работать.

Не запускайте просто свой сервер, например Wildfly, с помощью cmd. Он должен быть запущен в среде IDE и теперь перейти по URL-адресу локального хоста. Пример: http://localhost:8080/HelloWorldServlet/HelloWorld

Старая ветка, но поскольку я не нашел ее в другом месте, вот еще одна возможность:

Если вы используете servlet-api 3.0+, то ваш web.xml НЕ должен включать metadata-complete="true" атрибут

Это говорит tomcat для отображения сервлетов, используя данные, приведенные в web.xml вместо использования @WebServlet аннотаций.

Если здесь есть кто-то, кто использует MySQL и считает, что код работал накануне, а теперь нет, то я думаю, вы должны открыть MySQL CLI или MySQL Workbench и просто один раз подключиться к базе данных. После подключения база данных также подключается к Java-приложению. Раньше я получал ошибку Hibernate Dialect, в которой говорилось, что что-то не так с com.mysql.jdbc.Driver. Я думаю, что у MySQL на некоторых компьютерах проблемы с запуском. Это решило для меня.

Если вы студент и плохо знакомы с Java, возможно, возникла проблема с вашим файлом web.xml.

  1. Попробуйте удалить файл web.xml.
  2. Во-вторых, проверьте, правильно ли установлены переменные вашего пути.
  3. Перезагрузите сервер Tomcat или ваш компьютер.

Ваша проблема обязательно будет решена.

Я тоже столкнулся с этой проблемой, я получал 404 при доступе к шаблону URL, который, как я знал, был связан с сервлетом. Причина в том, что у меня было 2 сервлета с их @WebServlet name набор параметров в виде той же строки.

@WebServlet(name = "ServletName", urlPatterns = {"/path"})
public class ServletName extends HttpServlet {}
@WebServlet(name = "ServletName", urlPatterns = {"/other-path"})
public class OtherServletName extends HttpServlet {}

Оба nameпараметры такие же. Если вы используете параметр name, убедитесь, что они уникальны по сравнению со всеми другими сервлетами в вашем приложении.

У меня была такая же проблема. Я разрабатывал REST API на основе mvc, где не было явной конфигурации или файлов html. API использовал Swagger для создания пользовательского интерфейса. Проблема началась, когда я представил Swagger версии 3.0.0. Я вернулся к Swagger "2.9.2". Это решило мою проблему.

      <!-- Swagger -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>

Пожалуйста, проверьте, что корень контекста не может быть пустым.

Если вы используете затмение:
щелкните правой кнопкой мыши, выберите свойства, затем настройки веб-проекта. Проверьте, что корень контекста не может быть пустым

Другие вопросы по тегам