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

99

У меня есть 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 - / сервлет

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

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

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

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

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

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

Pongahead
источник

Ответы:

131

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

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

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

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

В случае проекта Maven класс должен быть помещен в его структуру пакета внутри main/java и, следовательно, не, например main/resources, для файлов, не являющихся классами . Ниже приведен пример структуры папок проекта Maven webapp по умолчанию, как видно в представлении 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» отображения сервлета. Это абсолютно не по определению имя класса / имя файла класса сервлета. В качестве значения @WebServletаннотации указывается шаблон URL .

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, используйте /servlet/*вместо них шаблон URL . См. Также параметры сервлета и пути, такие как / xyz / {value} / test, как отобразить в web.xml?

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

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

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
    version="4.0"
>
    <!-- Config here. -->
</web-app>

Или, если вы еще не используете Servlet 3.0+ (например, 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 500

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

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

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

Также необходимо убедиться, что на значке проекта нет красного креста, указывающего на ошибку сборки. Вы можете найти точную ошибку в представлении « Проблемы» ( Окно> Показать представление> Другое ... ). Обычно сообщение об ошибке нормально Googlable. Если вы понятия не имеете, лучше всего перезапустить с нуля и не трогать какие-либо параметры конфигурации IDE / проекта по умолчанию. Если вы используете Eclipse, вы можете найти инструкции в разделе Как импортировать API javax.servlet в мой проект Eclipse?

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

При условии, что сервер работает 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, и они просто станут частью значения. Будьте осторожны при копировании фрагментов кода из блогов! Известно, что некоторые движки блогов, в частности Wordpress, по умолчанию используют так называемые «умные кавычки», которые таким образом также искажают кавычки в фрагментах кода. С другой стороны, вместо того, чтобы копировать и вставлять код, попробуйте просто набрать код самостоятельно. Дополнительное преимущество фактического прохождения кода через ваш мозг и пальцы состоит в том, что это поможет вам запомнить и понять код намного лучше в долгосрочной перспективе, а также сделает вас лучшим разработчиком.

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

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

BalusC
источник
1
web-app version = "3.1" с помощью glassfish, я мог бы протестировать свой сервлет по отдельности, когда у меня было отображение в web.xml И аннотации. Я удалил сопоставление и оставил аннотацию, так как у меня последняя версия, но тогда я получу ошибку 404?
SallyRothroat
1
Это может произойти, если вы включите сервлет 2.5 или более старые библиотеки в само веб-приложение вместо того, чтобы полагаться на целевую среду выполнения, чтобы предоставить библиотеки сервлетов самостоятельно.
BalusC
@xdola: это действительно хрупко, потому что зависит от URI запроса. Просто прочтите ответ, чтобы узнать о своей проблеме и о правильном подходе.
BalusC
4

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

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


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

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


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

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

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


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


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

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

2: Удалить «целевую» папку. (mvn clean здесь вам не поможет)

3: пакет mvn

4: ВАШЕ_РАЗДЕЛЕНИЕ_COMMAND_HERE

(Мой: java -jar target / dependency / webapp-runner.jar --port 5190 target / *. War)

Полная предыстория:


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

java -jar цель / зависимость / webapp-runner.jar --port 5190 цель / *. война

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

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

Статус HTTP 404 - Отчет о состоянии типа не найден

Сообщение /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 :

JMI MADISON
источник
Ваш AppName.war и, следовательно, взорванное имя папки не соответствует ожидаемому имени, например, когда ваш файл war имеет версию как AppName-1.0-SNAPSHOT.war и вы пытаетесь / AppName /.
jla
1

Убедитесь, что вы ввели правильное сопоставление 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>
Лакинду Хевавасам
источник
0

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

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

введите описание изображения здесь

ИЛИ Имон
источник
0

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

THE_DOM
источник
0

Сделайте следующие два шага. Я надеюсь, что это решит проблему «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

Саджал Саха
источник
0

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

пижамы
источник
0

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

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

введите описание изображения здесь

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

Чайтанья
источник
0

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

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

Селби Хузвайо
источник
0

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

Джозеф Чжао
источник
0

Если вы хотите открыть сервлет с помощью 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) полный путь сервлета: путь, который отображается в браузере, когда вы запускаете только сервлет.

matak8s
источник
0

Отображение в 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")
Сидхарт Джайн
источник
0

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

Теджас Нареш Суварна
источник
0

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

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

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

Мудассар Малик
источник
-1

Убедитесь, что корень контекста не может быть пустым .

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

Вием Рахман
источник