รู้เบื้องต้นเกี่ยวกับตัวกรอง
แต่นั่นไม่ใช่ทั้งหมด คุณไม่คิดว่า servlets จะง่ายขนาดนั้นจริง ๆ ใช่ไหม
นอกจากเซิร์ฟเล็ตที่เราวิเคราะห์แล้วยังมีสิ่งที่เรียกว่า "ยูทิลิตี้เซิร์ฟเล็ต" - ตัวกรอง พวกมันคล้ายกับเซิร์ฟเล็ตมาก แต่งานหลักคือช่วยเซิร์ฟเล็ตประมวลผลคำขอ
ตัวกรองเปรียบเสมือนเลขานุการ และเซิร์ฟเล็ตเปรียบเสมือนผู้อำนวยการ ก่อนที่เอกสารจะถึงโต๊ะผู้อำนวยการ มันจะผ่านมือเลขาฯ และหลังจากที่ผู้อำนวยการลงนามแล้วก็จะไปที่เลขานุการอีกครั้งเช่นจดหมายโต้ตอบขาออก
เลขานุการดังกล่าวสามารถปฏิเสธคำขอบางอย่างที่ส่งถึงผู้อำนวยการ (เช่น สแปม) หรือให้คำตอบมาตรฐานสำหรับคำถามที่เขารู้จัก (“ผู้อำนวยการไม่อยู่”) และอื่น ๆ ยิ่งกว่านั้น อาจมีเลขานุการดังกล่าวได้หลายคน: คนหนึ่งสามารถกรองสแปมสำหรับกรรมการทุกคนพร้อมกัน อีกคนสามารถโอนคำขอระหว่างกรรมการที่แตกต่างกัน และอื่นๆ
ตัวกรองทำงานในลักษณะเดียวกัน
ตัวกรองคลาส, FilterChain, FilterConfig
ตัวกรองนั้นคล้ายกับเซิร์ฟเล็ตมาก แต่มีความแตกต่างเล็กน้อย หากต้องการเขียนตัวกรองของคุณเอง คุณต้องสืบทอดจากไฟล์javax.servlet.Filter
.
ตัวกรองยังมีวิธีการinit()
และ destroy()
แทนที่จะเป็นเมธอดservice()
ตัวกรองมีไฟล์doFilter()
. และยังมีคลาส FilterConfig ของตัวเองอีกด้วย ตัวกรองยังถูกเพิ่มไปยังเซิร์ฟเล็ตในไฟล์ web.xml หรือผ่านคำอธิบายประกอบ @WebFilter
รายการวิธีการ:
วิธีการ | คำอธิบาย | |
---|---|---|
1 | init(FilterConfig config) |
การเริ่มต้นตัวกรอง |
2 | destroy() |
ขนถ่ายตัวกรอง |
3 | doFilter(ServletRequest , ServletResponse, FilterChain) |
การประมวลผลคำขอ (การกรอง) |
เซิร์ฟเล็ตและตัวกรองต่างกันอย่างไร
อาจมีตัวกรองหลายตัว และตัวกรองจะประมวลผลคำขอ (และตอบกลับ) ตามลำดับ พวกเขารวมกันเป็นห่วงโซ่ที่เรียกว่า - และยังมีคลาสพิเศษสำหรับพวกเขาFilterChain
ด้วย
หลังจากประมวลผลคำขอในเมธอดแล้วdoFilter()
คุณต้องเรียกเมธอดdoFilter()
ของตัวกรองถัดไปในเชน ตัวอย่าง:
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
PrintWriter out = resp.getWriter();
out.print("Adding something before the body of the response");
chain.doFilter(req, resp); // call the next filter in the chain
out.print("Adding something after the body of the response");
}
public void destroy() {
}
}
อันที่จริงคุณไม่สามารถ เพิ่มเนื้อหาการตอบสนองแบบนั้น ได้ อย่างเป็นทางการ ตัวกรองและเซิร์ฟเล็ตเป็นอิสระจากกันและสามารถเปลี่ยนแปลงได้อย่างอิสระ สามารถเขียนโดยนักพัฒนาที่แตกต่างกันในเวลาที่ต่างกัน ฟังก์ชันตัวกรองเป็นเพียงฟังก์ชันบริการ ตัวอย่างเช่น
- การบันทึกคำขอที่เข้ามาทั้งหมด (และการตอบกลับ)
- การบีบอัดข้อมูล
- การเข้ารหัส (และถอดรหัส) ของข้อมูล
- ขอตรวจสอบข้อมูล
- เพิ่ม/ลบส่วนหัวที่ต้องการ
- คำขอเปลี่ยนเส้นทาง
- การควบคุมการเข้าถึง (ตรวจสอบว่าผู้ใช้เข้าสู่ระบบหรือไม่)
คลาส RequestDispatcher
doFilter()
บางครั้ง อาจจำเป็นต้องเรียกเซิร์ฟเล็ตอื่นในขณะที่ตัวกรองกำลังทำงานภายในเมธอด RequestDispatcher
เมื่อต้องการทำเช่น นี้คอนเทนเนอร์มีวัตถุพิเศษ
คุณสามารถรับได้สองวิธี:
- ที่วัตถุ
HttpServletRequest
- ที่วัตถุ
ServletContext
วัตถุนี้สามารถใช้เพื่อเปลี่ยนทิศทางคำขอที่มีอยู่ไปยังเซิร์ฟเล็ตอื่น ตัวอย่างเช่น ปรากฎว่าผู้ใช้ไม่ได้รับอนุญาต และเราต้องการแสดงหน้าที่ได้รับอนุญาต หรือมีข้อผิดพลาดบนเซิร์ฟเวอร์และเราต้องการแสดงหน้าข้อผิดพลาดแก่ผู้ใช้ :)
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = "/error.html";
ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(request, response);
}
}
คุณยังสามารถโทรRequestDispatcher
จากตัวกรอง
public class MyFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws Exception {
String path = "/error.html";
ServletContext servletContext = req.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
requestDispatcher.forward(req, resp);
}
public void destroy() {
}
}
โปรดทราบว่าคำขอจะได้รับการ จัดการในเมธอดforward()
และไม่จำเป็นต้องเรียกdoFilter()
ใช้หลังจากใช้งานRequestDispatcher
การเปรียบเทียบการเปลี่ยนเส้นทางและการส่งต่อ
และอีกหนึ่งจุดสำคัญ หากคุณต้องการเปลี่ยนเส้นทางผู้ใช้ไปยัง URI อื่นในเซิร์ฟเล็ตของคุณ คุณสามารถทำได้สองวิธี:
redirect
forward
เราได้วิเคราะห์แล้ว แต่เพื่อความสะดวกฉันจะพูดอีกครั้ง
เมื่อคุณเปลี่ยนเส้นทางผ่านการโทรresponse.sendRedirect("link")
เซิร์ฟเวอร์จะส่งการตอบสนองกลับไปยังเบราว์เซอร์ (ไคลเอ็นต์) 302
และลิงก์ที่คุณระบุ และหลังจากวิเคราะห์การตอบสนองของเซิร์ฟเวอร์แล้ว เบราว์เซอร์จะดาวน์โหลดลิงก์ที่คุณส่งมา นั่นคือลิงก์ในเบราว์เซอร์จะเปลี่ยนเป็นลิงก์ใหม่
หากคุณส่งต่อผ่านการโทรrequestDispatcher.forward()
จะมีการร้องขอใหม่ภายในคอนเทนเนอร์ และเซิร์ฟเล็ตของคุณจะส่งการตอบกลับไปยังเบราว์เซอร์ (ไคลเอ็นต์) เป็นการตอบกลับของเซิร์ฟเล็ตของคุณ ในกรณีนี้ เบราว์เซอร์ได้รับการตอบกลับจากเซิร์ฟเล็ตใหม่ แต่ลิงก์ในเบราว์เซอร์จะไม่เปลี่ยนแปลง
GO TO FULL VERSION