72

Tôi có một biểu mẫu HTML trong một tệp tin trong WebContent/jspsthư mục của tôi . Tôi có một lớp servlet servlet.javatrong gói mặc định của mình trong srcthư mục. Trong tôi web.xmlnó được ánh xạ như /servlet.

Tôi đã thử một số URL actionthuộc tính của biểu mẫu HTML:

<form action="/servlet">
<form action="/servlet.java">
<form action="/src/servlet.java">
<form action="../servlet.java">

Nhưng không ai trong số họ làm việc. Tất cả đều liên tục trả về lỗi HTTP 404 như bên dưới trong Tomcat 6/7/8:

Trạng thái HTTP 404 - / servlet

Mô tả : Tài nguyên được yêu cầu (/ servlet) không có sẵn.

Hoặc như dưới đây trong Tomcat 8,5 / 9:

Trạng thái HTTP 404 - Không tìm thấy

Tin nhắn : / servlet

Mô tả : Máy chủ gốc không tìm thấy đại diện hiện tại cho tài nguyên đích hoặc không sẵn sàng tiết lộ rằng một máy chủ tồn tại

Tại sao nó không làm việc?

|
110

Đặt lớp servlet trong một package

Trước hết, đặt lớp servlet trong Java package. Bạn phải luôn luôn đặt các lớp Java có thể sử dụng lại công khai trong một gói, nếu không chúng vô hình với các lớp trong một gói, chẳng hạn như chính máy chủ. Bằng cách này, bạn sẽ loại bỏ các vấn đề môi trường cụ thể tiềm năng. Các gói dịch vụ không đóng gói chỉ hoạt động trong các kết hợp Tomcat + JDK cụ thể và điều này không bao giờ nên được dựa vào.

Trong trường hợp dự án IDE "đơn giản", lớp cần được đặt trong cấu trúc gói của nó bên trong thư mục "Tài nguyên Java" và do đó không phải là "WebContent", đây là cho các tệp web như JSP. Dưới đây là một ví dụ về cấu trúc thư mục của Dự án Web động Eclipse mặc định như được thấy trong khung nhìn Navigator :

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

Trong trường hợp của một dự án Maven, lớp cần được đặt trong cấu trúc gói của nó bên trong main/java và do đó không phải là ví dụ main/resources, đây là cho các tệp không phải là lớp . Dưới đây là một ví dụ về cấu trúc thư mục của dự án ứng dụng web Maven mặc định như được thấy trong khung nhìn Navigator của Eclipse :

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

Lưu ý rằng /jspsthư mục con không thực sự cần thiết. Bạn thậm chí có thể làm mà không cần nó và đặt tệp JSP trực tiếp vào root webcontent / webapp, nhưng tôi chỉ tiếp nhận điều này từ câu hỏi của bạn.

Đặt URL servlet trong url-pattern

URL servlet được chỉ định là "mẫu URL" của ánh xạ servlet. Nó hoàn toàn không theo định nghĩa tên lớp / tên tệp của lớp servlet. Mẫu URL sẽ được chỉ định làm giá trị của @WebServletchú thích.

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.
    // ...
}

