เซิร์ฟเล็ตคืออะไร?
ก่อนอื่น มาดูกันว่าเซิร์ฟเล็ตคืออะไรและทำไมคุณถึงได้ยินบ่อย Java Servlet APIเป็น API มาตรฐานที่มีไว้สำหรับใช้งานบนเซิร์ฟเวอร์ มันโต้ตอบกับลูกค้าตามรูปแบบการตอบสนองคำขอ เซิร์ฟเล็ตคือคลาสที่สามารถรับคำขอจากไคลเอ็นต์และส่งคืนการตอบกลับไปยังไคลเอ็นต์ ในความเป็นจริง เซิร์ฟเล็ตเป็นหน่วยการสร้างที่เราใช้เพื่อสร้างสถาปัตยกรรมไคลเอ็นต์เซิร์ฟเวอร์ใน Java คุณอาจจำได้ว่าเราได้พูดถึงสถาปัตยกรรมนั้นไปแล้วในบทความอื่นในชุด เราจะไม่เอาชนะพุ่มไม้: มาเขียนโค้ดกันทันทีสิ่งที่คุณต้องการในการสร้างเว็บแอปพลิเคชัน
เพื่อความสะดวกสูงสุดเมื่อทำงานกับเซิร์ฟเวอร์ Java คุณต้องมี IntelliJ IDEA Ultimate Edition เป็นผลิตภัณฑ์แบบชำระเงิน แต่คุณสามารถเปิดใช้งานการทดลองใช้ 30 วันหรือใช้เวอร์ชันทดลองใช้ก่อนเปิดตัวได้ ซึ่งฟรีตลอดเวลา นอกจากนี้ ติดตั้ง Apache Tomcat — เซิร์ฟเวอร์ของแอปพลิเคชันของเรา Tomcat เป็นคอนเทนเนอร์เซิร์ฟเล็ต: ประมวลผลคำขอที่เข้ามาและส่งต่อไปยังแอปพลิเคชันของเรา ดาวน์โหลด Tomcat ที่ นี่มาสร้างเว็บแอปพลิเคชันแรกของเรากันเถอะ
หากทุกอย่างพร้อมแล้ว ให้สร้างโครงการ Maven หากคุณไม่คุ้นเคยกับ Maven โปรดดูบทความก่อนหน้า เอาล่ะ!-
ใน pom.xml เพิ่มการพึ่งพา javax.servlet-api และระบุบรรจุภัณฑ์ WAR:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>servlets</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> </dependencies> </project>
คลาสเซิร์ฟเล็ตอย่างง่าย:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/hello") public class MainServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); PrintWriter printWriter = resp.getWriter(); printWriter.write("Hello!"); printWriter.close(); } }
-
ในการเรียกใช้แอปพลิเคชัน คุณต้องสร้างการกำหนดค่า Tomcat:
-
ต่อไป เราจะระบุเวอร์ชันของ Tomcat ที่เราจะใช้ และ URL และพอร์ตสำหรับการสื่อสารกับเซิร์ฟเวอร์ คุณควรมีสิ่งนี้:
-
ตอนนี้เราต้องระบุสิ่งประดิษฐ์ (โครงการประกอบในไฟล์เก็บถาวร JAR) ที่จะปรับใช้ในคอนเทนเนอร์ คุณสามารถคลิก ปุ่ม แก้ไขและเลือกสงครามระเบิดได้ซึ่งหมายความว่าหลังจากสร้างโครงการใหม่แล้ว สิ่งประดิษฐ์จะถูกวางในคอนเทนเนอร์เซิร์ฟเล็ตโดยอัตโนมัติ
-
ค่าดีฟอลต์สำหรับบริบทของแอปพลิเคชันคือservlets_war_exploded ซึ่งหมายความว่าเราเข้าถึงแอปพลิเคชันได้ที่: http ://localhost:8080/servlets_war_exploded
ทำไมเราต้องการข้อความเพิ่มเติม มาลบสิ่งที่ไม่จำเป็นกันเถอะ ตอนนี้ที่อยู่เว็บแอปพลิเคชันของเราคือ: http://localhost: 8080
-
คลิกตกลง เราเห็นว่าตอนนี้เราสามารถเปิดแอปพลิเคชันได้แล้ว:
ตอนนี้เมื่อคุณเปิดแอปพลิเคชันในเบราว์เซอร์ คุณควรได้รับข้อผิดพลาด 404 สิ่งนี้สมเหตุสมผล เพราะที่อยู่http://localhost:8080/ต้องการเซิร์ฟเล็ตที่แมปกับ "/" แต่เซิร์ฟเล็ตเดียวของเราแมปกับ"/hello"
-
เราสามารถเข้าถึงได้ที่http://localhost:8080/hello . เมื่อทำเช่นนั้น เราจะได้คำตอบที่คาดไว้ — สตริง "Hello"!
@WebServlet()
คำอธิบายประกอบ นี่คือจุดที่เราผูก (หรือแมป) เซิร์ฟเล็ตกับเส้นทางเฉพาะ ("/hello") คำอธิบายประกอบนี้ปรากฏเฉพาะใน Java Servlet API 3.0 ดังนั้นอินเทอร์เน็ตจึงมีตัวอย่างมากมายที่การแมปเซิร์ฟเล็ตเกิดขึ้นผ่านไฟล์ XML สิ่งนี้ไม่จำเป็นอีกต่อไป ในการจัดการคำขอ GETเราจะแทนที่doGet()
เมธอด ให้ความสนใจกับพารามิเตอร์ของเมธอด: HttpServletRequest
และ HttpServletResponse
วัตถุHttpServletRequest
ให้ข้อมูลที่จำเป็นทั้งหมดเกี่ยวกับคำขอแก่เรา ในHttpServletResponse
เราเขียนคำตอบของเราและกำหนดส่วนหัวที่จำเป็น
การทำงานกับพารามิเตอร์และเซสชัน
มาปรับปรุงเซิร์ฟเล็ตของเราเพื่อให้สามารถประมวลผลพารามิเตอร์คำขอและทำงานกับเซสชันได้:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Integer visitCounter = (Integer) session.getAttribute("visitCounter");
if (visitCounter == null) {
visitCounter = 1;
} else {
visitCounter++;
}
session.setAttribute("visitCounter", visitCounter);
String username = req.getParameter("username");
resp.setContentType("text/html");
PrintWriter printWriter = resp.getWriter();
if (username == null) {
printWriter.write("Hello, Anonymous" + "<br>");
} else {
printWriter.write("Hello, " + username + "<br>");
}
printWriter.write("Page was visited " + visitCounter + " times.");
printWriter.close();
}
}
ขณะนี้ เซิร์ฟเล็ตทำงานร่วมกับเซสชัน เพิ่มมูลค่าvisitCounter
ทุกครั้งที่เพจถูกเยี่ยมชม หากvisitCounter
ยังไม่ได้สร้างแอตทริบิวต์ (เมื่อเข้าชมหน้าเว็บครั้งแรก) เมธอดgetAttribute()
จะส่งคืนค่าว่าง ดังนั้นเราต้องตรวจสอบค่าว่าง เช่นเดียวกับพารามิเตอร์คำขอ หากผู้ใช้ไม่ส่งพารามิเตอร์ชื่อผู้ใช้ ค่าจะเป็นโมฆะ ในกรณีนี้ เราทักทายผู้ใช้ในฐานะผู้เยี่ยมชมที่ไม่ระบุตัวตน ในการส่งพารามิเตอร์ในคำขอ GET จะใช้สตริงการสืบค้น ตัวอย่างเช่น เราสามารถใช้ URL ต่อไปนี้: http:// localhost:8080/hello? ชื่อผู้ใช้ = พอล คุณสามารถอ่านเพิ่มเติมเกี่ยวกับคำขอ HTTP ได้ในบทความก่อนหน้านี้ในซีรีส์ ขณะนี้แอปพลิเคชันของเราไม่มีตรรกะมากนัก แต่เป็นเรื่องน่ารำคาญเล็กน้อยที่เราได้รับข้อผิดพลาด 404 ที่เส้นทางรูท ในการแก้ไขปัญหานี้ เราจะสร้างเซิร์ฟเล็ตอื่นและแมปไปยังหน้าเริ่มต้น@WebServlet("/")
: จุดประสงค์ของเซิร์ฟเล็ตนี้คือเพื่อเปลี่ยนเส้นทางการร้องขอไปยังพาธ "/hello" ทำได้สองวิธี: ใช้ "ส่งต่อ" หรือ "เปลี่ยนเส้นทาง" บางทีมันก็คุ้มค่าที่จะเข้าใจความแตกต่างระหว่างพวกเขา ผู้รับมอบสิทธิ์ส่งต่อการประมวลผลคำขอไปยังเซิร์ฟเล็ตอื่นบนเซิร์ฟเวอร์ ลูกค้าไม่มีส่วนเกี่ยวข้อง เมื่อต้องการทำเช่นนี้ ให้เพิ่มโค้ดต่อไปนี้ในเมธอด doGet() ของเซิร์ฟเล็ตใหม่:
getServletContext().getRequestDispatcher("/hello").forward(req, resp);
ในโค้ดนี้ เราเข้าถึงบริบทของเซิร์ฟเล็ต รับตัวส่งคำขอสำหรับเซิร์ฟเล็ตที่เกี่ยวข้อง และขอให้ประมวลผลคำขอเฉพาะด้วยอาร์กิวเมนต์ที่ระบุ (req, resp) การเปลี่ยนเส้นทางจะส่งกลับไปยังไคลเอนต์ตามที่อยู่ที่ไคลเอนต์ต้องใช้ในการประมวลผลคำขอ เบราว์เซอร์ส่วนใหญ่จะนำทางไปยัง URL ที่ส่งคืนโดยอัตโนมัติ หากต้องการใช้การเปลี่ยนเส้นทาง คุณต้องเพิ่มรหัสนี้:
resp.sendRedirect(req.getContextPath() + "/hello");
เราเรียกredirect()
เมธอดบนHttpServletResponse
พารามิเตอร์และส่งผ่านแอดเดรสที่ไคลเอ็นต์ต้องการใช้ นี่คือรายละเอียดที่สำคัญ: ต้องเพิ่มพารามิเตอร์ HTTP ที่ส่วนท้ายของเส้นทางการเปลี่ยนเส้นทางแบบเต็มด้วย ซึ่งไม่สะดวกนัก ในสถานการณ์ของเรา ควรใช้forward
แต่บางครั้งการใช้redirect
ก็ดีกว่า หากคุณเข้าใจความแตกต่างในการทำงาน คุณจะเลือกไม่ผิด รหัสสำหรับเซิร์ฟเล็ตใหม่มีลักษณะดังนี้:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// getServletContext().getRequestDispatcher("/hello").forward(req, resp);
resp.sendRedirect(req.getContextPath() + "/hello");
}
}
GO TO FULL VERSION