Tempatkan kelas servlet di a package
Pertama-tama, letakkan kelas servlet di Java package
. Anda harus selalu meletakkan kelas Java yang dapat digunakan kembali secara publik dalam sebuah paket, jika tidak, kelas tersebut tidak akan terlihat oleh kelas yang ada dalam paket, seperti server itu sendiri. Dengan cara ini Anda mengeliminasi potensi masalah khusus lingkungan. Servlet tanpa paket hanya berfungsi dalam kombinasi Tomcat + JDK tertentu dan ini tidak boleh diandalkan.
Dalam kasus proyek IDE "biasa", kelas harus ditempatkan dalam struktur paketnya di dalam folder "Sumber Daya Java" dan bukan "Konten Web", ini untuk file web seperti JSP. Di bawah ini adalah contoh struktur folder dari Proyek Web Dinamis Eclipse default seperti yang terlihat pada tampilan Navigator :
EclipseProjectName
|-- src
| `-- com
| `-- example
| `-- YourServlet.java
|-- WebContent
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
Dalam kasus proyek Maven, kelas perlu ditempatkan dalam struktur paketnya di dalam main/java
dan bukan misalnya main/resources
, ini untuk file non-kelas . Di bawah ini adalah contoh struktur folder dari proyek webapp Maven default seperti yang terlihat di Eclipse tampilan Navigator :
MavenProjectName
|-- src
| `-- main
| |-- java
| | `-- com
| | `-- example
| | `-- YourServlet.java
| |-- resources
| `-- webapp
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
Perhatikan bahwa /jsps
subfolder tidak sepenuhnya diperlukan. Anda bahkan dapat melakukannya tanpa itu dan meletakkan file JSP langsung di webcontent / webapp root, tetapi saya hanya mengambil alih ini dari pertanyaan Anda.
Setel URL servlet di url-pattern
URL servlet ditentukan sebagai "pola URL" dari pemetaan servlet. Ini sama sekali bukan per definisi nama kelas / nama file dari kelas servlet. Pola URL harus ditentukan sebagai nilai @WebServlet
anotasi.
package com.example;
@WebServlet("/servlet")
public class YourServlet extends HttpServlet {
}
Jika Anda ingin mendukung parameter jalur seperti /servlet/foo/bar
, gunakan pola URL /servlet/*
sebagai gantinya. Lihat juga Servlet dan parameter jalur seperti / xyz / {value} / test, bagaimana cara memetakan di web.xml?
@WebServlet
hanya berfungsi pada Servlet 3.0 atau yang lebih baru
Untuk menggunakan @WebServlet
, Anda hanya perlu memastikan bahwa web.xml
file Anda , jika ada (opsional sejak Servlet 3.0), dinyatakan sesuai dengan versi Servlet 3.0+ dan dengan demikian tidak sesuai misalnya versi 2.5 atau lebih rendah . Di bawah ini adalah yang kompatibel dengan Servlet 4.0 (yang cocok dengan Tomcat 9+, WildFly 11+, Payara 5+, dll).
<?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>
Atau, jika Anda belum menggunakan Servlet 3.0+ (mis. Tomcat 6 atau lebih lama), hapus @WebServlet
anotasi tersebut.
package com.example;
public class YourServlet extends HttpServlet {
}
Dan daftarkan servlet sebagai gantinya web.xml
seperti ini:
<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>
Perhatikan dengan demikian bahwa Anda tidak boleh menggunakan kedua cara tersebut. Gunakan konfigurasi berbasis anotasi atau konfigurasi berbasis XML. Jika Anda memiliki keduanya, konfigurasi berbasis XML akan menggantikan konfigurasi berbasis anotasi.
Memverifikasi build / deployment
Jika Anda menggunakan alat build seperti Eclipse dan / atau Maven, Anda harus benar-benar memastikan bahwa file kelas servlet yang dikompilasi berada dalam struktur paketnya dalam /WEB-INF/classes
folder file WAR yang dihasilkan. Dalam kasus package com.example; public class YourServlet
, itu harus ditempatkan di /WEB-INF/classes/com/example/YourServlet.class
. Jika tidak, Anda akan menghadapi jika @WebServlet
juga terjadi kesalahan 404, atau dalam kasus <servlet>
kesalahan HTTP 500 seperti di bawah ini:
Status HTTP 500
Kesalahan membuat instance kelas servlet com.example.YourServlet
Dan temukan di log server a java.lang.ClassNotFoundException: com.example.YourServlet
, diikuti oleh a java.lang.NoClassDefFoundError: com.example.YourServlet
, pada gilirannya diikuti oleh javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet
.
Cara mudah untuk memverifikasi apakah servlet dikompilasi dan ditempatkan dengan benar di classpath adalah dengan membiarkan alat build menghasilkan file WAR (misalnya proyek klik kanan, Ekspor> file WAR di Eclipse) dan kemudian periksa isinya dengan alat ZIP. Jika kelas servlet tidak ada di /WEB-INF/classes
, atau jika ekspor menyebabkan kesalahan, maka proyek tersebut dikonfigurasi dengan buruk atau beberapa default konfigurasi IDE / proyek telah dikembalikan secara keliru (mis. Project> Build Automatically telah dinonaktifkan di Eclipse).
Anda juga perlu memastikan bahwa ikon proyek tidak memiliki tanda silang merah yang menunjukkan kesalahan versi. Anda dapat menemukan kesalahan yang tepat dalam tampilan Masalah ( Window> Show View> Other ... ). Biasanya pesan kesalahan baik-baik saja di Google. Jika Anda tidak tahu, yang terbaik adalah memulai ulang dari awal dan jangan menyentuh default konfigurasi IDE / proyek apa pun. Jika Anda menggunakan Eclipse, Anda dapat menemukan petunjuk di Bagaimana cara mengimpor API javax.servlet di proyek Eclipse saya?
Menguji servlet secara individual
Asalkan server berjalan localhost:8080
, dan WAR berhasil diterapkan pada jalur konteks /contextname
(yang default ke nama proyek IDE, case sensitive!), Dan servlet tidak gagal inisialisasi (baca log server untuk penerapan / pesan keberhasilan / kegagalan servlet dan jalur konteks aktual serta pemetaan servlet), maka servlet dengan pola URL /servlet
tersedia di http://localhost:8080/contextname/servlet
.
Anda cukup memasukkannya langsung di bilah alamat browser untuk mengujinya secara individual. Jika doGet()
itu diganti dan diterapkan dengan benar, maka Anda akan melihat outputnya di browser. Atau jika Anda tidak memiliki doGet()
atau jika panggilan salah super.doGet()
, maka " HTTP 405: metode HTTP GET tidak didukung oleh URL ini " akan ditampilkan (yang masih lebih baik daripada 404 karena 405 adalah bukti bahwa servlet sendiri sebenarnya ditemukan).
Mengganti service()
adalah praktik yang buruk, kecuali Anda menemukan kembali kerangka kerja MVC - yang sangat tidak mungkin jika Anda baru memulai dengan servlet dan tidak mengerti masalah yang dijelaskan dalam pertanyaan saat ini;) Lihat juga Pola Desain aplikasi berbasis web .
Terlepas dari itu, jika servlet sudah mengembalikan 404 saat diuji secara invidivual, maka tidak ada gunanya mencoba dengan bentuk HTML sebagai gantinya. Oleh karena itu, secara logis, itu juga sama sekali tidak ada gunanya untuk memasukkan bentuk HTML dalam pertanyaan tentang kesalahan 404 dari servlet.
Mereferensikan URL servlet dari HTML
Setelah Anda memverifikasi bahwa servlet berfungsi dengan baik saat dipanggil secara individual, Anda dapat melanjutkan ke HTML. Untuk masalah konkret Anda dengan formulir HTML, <form action>
nilainya harus berupa URL yang valid. Hal yang sama berlaku untuk <a href>
. Anda perlu memahami cara kerja URL absolut / relatif. Anda tahu, URL adalah alamat web seperti yang Anda masukkan / lihat di bilah alamat browser web. Jika Anda menentukan URL relatif sebagai tindakan formulir, yaitu tanpa http://
skema, maka URL tersebut menjadi relatif terhadap URL saat ini seperti yang Anda lihat di bilah alamat browser web Anda. Jadi ini sama sekali tidak relatif terhadap lokasi file JSP / HTML dalam struktur folder WAR server seperti yang dipikirkan banyak pemula.
Jadi, dengan asumsi bahwa halaman JSP dengan bentuk HTML dibuka oleh http://localhost:8080/contextname/jsps/page.jsp
, dan Anda perlu mengirimkan ke servlet yang terletak di http://localhost:8080/contextname/servlet
, berikut adalah beberapa kasus (perhatikan bahwa Anda dapat menggantinya <form action>
dengan aman di <a href>
sini):
Tindakan formulir dikirimkan ke URL dengan garis miring di depan.
<form action="/servlet">
Garis miring di depan /
membuat URL relatif terhadap domain, sehingga formulir akan dikirim
http://localhost:8080/servlet
Tetapi ini kemungkinan akan menghasilkan 404 karena berada dalam konteks yang salah.
Tindakan formulir dikirimkan ke URL tanpa garis miring di awal.
<form action="servlet">
Ini membuat URL relatif ke folder saat ini dari URL saat ini, sehingga formulir akan dikirim
http://localhost:8080/contextname/jsps/servlet
Tetapi ini kemungkinan akan menghasilkan 404 karena berada di folder yang salah.
Tindakan formulir dikirimkan ke URL yang naik satu folder.
<form action="../servlet">
Ini akan naik satu folder ke atas (persis seperti di jalur sistem file disk lokal!), Sehingga formulir akan dikirim ke
http://localhost:8080/contextname/servlet
Yang ini harus berhasil!
Pendekatan kanonik, bagaimanapun, adalah membuat URL domain-relative sehingga Anda tidak perlu memperbaiki URL sekali lagi ketika Anda kebetulan memindahkan file JSP ke dalam folder lain.
<form action="${pageContext.request.contextPath}/servlet">
Ini akan menghasilkan
<form action="/contextname/servlet">
Yang dengan demikian akan selalu mengirimkan ke URL yang benar.
Gunakan tanda kutip lurus dalam HTML
Anda harus benar-benar memastikan bahwa Anda menggunakan tanda kutip lurus dalam atribut HTML seperti action="..."
atau action='...'
dan dengan demikian bukan tanda kutip keriting seperti action=”...”
atau action=’...’
. Tanda kutip keriting tidak didukung dalam HTML dan hanya akan menjadi bagian dari nilai. Hati-hati saat menyalin potongan kode dari blog! Beberapa mesin blog, terutama Wordpress, diketahui secara default menggunakan apa yang disebut "tanda kutip pintar" yang dengan demikian juga merusak tanda kutip dalam cuplikan kode dengan cara ini. Di sisi lain, alih-alih menyalin-tempel kode, coba ketikkan sendiri kode itu. Keuntungan tambahan dari benar-benar mendapatkan kode melalui otak dan jari Anda adalah bahwa itu akan membuat Anda mengingat dan memahami kode jauh lebih baik dalam jangka panjang dan juga membuat Anda menjadi pengembang yang lebih baik.
Lihat juga:
Kasus lain dari kesalahan HTTP Status 404: