รู้เบื้องต้นเกี่ยวกับตัวกรอง

แต่นั่นไม่ใช่ทั้งหมด คุณไม่คิดว่า 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()จะมีการร้องขอใหม่ภายในคอนเทนเนอร์ และเซิร์ฟเล็ตของคุณจะส่งการตอบกลับไปยังเบราว์เซอร์ (ไคลเอ็นต์) เป็นการตอบกลับของเซิร์ฟเล็ตของคุณ ในกรณีนี้ เบราว์เซอร์ได้รับการตอบกลับจากเซิร์ฟเล็ตใหม่ แต่ลิงก์ในเบราว์เซอร์จะไม่เปลี่ยนแปลง