บทนำ
คุณควรใช้doGet()
เมื่อคุณต้องการที่จะตัดในHTTP GET ร้องขอ คุณควรใช้doPost()
เมื่อคุณต้องการที่จะสกัดกั้นในการร้องขอ HTTP POST นั่นคือทั้งหมด อย่าโอนพอร์ตหนึ่งไปยังอีกเครื่องหนึ่งหรือในทางกลับกัน (เช่นในprocessRequest()
วิธีสร้างอัตโนมัติที่โชคร้ายของ Netbeans ) สิ่งนี้ไม่สมเหตุสมผล
รับ
โดยปกติ HTTP GET คำขอidempotent กล่าวคือคุณจะได้รับผลลัพธ์เดียวกันทุกครั้งที่คุณดำเนินการตามคำขอ (ออกจากการอนุญาต / การรับรองความถูกต้องและลักษณะของหน้าเว็บที่คำนึงถึงเวลา - ผลการค้นหาข่าวล่าสุด ฯลฯ - การพิจารณาจากภายนอก) เราสามารถพูดคุยเกี่ยวกับคำขอที่คั่นหน้าได้ การคลิกลิงก์คลิกบุ๊กมาร์กป้อน URL ดิบในแถบที่อยู่ของเบราว์เซอร์ ฯลฯ ทั้งหมดจะเริ่มการร้องขอ HTTP GET หาก Servlet กำลังฟัง URL ที่เป็นปัญหาระบบdoGet()
จะเรียกวิธีการนั้น โดยปกติจะใช้เพื่อประมวลผลคำขอล่วงหน้า ได้แก่ การทำธุรกิจบางอย่างก่อนที่จะนำเสนอเอาต์พุต HTML จาก JSP เช่นการรวบรวมข้อมูลเพื่อแสดงในตาราง
@WebServlet("/products")
public class ProductsServlet extends HttpServlet {
@EJB
private ProductService productService;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Product> products = productService.list();
request.setAttribute("products", products); // Will be available as ${products} in JSP
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}
}
<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td><a href="product?id=${product.id}">detail</a></td>
</tr>
</c:forEach>
</table>
นอกจากนี้ลิงก์ดู / แก้ไขรายละเอียดดังที่แสดงในคอลัมน์สุดท้ายด้านบนมักจะไม่ปรากฏ
@WebServlet("/product")
public class ProductServlet extends HttpServlet {
@EJB
private ProductService productService;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Product product = productService.find(request.getParameter("id"));
request.setAttribute("product", product); // Will be available as ${product} in JSP
request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
}
}
<dl>
<dt>ID</dt>
<dd>${product.id}</dd>
<dt>Name</dt>
<dd>${product.name}</dd>
<dt>Description</dt>
<dd>${product.description}</dd>
<dt>Price</dt>
<dd>${product.price}</dd>
<dt>Image</dt>
<dd><img src="productImage?id=${product.id}" /></dd>
</dl>
โพสต์
คำขอ HTTP POST ไม่ใช่สิ่งที่จำเป็น หาก enduser ส่งแบบฟอร์ม POST บน URL ล่วงหน้าซึ่งยังไม่ได้ทำการเปลี่ยนเส้นทางแสดงว่า URL นั้นไม่จำเป็นต้องบุ๊กมาร์ก ข้อมูลแบบฟอร์มที่ส่งจะไม่แสดงใน URL การคัดลอก URL ไปยังหน้าต่าง / แท็บใหม่ของเบราว์เซอร์อาจไม่จำเป็นต้องให้ผลลัพธ์เหมือนกับหลังการส่งแบบฟอร์ม จากนั้น URL ดังกล่าวจะไม่สามารถบุ๊กมาร์กได้ หาก Servlet กำลังฟัง URL ที่เป็นปัญหาระบบdoPost()
จะเรียกมัน โดยปกติจะใช้เพื่อประมวลผลคำขอ ได้แก่ การรวบรวมข้อมูลจากรูปแบบ HTML ที่ส่งมาและทำธุรกิจบางอย่างด้วย (การแปลงการตรวจสอบความถูกต้องการบันทึกในฐานข้อมูล ฯลฯ ) ในที่สุดผลลัพธ์จะแสดงเป็น HTML จากหน้า JSP ที่ส่งต่อ
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="login">
<span class="error">${error}</span>
</form>
... ซึ่งสามารถใช้ร่วมกับ Servlet ชิ้นนี้ได้:
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@EJB
private UserService userService;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect("home");
}
else {
request.setAttribute("error", "Unknown user, please try again");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
คุณจะเห็นว่าถ้าUser
พบใน DB (เช่นชื่อผู้ใช้และรหัสผ่านถูกต้อง) User
จะถูกใส่ในขอบเขตเซสชัน (เช่น "เข้าสู่ระบบ") และ servlet จะเปลี่ยนเส้นทางไปยังหน้าหลักบางหน้า (ตัวอย่างนี้ไปที่http://example.com/contextname/home
) อื่น ๆ มันจะตั้งข้อผิดพลาดและส่งต่อการร้องขอกลับไปที่หน้า JSP ${error}
เดียวกันเพื่อให้ได้รับข้อความแสดงโดย
คุณสามารถ "ซ่อน" login.jsp
ในได้หากจำเป็น/WEB-INF/login.jsp
เพื่อให้ผู้ใช้สามารถเข้าถึงได้โดย servlet เท่านั้น http://example.com/contextname/login
นี้ช่วยให้การทำความสะอาดของ URL สิ่งที่คุณต้องทำคือเพิ่ม a doGet()
ให้กับ servlet ดังนี้:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
(และอัปเดตบรรทัดเดียวกันdoPost()
ตามนั้น)
ที่กล่าวว่าผมไม่แน่ใจว่าถ้ามันเป็นเพียงแค่การเล่นไปรอบ ๆ และการถ่ายภาพในที่มืด แต่รหัสที่คุณโพสต์ไม่ได้ดูดี (เช่นใช้compareTo()
แทนequals()
และเครื่องตักดิน parameternames แทนการเพียงแค่ใช้getParameter()
และid
และpassword
ดูเหมือนว่าจะ ถูกประกาศเป็นตัวแปรอินสแตนซ์ servlet - ซึ่งไม่ใช่เธรดที่ปลอดภัย ) ดังนั้นผมจะขอแนะนำให้เรียนรู้อีกเล็กน้อยเกี่ยวกับพื้นฐาน Java SE API โดยใช้บทเรียนออราเคิล (ตรวจสอบบท "เส้นทางครอบคลุมพื้นฐาน") และวิธีการใช้ JSP / Servlets วิธีการที่เหมาะสมโดยใช้บทเรียนเหล่านั้น
ดูสิ่งนี้ด้วย:
อัปเดต : ตามการอัปเดตคำถามของคุณ (ซึ่งเป็นเรื่องสำคัญมากคุณไม่ควรลบบางส่วนของคำถามเดิมของคุณสิ่งนี้จะทำให้คำตอบไร้ค่า .. แต่เพิ่มข้อมูลในบล็อกใหม่) ปรากฎว่าคุณ multipart/form-data
ประเภทการเข้ารหัสรูปแบบการตั้งค่าโดยไม่จำเป็นที่จะ สิ่งนี้จะส่งพารามิเตอร์คำขอในองค์ประกอบที่แตกต่างจาก (ค่าเริ่มต้น) application/x-www-form-urlencoded
ซึ่งส่งพารามิเตอร์คำขอเป็นสตริงการสืบค้น (เช่นname1=value1&name2=value2&name3=value3
) คุณต้องการmultipart/form-data
เมื่อใดก็ตามที่คุณมีไฟล์<input type="file">
องค์ประกอบในรูปแบบเพื่ออัปโหลดไฟล์ซึ่งอาจเป็นข้อมูลที่ไม่ใช่อักขระ (ข้อมูลไบนารี) นี่ไม่ใช่กรณีของคุณดังนั้นเพียงแค่ลบออกและจะได้ผลตามที่คาดไว้ หากคุณต้องการอัปโหลดไฟล์คุณจะต้องตั้งค่าประเภทการเข้ารหัสและแยกวิเคราะห์เนื้อหาคำขอด้วยตัวคุณเอง โดยปกติคุณจะใช้Apache Commons FileUpload ที่นั่น แต่ถ้าคุณใช้ Servlet 3.0 API ใหม่อยู่แล้วคุณก็สามารถใช้สิ่งอำนวยความสะดวกในตัวที่เริ่มต้นด้วยHttpServletRequest#getPart()
. ดูคำตอบนี้สำหรับตัวอย่างที่เป็นรูปธรรม: วิธีอัปโหลดไฟล์ไปยังเซิร์ฟเวอร์โดยใช้ JSP / Servlet