Trong trường hợp bạn muốn hỗ trợ các tham số đường dẫn như thế /servlet/foo/bar, thì hãy sử dụng mẫu URL /servlet/*thay thế. Xem thêm Servlet và các tham số đường dẫn như / xyz / {value} / test, làm thế nào để ánh xạ trong web.xml?

@WebServlet chỉ hoạt động trên Servlet 3.0 trở lên

Để sử dụng @WebServlet, bạn chỉ cần đảm bảo rằng web.xmltệp của bạn , nếu có (tùy chọn kể từ Servlet 3.0), được khai báo tuân thủ phiên bản Servlet 3.0+ và do đó không tuân thủ phiên bản 2.5 trở xuống . Dưới đây là một phiên bản tương thích Servlet 3.1 (phù hợp với Tomcat 8+, WildFly 8+, GlassFish 4+, v.v.).

<?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>

Hoặc, trong trường hợp bạn chưa có trên Servlet 3.0+ (không phải Tomcat 7 hoặc mới hơn, mà là Tomcat 6 trở lên), sau đó xóa @WebServletchú thích.

package com.example;

public class YourServlet extends HttpServlet {
    // ...
}

Và đăng ký servlet thay vì web.xmlnhư thế này:

<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>

Lưu ý do đó bạn không nên sử dụng cả hai cách. Sử dụng cấu hình dựa trên chú thích hoặc cấu hình dựa trên XML. Khi bạn có cả hai, thì cấu hình dựa trên XML sẽ ghi đè cấu hình dựa trên chú thích.

Xác minh việc xây dựng / triển khai

Trong trường hợp bạn đang sử dụng một công cụ xây dựng như Eclipse và / hoặc Maven, thì bạn cần chắc chắn rằng tệp lớp servlet đã biên dịch nằm trong cấu trúc gói của nó trong /WEB-INF/classesthư mục của tệp WAR được tạo. Trong trường hợp package com.example; public class YourServlet, nó phải được đặt tại /WEB-INF/classes/com/example/YourServlet.class. Nếu không, bạn sẽ phải đối mặt trong trường hợp @WebServletcũng có lỗi 404 hoặc trong trường hợp <servlet>có lỗi HTTP 500 như dưới đây:

Trạng thái HTTP 500

Lỗi khởi tạo lớp servlet com.example.YourServlet

Và tìm trong máy chủ đăng nhập a java.lang.ClassNotFoundException: com.example.YourServlet, theo sau là a java.lang.NoClassDefFoundError: com.example.YourServlet, lần lượt theo sau javax.servlet.ServletException: Error instantiating servlet class com.example.YourServlet.

Một cách dễ dàng để xác minh xem servlet có được biên dịch và đặt chính xác trong đường dẫn lớp hay không là để công cụ xây dựng tạo ra một tệp WAR (ví dụ: dự án rightclick, xuất> tệp WAR trong Eclipse) và sau đó kiểm tra nội dung của nó bằng công cụ ZIP. Nếu lớp servlet bị thiếu /WEB-INF/classes, thì dự án bị cấu hình kém hoặc một số mặc định cấu hình IDE / dự án đã bị hoàn nguyên nhầm (ví dụ: Project> Build Automatic đã bị vô hiệu hóa trong Eclipse). Trong trường hợp bạn không có đầu mối, tốt nhất là khởi động lại từ đầu và không chạm vào bất kỳ mặc định cấu hình IDE / dự án nào.

Kiểm tra từng servlet

Với điều kiện là máy chủ chạy localhost:8080và WAR được triển khai thành công trên đường dẫn ngữ cảnh /contextname(mặc định là tên dự án IDE, phân biệt chữ hoa chữ thường!) Và servlet đã không khởi tạo được nó (đọc nhật ký máy chủ cho bất kỳ triển khai / Các thông báo thành công / thất bại của servlet và đường dẫn ngữ cảnh thực tế và ánh xạ servlet), sau đó một servlet có mẫu URL /servletcó sẵn tại http://localhost:8080/contextname/servlet.

Bạn chỉ có thể nhập thẳng vào thanh địa chỉ của trình duyệt để kiểm tra nó một cách vô tình. Nếu nó doGet()được ghi đè và thực hiện đúng, thì bạn sẽ thấy đầu ra của nó trong trình duyệt. Hoặc nếu bạn không có bất kỳ doGet()hoặc nếu nó gọi không chính xác super.doGet(), thì lỗi " HTTP 405: HTTP phương thức GET không được hỗ trợ bởi URL này " sẽ được hiển thị (vẫn tốt hơn 404 vì 405 là bằng chứng cho thấy servlet chính nó thực sự được tìm thấy).

Ghi đè service()là một thực tiễn tồi, trừ khi bạn phát minh lại khung MVC - điều này rất khó xảy ra nếu bạn chỉ mới bắt đầu với các máy chủ và không biết gì về vấn đề được mô tả trong câu hỏi hiện tại;) Xem thêm Thiết kế ứng dụng dựa trên web .

Bất kể, nếu servlet đã trả về 404 khi được kiểm tra một cách vô tình, thì việc thử với biểu mẫu HTML hoàn toàn vô nghĩa. Về mặt logic, do đó, hoàn toàn vô nghĩa khi đưa bất kỳ biểu mẫu HTML nào vào các câu hỏi về lỗi 404 từ một servlet.

Tham chiếu URL servlet từ HTML

Khi bạn đã xác minh rằng servlet hoạt động tốt khi được gọi riêng lẻ, thì bạn có thể chuyển sang HTML. Đối với vấn đề cụ thể của bạn với biểu mẫu HTML, <form action>giá trị cần phải là một URL hợp lệ. Áp dụng tương tự cho <a href>. Bạn cần hiểu cách URL tuyệt đối / tương đối hoạt động. Bạn biết đấy, một URL là một địa chỉ web mà bạn có thể nhập / xem trong thanh địa chỉ của webbrowser. Nếu bạn chỉ định một URL tương đối dưới dạng hành động biểu mẫu, tức là không có http://lược đồ, thì nó sẽ trở thành tương đối với URL hiện tại như bạn thấy trong thanh địa chỉ của webbrowser. Do đó, nó hoàn toàn không liên quan đến vị trí tệp tin JSP / HTML trong cấu trúc thư mục WAR của máy chủ như nhiều người mới bắt đầu nghĩ.

Vì vậy, giả định rằng các trang web với các hình thức HTML JSP được mở ra bởi http://localhost:8080/contextname/jsps/page.jsp, và bạn cần phải nộp cho một servlet nằm trong http://localhost:8080/contextname/servlet, sau đây là một vài trường hợp (lưu ý rằng bạn có thể yên tâm thay thế <form action>với <a href>ở đây):

  • Hành động biểu mẫu gửi đến một URL với dấu gạch chéo hàng đầu.

    <form action="/servlet">

    Dấu gạch chéo hàng đầu /làm cho URL liên quan đến tên miền, do đó biểu mẫu sẽ được gửi tới

    http://localhost:8080/servlet

    Nhưng điều này có thể sẽ dẫn đến một 404 vì nó trong bối cảnh sai.


  • Hành động biểu mẫu gửi đến một URL mà không có dấu gạch chéo hàng đầu.

    <form action="servlet">

    Điều này làm cho URL liên quan đến thư mục hiện tại của URL hiện tại, do đó biểu mẫu sẽ được gửi tới

    http://localhost:8080/contextname/jsps/servlet

    Nhưng điều này có thể sẽ dẫn đến một 404 vì nó nằm trong thư mục sai.


  • Hành động biểu mẫu gửi đến một URL đi lên một thư mục.

    <form action="../servlet">

    Điều này sẽ đi lên một thư mục (chính xác như trong đường dẫn hệ thống tệp đĩa cục bộ!), Do đó biểu mẫu sẽ được gửi tới

    http://localhost:8080/contextname/servlet

    Cái này phải làm việc!


  • Tuy nhiên, cách tiếp cận chính tắc là làm cho tên miền URL trở nên tương đối để bạn không cần sửa URL một lần nữa khi bạn tình cờ di chuyển các tệp JSP xung quanh vào một thư mục khác.

    <form action="${pageContext.request.contextPath}/servlet">

    Điều này sẽ tạo ra

    <form action="/contextname/servlet">

    Do đó sẽ luôn luôn gửi đúng URL.


Sử dụng dấu ngoặc kép trong HTML

Bạn cần chắc chắn rằng bạn đang sử dụng dấu ngoặc kép thẳng trong các thuộc tính HTML như action="..."hoặc action='...'do đó không phải là dấu ngoặc kép như action=”...”hoặc action=’...’. Dấu ngoặc kép không được hỗ trợ trong HTML và chúng sẽ đơn giản trở thành một phần của giá trị.

Xem thêm:

Các trường hợp khác của lỗi Trạng thái HTTP 404:

|
  • 1

    phiên bản ứng dụng web = "3.1" bằng cách sử dụng cá thủy tinh, tôi có thể kiểm tra riêng servlet của mình chỉ tốt khi tôi có ánh xạ trong tệp web.xml VÀ chú thích. Tôi đã xóa ánh xạ và để lại chú thích vì tôi có phiên bản mới nhất nhưng sau đó tôi sẽ gặp lỗi 404?

    – Hoàng Kim Hương 13:54:56 14/03/2018
  • 1

    Điều đó có thể xảy ra nếu bạn bao gồm các thư viện servlet 2.5 trở lên trong chính ứng dụng web thay vì dựa vào thời gian chạy đích để tự cung cấp các thư viện servlet.

    – Bùi Phương Giang 14:19:13 14/03/2018
  • 1

    <form action="../servlet">không hoạt động trong trường hợp của tôi ...

    – Trịnh Nguyên Hồng 17:48:53 06/04/2019
  • 1

    @xdola: Nó thực sự dễ vỡ vì nó phụ thuộc vào URI yêu cầu. Chỉ cần đọc câu trả lời cho lời giải thích về vấn đề của bạn và cách tiếp cận đúng là gì.

    – Hoàng Việt Hồng 11:17:46 08/04/2019
1

Kịch bản # 1: Bạn tình cờ triển khai lại từ dòng lệnh trong khi tomcat đang chạy .

Trả lời ngắn: Dừng Tomcat, xóa thư mục đích , gói mvn, sau đó triển khai lại


Kịch bản # 2: request.getRequestDispatcher (" MISinksELLED_FILE_NAME .jsp")

Trả lời ngắn: Kiểm tra chính tả tên tập tin , đảm bảo trường hợp chính xác.


Kịch bản # 3: Ngoại lệ không tìm thấy lớp (Trả lời được đặt ở đây vì: Câu hỏi # 17982240) ( java.lang.ClassNotFoundException cho servlet trong tomcat với nhật thực ) (được đánh dấu là trùng lặp và hướng dẫn tôi đến đây)

Câu trả lời ngắn # 3.1: web.xml có đường dẫn gói sai trong thẻ lớp servlet.

Câu trả lời ngắn # 3.2: tệp java có câu lệnh nhập sai.


Dưới đây là thông tin chi tiết cho Kịch bản # 1:


1: Dừng Tomcat

  • Tùy chọn 1: Qua CTRL + C trong thiết bị đầu cuối.
  • Tùy chọn 2: (thiết bị đầu cuối đóng trong khi tomcat vẫn chạy)
  • ------------ 2.1: nhấn: Windows + R -> gõ: " services.msc "
  • ------------ 2.2: Tìm "Apache Tomcat #. # Tomcat #" trong cột Tên của danh sách.
  • ------------ 2.3: Nhấp chuột phải -> " dừng "

2: Xóa thư mục "đích". (mvn sạch sẽ không giúp bạn ở đây)

3: gói mvn

4: Your_DEPLOYMENT_COMMAND_HERE

(Của tôi: java -jar đích / phụ thuộc / webapp-runner.jar - cổng 5190 đích / *. War)

Câu chuyện đầy đủ trở lại:


Vô tình mở một cửa sổ git-bash mới và cố gắng triển khai tệp .war cho dự án heroku của tôi thông qua:

java -jar đích / phụ thuộc / webapp-runner.jar - cổng 5190 đích / *. war

Sau khi thất bại trong việc triển khai, tôi nhận ra rằng tôi đã mở hai cửa sổ git-bash và không sử dụng CTLR + C để dừng việc triển khai trước đó .

Tôi đã được gặp:

Trạng thái HTTP 404 - Không tìm thấy Báo cáo trạng thái loại

Tin nhắn /if-student-test.jsp

Mô tả Máy chủ gốc không tìm thấy đại diện hiện tại cho tài nguyên đích hoặc không sẵn sàng tiết lộ rằng tài nguyên đó tồn tại.

Mèo Tom Apache / 8.5.31

Dưới đây là thông tin chi tiết cho Kịch bản # 3:


SCENARIO 3.1: Đường dẫn gói lớp servlet bị sai trong tệp web.xml của bạn.

Nó nên MATCH câu lệnh gói ở đầu lớp java servlet của bạn.

Tệp: my_ ware / MyClass.java :

   package my_stuff;

Tệp: PRJ_ROOT / src / main / webapp / WEB-INF / web.xml

   <servlet-class>
   my_stuff.MyClass
   </servlet-class>

LỊCH SỬ 3.2:

Bạn đặt câu lệnh " gói " sai ở đầu tệp myClass.java của bạn.

Ví dụ:

Tệp nằm trong thư mục : " / my_ ware "

Bạn viết nhầm:

package com.my_stuff

Điều này là khó khăn vì:

1: Bản dựng maven (gói mvn) sẽ không báo cáo bất kỳ lỗi nào ở đây.

2: dòng lớp servlet trong web.xml có thể có đường dẫn gói CORRECT. Ví dụ:

<servlet-class>
my_stuff.MyClass
</servlet-class>

Ngăn xếp được sử dụng: Notepad ++ + GitBash + Maven + Trình chạy ứng dụng web Heroku + Tomcat9 + Windows10 :

|
  • 1

    AppName.war của bạn và do đó, tên thư mục đã phát nổ không khớp với tên dự kiến ​​của bạn, ví dụ: khi tệp chiến tranh của bạn được phiên bản như AppName-1.0-SNAPSHOT.war và bạn đang thử / AppName /.

    – Dương Lam Giang 23:41:38 30/10/2018
0

Tôi đã xóa thư viện web cũ, đó là các thư viện khung mùa xuân. Và xây dựng một con đường mới của các thư viện. Sau đó, nó hoạt động.

|
0

Làm hai bước sau. Tôi hy vọng, nó sẽ giải quyết vấn đề "404 không tìm thấy" trong máy chủ tomcat trong quá trình phát triển ứng dụng java servlet.

Bước 1: Right click on the server(in the server explorer tab)->Properties->Switch Location from workspace metadata to tomcat server

Bước 2: Double Click on the server(in the server explorer tab)->Select Use tomcat installation option inside server location menu

|
0

Vấn đề của tôi là phương pháp của tôi bị thiếu chú thích @RequestBody. Sau khi thêm chú thích, tôi không còn nhận được ngoại lệ 404.

|
0

Giải pháp cho HTTP Status 404trong NetBeans IDE: Nhấp chuột phải vào dự án của bạn và đi đến thuộc tính dự án của bạn, sau đó nhấp vào chạy, sau đó nhập URL tương đối của dự án của bạn như thế nào index.jsp.

  1. Dự án-> Thuộc tính
  2. Bấm vào Chạy
  3. URL tương đối: /index.jsp (Chọn URL gốc dự án của bạn)

|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.