Servlet trả về “Trạng thái HTTP 404 Tài nguyên được yêu cầu (/ servlet) không khả dụng”


95

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

Tôi đã thử một số URL trong 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ố đó hoạt động. Tất cả chúng đều tiếp 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 khả dụng.

Hoặc như bên dưới 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 tài nguyên đó tồn tại

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

Câu trả lời:


127

Đặ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 đặ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 sẽ ẩn đối với các lớp nằm trong một gói, chẳng hạn như chính máy chủ. Bằng cách này, bạn loại bỏ các vấn đề tiềm ẩn về môi trường cụ thể. Các servlet khô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ờ được dựa vào.

Trong trường hợp là một dự án IDE "thuần túy", 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 "WebContent", điều này dành cho các tệp web như JSP. Dưới đây là 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 dạng xem Bộ điều hướng :

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 phải được đặt ở bên trong cấu trúc gói của nó main/java và do đó không ví dụ main/resources, đây là cho các tập tin không theo class . Dưới đây là 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 dạng xem Bộ điều hướng 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 hoàn toàn 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 webcontent / webapp root, nhưng tôi chỉ giải quyết vấn đề này từ câu hỏi của bạn.

Đặt URL của servlet trong url-pattern

URL của servlet được chỉ định là "mẫu URL" của ánh xạ servlet. Nó hoàn toàn không phải 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ư /servlet/foo/bar, 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, cách ánh xạ trong web.xml?

@WebServlet chỉ hoạt động trên Servlet 3.0 hoặc mới hơ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ó (nó là tùy chọn kể từ Servlet 3.0), được khai báo là phù hợp với phiên bản Servlet 3.0+ và do đó không tuân theo phiên bản 2.5 hoặc thấp hơn . Dưới đây là một tương thích Servlet 4.0 (phù hợp với Tomcat 9+, WildFly 11+, Payara 5+, v.v.).

<?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"
>
    <!-- Config here. -->
</web-app>

Hoặc, trong trường hợp bạn chưa sử dụng Servlet 3.0+ (ví dụ: Tomcat 6 trở lên), hãy xóa @WebServletchú thích.

package com.example;

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

Và đăng ký servlet thay thế trong 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>

Do đó, lưu ý rằng 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 hoàn toàn đảm bảo 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 của 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ẽ gặp phải trường hợp @WebServletlỗi 404 hoặc trong trường hợp <servlet>lỗi HTTP 500 như bên dưới:

Trạng thái HTTP 500

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

Và tìm trong nhật ký máy chủ a java.lang.ClassNotFoundException: com.example.YourServlet, tiếp theo là a java.lang.NoClassDefFoundError: com.example.YourServlet, lần lượt theo sau là 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 chính xác và được đặt trong classpath hay không là để công cụ xây dựng tạo ra tệp WAR (ví dụ: dự án nhấp chuột phải, 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 thiếu lớp servlet /WEB-INF/classeshoặc nếu quá trình xuất gây ra lỗi, thì dự án được định cấu hình sai hoặc một số mặc định cấu hình IDE / dự án đã bị hoàn nguyên một cách nhầm lẫn (ví dụ: Dự án> Xây dựng Tự động đã bị tắt trong Eclipse).

Bạn cũng cần đảm bảo rằng biểu tượng dự án không có chữ thập đỏ chỉ ra lỗi xây dựng. Bạn có thể tìm lỗi chính xác trong dạng xem Vấn đề ( Cửa sổ> Hiển thị Dạng xem> Khác ... ). Thông thường thông báo lỗi là tốt Googlable. Trong trường hợp bạn không có manh 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. Trong trường hợp bạn đang sử dụng Eclipse, bạn có thể tìm hướng dẫn trong Làm cách nào để nhập API javax.servlet vào dự án Eclipse của tôi?

Kiểm tra servlet riêng lẻ

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 thất bại (đọc nhật ký máy chủ cho bất kỳ triển khai nào / 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), thì một servlet với mẫu URL của /servletcó sẵn tại http://localhost:8080/contextname/servlet.

Bạn chỉ có thể nhập trực tiếp vào thanh địa chỉ của trình duyệt để kiểm tra nó một cách ẩn ý. Nếu nó doGet()được ghi đè và triển khai đúng cách, 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ì URL này không hỗ trợ " HTTP 405: HTTP method GET " sẽ được hiển thị (vẫn tốt hơn 404 vì 405 là bằng chứng cho thấy servlet bản thân nó thực sự được tìm thấy).

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

Bất kể, nếu servlet đã trả về 404 khi được kiểm tra một cách vô hình, thì việc thử với một biểu mẫu HTML thay thế là hoàn toàn vô nghĩa. Về mặt logic, do đó cũng hoàn toàn vô nghĩa nếu đư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 của 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ệ. Điều tương tự cũng áp dụng 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, URL là một địa chỉ web mà bạn có thể nhập / xem trong thanh địa chỉ của trình duyệt web. Nếu bạn đang chỉ định một URL tương đối làm hành động biểu mẫu, tức là không có http://lược đồ, thì nó sẽ tương đối với URL hiện tại như bạn thấy trong thanh địa chỉ của trình duyệt web của mình. Do đó, nó hoàn toàn không liên quan đến vị trí tệp 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 dường như nghĩ.

Vì vậy, giả sử rằng trang JSP có biểu mẫu HTML được mở bởi http://localhost:8080/contextname/jsps/page.jspvà bạn cần gửi đến một servlet nằm trong đó http://localhost:8080/contextname/servlet, đây là một số trường hợp (lưu ý rằng bạn có thể thay thế một cách an toàn <form action>bằng <a href>đây):

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

    <form action="/servlet">

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

    http://localhost:8080/servlet

    Nhưng điều này có thể sẽ dẫn đến 404 vì nó ở trong ngữ 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 ở đầu.

    <form action="servlet">

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

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

    Nhưng điều này có thể sẽ dẫn đến 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">

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

    http://localhost:8080/contextname/servlet

    Cái này phải hoạt động!


  • Tuy nhiên, cách tiếp cận chuẩn là tạo tên miền URL tương đối để bạn không cần sửa lại các URL khi bạn tình cờ di chuyển các tệp JSP sang 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 gửi đến đú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='...'và do đó không phải 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
web-app version = "3.1" bằng cách sử dụng glassfish, tôi có thể kiểm tra từng servlet của mình rất tốt khi tôi có ánh xạ trong 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?
SallyRothroat 14/03/18

1
Điều đó có thể xảy ra nếu bạn bao gồm các thư viện servlet 2.5 hoặc cũ hơ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.
BalusC

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

4

Tình huống # 1: Bạn vô tình triển khai lại từ dòng lệnh trong khi tomcat đang chạy .

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


Tình huống # 2: request.getRequestDispatcher (" MIS_SPELLED_FILE_NAME .jsp")

Ngắn Trả lời: Kiểm tra tên file chính tả , hãy chắc chắn trường hợp là đúng.


Tình huống # 3: Ngoại lệ Không tìm thấy Lớp (Câu trả lời được đặt ở đây vì: Câu hỏi # 17982240) ( java.lang.ClassNotFoundException cho servlet trong tomcat với eclipse ) (đượ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 khác cho Kịch bản số 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 clean sẽ không giúp bạn ở đây)

3: gói mvn

4: YOUR_DEPLOYMENT_COMMAND_HERE

(Của tôi: java -jar target / dependency / webapp-runner.jar --port 5190 target / *. War)

Toàn bộ câu chuyện trở lại:


Tình cờ 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 qua:

java -jar target / dependency / webapp-runner.jar --port 5190 target / *. war

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

Tôi đã gặp:

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

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.

Apache Tomcat / 8.5.31

Dưới đây là các chi tiết khác cho Kịch bản số 3:


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

Nó sẽ PHÙ HỢP với câu lệnh gói ở đầu lớp servlet java của bạn.

Tệp: my_stuff / MyClass.java :

   package my_stuff;

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

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

KỊCH BẢN 3.2:

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

Ví dụ:

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

Bạn viết nhầm:

package com.my_stuff

Điều này rất khó vì:

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

2: Dòng cấp độ servlet trong web.xml có thể có đường dẫn gói ĐÚNG. Ví dụ:

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

Ngăn xếp được sử dụng: Notepad ++ + GitBash + Maven + Heroku Web App Runner + Tomcat9 + Windows10 :


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

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à chuyển đế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ư index.jsp.

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

nhập mô tả hình ảnh ở đây


0

Vấn đề của tôi là phương pháp của tôi 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 nữa.


0

Thực hiện hai bước sau. Tôi hy vọng, nó sẽ giải quyết được vấn đề "404 not found" 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

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


0

Một chủ đề cũ, nhưng vì tôi không tìm thấy nó ở nơi khác, đây là một khả năng nữa:

Nếu bạn đang sử dụng servlet-api 3.0+ , thì web.xml của bạn KHÔNG được bao gồm metadata-complete="true"thuộc tính

nhập mô tả hình ảnh ở đây

Điều này yêu cầu tomcat ánh xạ các servlet bằng cách sử dụng dữ liệu được cung cấp web.xmlthay vì sử dụng @WebServletchú thích.


0

Trước hết, hãy chạy IDE của bạn với tư cách là Quản trị viên. Sau đó, nhấp chuột phải vào thư mục dự án -> Project Facets và đảm bảo rằng Phiên bản Java được đặt chính xác. Trên PC của tôi. (Ví dụ 1.8) Bây giờ nó sẽ hoạt động.

Đừng chỉ khởi động máy chủ của bạn, ví dụ như Wildfly, bằng cách sử dụng cmd. Nó phải được khởi chạy trong IDE và bây giờ hãy truy cập URL máy chủ cục bộ của bạn. Ví dụ: http: // localhost: 8080 / HelloWorldServlet / HelloWorld


0

Cách khắc phục phù hợp với tôi là (nếu bạn đang sử dụng Maven): Nhấp chuột phải vào dự án của bạn, Maven -> Cập nhật dự án. Điều này có thể cung cấp cho bạn một số lỗi khác với JDK và các Thư viện khác (trong trường hợp của tôi là trình kết nối MySQL), nhưng khi bạn sửa chúng, sự cố ban đầu của bạn sẽ được khắc phục!


0

Nếu bạn muốn mở một servlet bằng javascript mà không sử dụng nút 'biểu mẫu' và 'gửi', đây là đoạn mã sau:

var button = document.getElementById("<<button-id>>");
button.addEventListener("click", function() {
  window.location.href= "<<full-servlet-path>>" (eg. http://localhost:8086/xyz/servlet)
});

Chìa khóa:

1) button-id: Thẻ 'id' mà bạn cấp cho nút trong tệp html / jsp của bạn.

2) full-servlet-path: Đường dẫn hiển thị trong trình duyệt khi bạn chạy một mình servlet


0

Ánh xạ trong web.xml là những gì tôi đã làm: -

  1. Nếu có một gói khác được tạo cho chương trình mới thì chúng ta phải đề cập đến: -

packagename.filename giữa việc mở và đóng thẻ lớp servlet trong tệp xml.

  1. Nếu bạn đang ánh xạ các tệp của mình trong xml và chúng không hoạt động hoặc hiển thị lỗi, hãy nhận xét về dòng mã chú thích trong các tệp tương ứng.

Cả hai phương pháp không hoạt động với nhau, vì vậy tôi sử dụng phương pháp chú thích của các tệp được đề cập khi chúng tôi tạo servlet hoặc cách ánh xạ, sau đó tôi xóa hoặc nhận xét dòng chú thích. Ví dụ:

 <servlet>
   <servlet-name>s1</servlet-name>
   <servlet-class>performance.FirstServ</servlet-class>
   </servlet>    
   
   <servlet-mapping>
   <servlet-name>s1</servlet-name>
   <url-pattern>/FirstServ</url-pattern>
   </servlet-mapping>
   
   <servlet>
   <servlet-name>s2</servlet-name>
   <servlet-class>performance.SecondServ</servlet-class>
   </servlet>
   
   <servlet-mapping>
   <servlet-name>s2</servlet-name>
   <url-pattern>/SecondServ</url-pattern>
   </servlet-mapping>

Nhận xét dòng mã chú thích trong tệp tương ứng, nếu ánh xạ trong xml được thực hiện.

//@WebServlet("/FirstServ")
//@WebServlet("/SecondServ")

-1

Vui lòng kiểm tra gốc ngữ cảnh không được để trống .

Nếu bạn đang sử dụng eclipse:
nhấp chuột phải , chọn thuộc tính , sau đó cài đặt dự án web . Kiểm tra gốc ngữ cảnh không được để trống

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.