Servlet возвращает "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 - не найдено

Сообщение:/servlet

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

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

Ответы

Ответ 1

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

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

В случае "простого" проекта IDE класс должен быть помещен в структуру пакета внутри папки "Ресурсы Java" и, следовательно, не "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 Webapp по умолчанию, как показано в представлении Eclipse Navigator:

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

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

Установить 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, если он есть (он по умолчанию с сервлета 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 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.

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

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

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

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

Переопределение service() - это плохая практика, если вы не изобретаете структуру MVC и— что очень маловероятно, если вы только начинаете работу с сервлетами и не знаете, что связано с проблемой, описанной в текущем вопросе;) См. также Веб-приложения с шаблонами проектирования.

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

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

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

Ответ 2

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

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


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

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


Сценарий № 3: Исключения класса не найдены (ответ приведен здесь, потому что: Вопрос № 17982240) (java.lang.ClassNotFoundException для сервлета в 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: Удалить папку "target". (mvn clean вам здесь не поможет)

3: пакет mvn

4: YOUR_DEPLOYMENT_COMMAND_HERE

(Mine: 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>

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

Ответ 3

В Web.xml вам нужно настроить следующим образом

<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.example.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

в вашей HTML-форме, мы должны сделать это

<form action="login" method = "post" class="form-signin" role="form" >

надеюсь, что это сработает

Ответ 4

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

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

enter image description here

Ответ 5

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

enter image description here

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

Ответ 9

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

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

Ответ 10

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

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