Поместите класс сервлета в 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;
@WebServlet("/servlet")
public class YourServlet extends 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"
>
</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>
</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: