ใส่คลาส servlet ใน package
ครั้งแรกของทั้งหมดใส่ชั้นเซิร์ฟเล็ตใน package
Java คุณควรเสมอใส่เรียน Java Reuseable สาธารณชนในแพคเกจมิฉะนั้นพวกเขาจะมองไม่เห็นจากการเรียนที่อยู่ในแพคเกจเช่นเซิร์ฟเวอร์เอง วิธีนี้ช่วยขจัดปัญหาเฉพาะสภาพแวดล้อมที่อาจเกิดขึ้นได้ servlets แบบไม่ใช้แพ็กเกจทำงานเฉพาะในชุดค่าผสม Tomcat + JDK ที่เฉพาะเจาะจงและสิ่งนี้ไม่ควรพึ่งพา
ในกรณีของโปรเจ็กต์ IDE "ธรรมดา" คลาสจะต้องถูกวางไว้ในโครงสร้างแพ็กเกจภายในโฟลเดอร์ "Java Resources" และไม่ใช่ "WebContent" ซึ่งเป็นไฟล์เว็บเช่น JSP ด้านล่างนี้เป็นตัวอย่างโครงสร้างโฟลเดอร์ของ Eclipse Dynamic Web Project ที่เป็นค่าเริ่มต้นดังที่เห็นในมุมมองNavigator :
EclipseProjectName
|-- src
| `-- com
| `-- example
| `-- YourServlet.java
|-- WebContent
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
ในกรณีของโครงการ Maven ชั้นจะต้องมีการวางไว้ในโครงสร้างภายในแพคเกจของมันmain/java
จึงไม่ได้เช่นmain/resources
นี้เป็นไฟล์ที่ไม่ใช่ระดับ ด้านล่างนี้เป็นตัวอย่างโครงสร้างโฟลเดอร์ของโปรเจ็กต์ Maven webapp เริ่มต้นดังที่เห็นในมุมมองNavigatorของ Eclipse :
MavenProjectName
|-- src
| `-- main
| |-- java
| | `-- com
| | `-- example
| | `-- YourServlet.java
| |-- resources
| `-- webapp
| |-- WEB-INF
| | `-- web.xml
| `-- jsps
| `-- page.jsp
:
โปรดทราบว่า/jsps
โฟลเดอร์ย่อยไม่จำเป็นอย่างยิ่ง คุณสามารถทำได้โดยไม่ต้องใช้มันและวางไฟล์ JSP โดยตรงใน webcontent / webapp root แต่ฉันแค่รับเรื่องนี้จากคำถามของคุณ
ตั้งค่า servlet URL ใน url-pattern
URL ของ servlet ถูกระบุเป็น "รูปแบบ URL" ของการแมป servlet ไม่ใช่อย่างแน่นอนตามนิยามชื่อคลาส / ชื่อไฟล์ของคลาส servlet รูปแบบ URL จะถูกระบุเป็นค่าของ@WebServlet
คำอธิบายประกอบ
package com.example;
@WebServlet("/servlet")
public class YourServlet extends HttpServlet {
}
ในกรณีที่คุณต้องการสนับสนุนพารามิเตอร์เส้นทางเช่น/servlet/foo/bar
ให้ใช้รูปแบบ URL /servlet/*
แทน โปรดดูพารามิเตอร์ Servlet และ path เช่น / 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 {
}
และลงทะเบียน servlet แทนใน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 คุณต้องตรวจสอบให้แน่ใจว่าไฟล์คลาส servlet ที่คอมไพล์นั้นอยู่ในโครงสร้างแพ็คเกจใน/WEB-INF/classes
โฟลเดอร์ของไฟล์ WAR ที่สร้างขึ้น ในกรณีนี้package com.example; public class YourServlet
จะต้องอยู่ใน/WEB-INF/classes/com/example/YourServlet.class
. มิฉะนั้นคุณจะต้องเผชิญกับ@WebServlet
ข้อผิดพลาด 404 หรือในกรณีของ<servlet>
ข้อผิดพลาด HTTP 500 ดังต่อไปนี้:
สถานะ HTTP 500
เกิดข้อผิดพลาดในการสร้างอินสแตนซ์คลาส servlet 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
.
วิธีง่ายๆในการตรวจสอบว่า servlet ถูกคอมไพล์และวางไว้ใน classpath อย่างถูกต้องหรือไม่คือการปล่อยให้เครื่องมือ build สร้างไฟล์ WAR (เช่น rightclick project, Export> WAR fileใน Eclipse) จากนั้นตรวจสอบเนื้อหาด้วยเครื่องมือ ZIP หากไม่มีคลาส servlet ใน/WEB-INF/classes
หรือหากการเอ็กซ์พอร์ตทำให้เกิดข้อผิดพลาดแสดงว่าโปรเจ็กต์ถูกกำหนดค่าไม่ดีหรือค่าดีฟอลต์คอนฟิกูเรชัน IDE / โปรเจ็กต์บางอย่างถูกยกเลิกโดยไม่ถูกต้อง (เช่นProject> Build Automaticallyถูกปิดใช้งานใน Eclipse)
นอกจากนี้คุณต้องตรวจสอบให้แน่ใจว่าไอคอนโครงการไม่มีเครื่องหมายกากบาทสีแดงที่ระบุข้อผิดพลาดของการสร้าง คุณสามารถค้นหาข้อผิดพลาดที่แน่นอนได้ใน มุมมองปัญหา ( หน้าต่าง> แสดงมุมมอง> อื่น ๆ ... ) โดยปกติแล้วข้อความแสดงข้อผิดพลาดนั้นใช้ได้กับ Googlable ในกรณีที่คุณไม่มีเบาะแสวิธีที่ดีที่สุดคือเริ่มต้นใหม่ตั้งแต่ต้นและอย่าแตะค่าเริ่มต้นการกำหนดค่า IDE / โครงการ ในกรณีที่คุณใช้ Eclipse คุณสามารถดูคำแนะนำได้ในฉันจะนำเข้า javax.servlet API ในโครงการ Eclipse ของฉันได้อย่างไร
ทดสอบ servlet ทีละรายการ
โดยมีเงื่อนไขว่าเซิร์ฟเวอร์รันlocalhost:8080
และ WAR ถูกปรับใช้บนพา ธ บริบทสำเร็จ/contextname
(ซึ่งดีฟอลต์ชื่อโปรเจ็กต์ IDE, case sensitive!) และ servlet ไม่ล้มเหลวในการเตรียมใช้งาน (อ่านบันทึกเซิร์ฟเวอร์สำหรับการปรับใช้ / ใด ๆ ความสำเร็จ servlet / ล้มเหลวข้อความและเส้นทางบริบทและการทำแผนที่เซิร์ฟเล็ตที่เกิดขึ้นจริง) แล้วเซิร์ฟเล็ตที่มีรูปแบบ URL ของที่มีอยู่ใน/servlet
http://localhost:8080/contextname/servlet
คุณสามารถป้อนลงในแถบที่อยู่ของเบราว์เซอร์ได้โดยตรงเพื่อทดสอบไม่ถูกต้อง หากdoGet()
ถูกลบล้างและใช้งานอย่างถูกต้องคุณจะเห็นผลลัพธ์ในเบราว์เซอร์ หรือถ้าคุณไม่มีdoGet()
หรือหากเรียกไม่ถูกต้องข้อผิดพลาดsuper.doGet()
" HTTP 405: HTTP method GET ไม่ได้รับการสนับสนุนโดย URL นี้ " จะแสดงขึ้น (ซึ่งยังดีกว่า 404 เนื่องจาก 405 เป็นหลักฐานว่า servlet พบตัวมันเอง)
เอาชนะservice()
คือการปฏิบัติที่ไม่ดีถ้าคุณกำลังปฏิรูปกรอบ MVC - ซึ่งไม่น่ามากถ้าคุณเพิ่งเริ่มออกมาพร้อมกับ Servlets และ clueless เป็นปัญหาที่อธิบายไว้ในคำถามปัจจุบัน;) ดูเพิ่มเติมการออกแบบการใช้งานรูปแบบเว็บเบส
ไม่ว่า servlet จะส่งคืน 404 ไปแล้วเมื่อทดสอบโดยไม่ถูกต้องแล้วก็ไม่มีจุดหมายโดยสิ้นเชิงที่จะลองใช้รูปแบบ HTML แทน ดังนั้นจึงไม่มีจุดหมายโดยสิ้นเชิงที่จะรวมรูปแบบ HTML ใด ๆ ในคำถามเกี่ยวกับข้อผิดพลาด 404 จาก servlet
อ้างอิง servlet URL จาก HTML
เมื่อคุณตรวจสอบแล้วว่า servlet ทำงานได้ดีเมื่อเรียกใช้ทีละรายการคุณสามารถเลื่อนไปยัง HTML ได้ สำหรับปัญหาที่เป็นรูปธรรมของคุณกับรูปแบบ HTML <form action>
ค่าจะต้องเป็น URL ที่ถูกต้อง <a href>
เช่นเดียวกับ คุณต้องเข้าใจว่า URL สัมบูรณ์ / สัมพัทธ์ทำงานอย่างไร คุณทราบดีว่า URL คือที่อยู่เว็บที่คุณสามารถป้อน / ดูได้ในแถบที่อยู่ของเว็บเบราว์เซอร์ หากคุณกำลังระบุ URL สัมพัทธ์เป็นการดำเนินการในรูปแบบเช่นโดยไม่มีhttp://
โครงร่างURL นั้นจะสัมพันธ์กับ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: