Помістіть клас сервлету в a package
Перш за все, помістіть клас сервлетів в Java package
. Завжди слід поміщати загальнодоступні багаторазові класи Java у пакет, інакше вони невидимі для класів, що знаходяться в пакеті, наприклад, самого сервера. Таким чином ви усуваєте потенційні проблеми, пов'язані з навколишнім середовищем. Безпакетні сервлети працюють лише у певних комбінаціях Tomcat + JDK, і на це ніколи не можна покладатися.
У випадку "простого" проекту IDE клас потрібно розмістити у структурі пакету всередині папки "Ресурси Java", а не "WebContent", це стосується веб-файлів, таких як JSP. Нижче наведено приклад структури папок за замовчуванням Динамічного веб-проекту Eclipse, як показано в поданні Навігатора :
EclipseProjectName
|-- src
| `-- com
| `-- example
| `-- YourServlet.java
|-- WebContent
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
У разі проекту Maven клас потрібно розмістити всередині його структури пакета, main/java
і, отже, не, наприклад main/resources
, це стосується некласових файлів . Нижче наведено приклад структури папок за замовчуванням проекту веб-програми Maven, як показано в поданні Навігатора Eclipse :
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;
@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 або нижче . Нижче наведено сумісний сервлет 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
, за яким слідує a java.lang.NoClassDefFoundError: com.example.YourServlet
, у свою чергу слідує javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet
.
Найпростіший спосіб перевірити, чи правильно скомпільований та розміщений сервлет у шляху до класу, - це дозволити інструменту побудови створити файл WAR (наприклад, проект клацання правою кнопкою миші, Експорт> Файл WAR у Eclipse), а потім перевірити його вміст за допомогою інструмента ZIP. Якщо клас сервлета відсутній /WEB-INF/classes
, або якщо експорт спричиняє помилку, проект погано налаштований або деякі типові налаштування IDE / конфігурації проекту були помилково скасовані (наприклад, Проект> Автоматична побудова вимкнена в 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: