คำอธิบายโดยละเอียดของการแคชเนื้อหาแบบไดนามิกภายใต้ JSP 2.0
ผู้เขียน:Eve Cole
เวลาอัปเดต:2009-07-03 16:56:34
การแคชเนื้อหาเป็นหนึ่งในเทคนิคการเพิ่มประสิทธิภาพที่พบบ่อยที่สุดในเว็บแอปพลิเคชันและสามารถนำไปใช้งานได้อย่างง่ายดาย ตัวอย่างเช่น คุณสามารถใช้แท็ก JSP ที่กำหนดเองได้ ตั้งชื่อให้ว่า <jc:cache> ด้วย <jc:cache> และ </jc:cache> เพื่อสรุปแต่ละส่วนของหน้าที่ต้องแคช แท็กที่กำหนดเองใดๆ สามารถควบคุมได้ว่าเมื่อใดที่ชิ้นส่วนที่มีอยู่ (นั่นคือ ส่วนของเพจที่บรรจุไว้ล่วงหน้า) จะถูกดำเนินการ และสามารถบันทึกผลลัพธ์เอาต์พุตแบบไดนามิกได้ แท็ก <jc:cache> ช่วยให้คอนเทนเนอร์ JSP (เช่น Tomcat) สามารถสร้างเนื้อหาได้เพียงครั้งเดียวในฐานะตัวแปร JSP ทั่วทั้งแอปพลิเคชัน เพื่อจัดเก็บแต่ละส่วนของแคช แต่ละครั้งที่มีการดำเนินการเพจ JSP แท็กที่กำหนดเองจะโหลดส่วนของหน้าที่แคชไว้ โดยไม่ต้องรันโค้ด JSP อีกครั้งเพื่อสร้างเอาต์พุต ในฐานะที่เป็นส่วนหนึ่งของโครงการจาการ์ตา ไลบรารีแท็กได้รับการพัฒนาโดยใช้เทคโนโลยีนี้ โดยจะทำงานได้ดีเมื่อไม่จำเป็นต้องปรับแต่งเนื้อหาที่แคชไว้สำหรับผู้ใช้แต่ละรายหรือคำขอ
บทความนี้ปรับปรุงเทคนิคที่อธิบายไว้ข้างต้นโดยใช้ JSP 2.0 Expression Language (EL) ซึ่งช่วยให้เพจ JSP ปรับแต่งเนื้อหาที่แคชไว้สำหรับแต่ละคำขอและผู้ใช้ ส่วนของหน้าแคชสามารถมีนิพจน์ JSP ที่ไม่ได้รับการประเมินโดยคอนเทนเนอร์ JSP ค่าของนิพจน์เหล่านี้จะถูกกำหนดโดยแท็กที่กำหนดเองในแต่ละครั้งที่มีการดำเนินการเพจ ดังนั้น การสร้างเนื้อหาไดนามิกจึงได้รับการปรับให้เหมาะสม แต่แฟรกเมนต์ที่แคชไว้สามารถประกอบด้วยบางส่วนของเนื้อหาที่สร้างโดยคำขอแต่ละรายการโดยใช้ภาษานิพจน์ JSP ดั้งเดิม ด้วยความช่วยเหลือของ JSP 2.0 EL API นักพัฒนา Java สามารถทำให้สิ่งนี้เป็นไปได้โดยใช้ภาษานิพจน์
การแคชเนื้อหา VS การแคชข้อมูล การแคชเนื้อหาไม่ใช่ตัวเลือกเดียว ตัวอย่างเช่น ข้อมูลที่แยกจากฐานข้อมูลก็สามารถแคชได้เช่นกัน ในความเป็นจริง การแคชข้อมูลอาจมีประสิทธิภาพมากกว่าเนื่องจากข้อมูลที่เก็บไว้ไม่มีมาร์กอัป HTML และต้องใช้หน่วยความจำน้อยกว่า อย่างไรก็ตาม ในหลายกรณี การแคชในหน่วยความจำจะนำไปใช้ได้ง่ายกว่า สมมติว่าในบางกรณี แอปพลิเคชันประกอบด้วยอ็อบเจ็กต์ธุรกรรมจำนวนมาก ครอบครองทรัพยากร CPU ที่สำคัญ สร้างข้อมูลที่ซับซ้อน และใช้เพจ JSP เพื่อนำเสนอข้อมูล ทุกอย่างทำงานได้ดีจนกระทั่งวันหนึ่งภาระบนเซิร์ฟเวอร์เพิ่มขึ้นอย่างกะทันหันและจำเป็นต้องมีวิธีแก้ปัญหาฉุกเฉิน ในขณะนี้ การสร้างเลเยอร์แคชระหว่างอ็อบเจ็กต์ธุรกรรมและเลเยอร์การนำเสนอเป็นโซลูชันที่ดีและมีประสิทธิภาพ แต่เพจ JSP ที่แคชเนื้อหาไดนามิกต้องได้รับการแก้ไขอย่างรวดเร็วและราบรื่น เมื่อเทียบกับการแก้ไขเพจ JSP แบบธรรมดา การเปลี่ยนแปลงตรรกะทางธุรกิจของแอปพลิเคชันมักจะต้องอาศัยการทำงานและการทดสอบเพิ่มเติม นอกจากนี้ หากเพจรวบรวมข้อมูลจากหลายแหล่งคอมโพสิต เว็บเลเยอร์ต้องการการเปลี่ยนแปลงเพียงเล็กน้อยเท่านั้น ปัญหาคือพื้นที่แคชจำเป็นต้องได้รับการว่างเมื่อข้อมูลที่แคชกลายเป็นข้อมูลเก่า และอ็อบเจ็กต์ธุรกรรมควรทราบเมื่อสิ่งนี้เกิดขึ้น อย่างไรก็ตาม เมื่อเลือกใช้การแคชเนื้อหาหรือการแคชข้อมูล หรือเทคนิคการปรับให้เหมาะสมอื่นๆ มีหลายปัจจัยที่ต้องพิจารณา และบางครั้งอาจมีข้อกำหนดพิเศษสำหรับโปรแกรมที่กำลังพัฒนา
การแคชข้อมูลและการแคชเนื้อหาไม่จำเป็นต้องแยกจากกัน แต่สามารถใช้ร่วมกันได้ ตัวอย่างเช่น ในแอปพลิเคชันที่ขับเคลื่อนด้วยฐานข้อมูล ข้อมูลที่แยกจากฐานข้อมูลและ HTML ที่แสดงข้อมูลจะถูกแคชแยกกัน ซึ่งค่อนข้างคล้ายกับการใช้ JSP เพื่อสร้างเทมเพลตแบบเรียลไทม์ เทคนิค API ที่ใช้ EL ที่กล่าวถึงในบทความนี้แสดงวิธีใช้ JSP EL เพื่อโหลดข้อมูลลงในเทมเพลตการแสดงผล
การแคชเนื้อหาแบบไดนามิกโดยใช้ตัวแปร JSP เมื่อใดก็ตามที่คุณใช้กลไกการแคช คุณต้องมีวิธีการจัดเก็บออบเจ็กต์แคช ในบทความนี้ วัตถุประเภทสตริงจะเกี่ยวข้อง ทางเลือกหนึ่งคือการใช้เฟรมเวิร์กการแคชอ็อบเจ็กต์ หรือใช้แผนที่ Java เพื่อใช้โครงร่างการแคชแบบกำหนดเอง JSP มีสิ่งที่เรียกว่า "แอตทริบิวต์ที่กำหนดขอบเขต" หรือ "ตัวแปร JSP" อยู่แล้วเพื่อจัดเตรียมการแมปวัตถุ ID ซึ่งเป็นสิ่งที่กลไกการแคชต้องการ สำหรับการใช้ขอบเขตเพจหรือคำขอสิ่งนี้ไม่สมเหตุสมผล ในขณะที่ในขอบเขตแอปพลิเคชันนี่เป็นที่ที่ดีในการจัดเก็บเนื้อหาที่แคชไว้เนื่องจากมีการแชร์โดยผู้ใช้และเพจทั้งหมด ขอบเขตเซสชันยังสามารถใช้ได้เมื่อจำเป็นต้องมีการแคชแยกกันสำหรับผู้ใช้แต่ละราย แต่ก็ไม่ได้มีประสิทธิภาพมากนัก ไลบรารีแท็ก JSTL สามารถใช้กับเนื้อหานั้นเพื่อแคชเนื้อหา โดยใช้ตัวแปร JSP ดังแสดงในตัวอย่างต่อไปนี้:
<%@ คำนำหน้า taglib="c" uri=" http://java.sun.com/jsp/jstl/core " %><c:if test="${empty cachedFragment}">
<c:set var="cachedFragment" scope="แอปพลิเคชัน">
-
</c:set></c:ถ้า>
ส่วนของเพจที่แคชไว้จะแสดงผลลัพธ์โดยใช้คำสั่งต่อไปนี้:
${applicationScope.cachedFragment}
จะเกิดอะไรขึ้นเมื่อจำเป็นต้องปรับแต่งส่วนแคชสำหรับแต่ละคำขอ ตัวอย่างเช่น หากคุณต้องการรวมตัวนับ คุณจะต้องแคชสองแฟรกเมนต์:
<%@ คำนำหน้า taglib="c" uri=" http://java.sun.com/jsp/jstl/core " %><c:if test="${sessionScope.counter == null}"> <c :set var="counter" scope="session" value="0"/></c:if><c:set var="counter" value="${counter+1}" scope="session"/ <c:if test="${empty cachedFragment1}">
<c:set var="cachedFragment1" scope="application">
-
</c:set></c:if><c:if test="${empty cachedFragment2}">
<c:set var="cachedFragment2" scope="application">
-
</c:set></c:ถ้า>
คุณสามารถใช้คำสั่งต่อไปนี้เพื่อส่งออกเนื้อหาแคช:
${cachedFragment1} ${เคาน์เตอร์} ${cachedFragment2}
ด้วยความช่วยเหลือของไลบรารีแท็กเฉพาะ การแคชส่วนของหน้าที่ต้องการการปรับแต่งกลายเป็นเรื่องง่ายมาก ตามที่กล่าวไว้ข้างต้น เนื้อหาที่แคชไว้สามารถปิดล้อมได้ด้วยแท็กเปิด (<jc:cache>) และแท็กปิด (</jc:cache>) การปรับแต่งแต่ละรายการสามารถแสดงโดยใช้แท็กอื่น (<jc:dynamic expr="..."/>) เพื่อส่งออกนิพจน์ JSP (${...}) เนื้อหาไดนามิกถูกแคชโดยใช้นิพจน์ JSP และกำหนดทุกครั้งที่มีการปล่อยเนื้อหาแคช คุณสามารถดูวิธีการบรรลุเป้าหมายนี้ได้ในส่วนด้านล่าง Counter.jsp แคชส่วนของเพจที่มีตัวนับ ตัวนับจะเพิ่มขึ้น 1 โดยอัตโนมัติทุกครั้งที่ผู้ใช้รีเฟรชเพจ
<%@ คำนำหน้า taglib = "c" uri = " http://java.sun.com/jsp/jstl/core " %><%@ คำนำหน้า taglib = "jc" uri = " http://devsphere.com/ บทความ/jspcache " %><c:if test="${sessionScope.counter == null}">
<c:set var="counter" scope="session" value="0"/></c:if><c:set var="counter" value="${counter+1}" scope="เซสชัน "/><jc:cache id="cachedFragmentWithCounter">
... <jc:dynamic expr="sessionScope.counter"/>
...</jc:แคช>
ตัวแปร JSP ใช้งานง่ายและเป็นโซลูชันการแคชเนื้อหาที่ดีสำหรับเว็บแอปแบบธรรมดา อย่างไรก็ตาม หากแอปพลิเคชันสร้างเนื้อหาไดนามิกจำนวนมาก การไม่สามารถควบคุมขนาดแคชได้ถือเป็นปัญหาอย่างแน่นอน เฟรมเวิร์กแคชเฉพาะสามารถมอบโซลูชันที่มีประสิทธิภาพยิ่งขึ้น ช่วยให้สามารถตรวจสอบแคช จำกัดขนาดแคช ควบคุมนโยบายแคช ฯลฯ...
การใช้ JSP 2.0 Expression Language API
คอนเทนเนอร์ JSP (เช่น Tomcat) ประเมินนิพจน์ในหน้า JSP โดยใช้ EL API และสามารถใช้ได้โดยโค้ด Java ซึ่งอนุญาตให้มีการพัฒนาภายนอกเว็บเพจโดยใช้ JSP EL เช่น บนไฟล์ XML ทรัพยากรแบบข้อความ และสคริปต์ที่กำหนดเอง EL API ยังมีประโยชน์เมื่อคุณต้องการควบคุมว่าจะกำหนดนิพจน์ในเว็บเพจเมื่อใดหรือเป็นลายลักษณ์อักษรที่เกี่ยวข้องกับนิพจน์เหล่านั้น ตัวอย่างเช่น ส่วนของหน้าที่แคชไว้สามารถมีนิพจน์ JSP แบบกำหนดเองได้ และ EL API จะถูกนำมาใช้เพื่อกำหนดหรือประเมินนิพจน์เหล่านี้ใหม่ทุกครั้งที่มีการปล่อยเนื้อหาที่แคชไว้
บทความนี้มีตัวอย่างโปรแกรม (ดูส่วนทรัพยากรที่ส่วนท้ายของบทความ) แอปพลิเคชันนี้ประกอบด้วยคลาส Java (JspUtils) และเมธอด eval() ในคลาส วิธีการนี้มีพารามิเตอร์สามตัว: นิพจน์ JSP ซึ่งเป็นประเภทที่คาดหวัง ของการแสดงออกและวัตถุบริบท JSP เมธอด Eval() รับ ExpressionEvaluator จากบริบท JSP และเรียกใช้เมธอดประเมิน () โดยส่งผ่านนิพจน์ ประเภทที่คาดหวังของนิพจน์ และตัวแปรที่ได้รับจากข้อความ JSP JspUtils.eval() วิธีการส่งกลับค่าของการแสดงออก
แพ็คเกจ com.devsphere.articles.jspcache;
นำเข้า javax.servlet.jsp.JspContext;
นำเข้า javax.servlet.jsp.JspException;
นำเข้า javax.servlet.jsp.PageContext;
นำเข้า javax.servlet.jsp.el.ELException;
นำเข้า javax.servlet.jsp.el.ExpressionEvaluator;
นำเข้า java.io.IOException; JspUtils คลาสสาธารณะ {
การประเมินวัตถุคงที่สาธารณะ (
สตริง expr, ประเภทคลาส, JspContext jspContext)
พ่น JspException {
พยายาม {
ถ้า (expr.indexOf("${") == -1)
กลับ expr;
ผู้ประเมิน ExpressionEvaluator
= jspContext.getExpressionEvaluator();
ส่งคืน evaluator.evaluate (expr, ประเภท,
jspContext.getVariableResolver(), null);
} จับ (ELException e) {
โยน JspException ใหม่ (e);
-
-
-
หมายเหตุ: JspUtils.eval() ส่วนใหญ่สรุป ExpressionEvaluator มาตรฐาน ถ้า expr ไม่มี ${ JSP EL API จะไม่ถูกเรียกเนื่องจากไม่มีนิพจน์ JSP
การสร้างไฟล์ tag Library descriptor (TLD) ไลบรารีแท็ก JSP ต้องการไฟล์ tag Library descriptor (TLD) เพื่อปรับแต่งการตั้งชื่อแท็ก คุณลักษณะ และคลาส Java ที่ทำงานบนแท็ก jspcache.tld อธิบายแท็กที่กำหนดเองสองแท็ก <jc:cache> มีสองแอตทริบิวต์: id ของส่วนของเพจที่แคชไว้และขอบเขต JSP ซึ่งเป็นขอบเขตเนื้อหาของเพจ JSP ที่ต้องจัดเก็บอยู่เสมอ <jc:dynamic> มีแอ็ตทริบิวต์เดียวเท่านั้น นั่นคือนิพจน์ JSP ที่ต้องได้รับการประเมินทุกครั้งที่เอาต์พุตแฟรกเมนต์แคช ไฟล์ TLD จับคู่แท็กที่กำหนดเองทั้งสองนี้กับคลาส CacheTag และ DynamicTag ดังนี้
<?xml version="1.0" encoding="UTF-8" ?><taglib xmlns=" http://java.sun.com/xml/ns/j2ee "
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance "
xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee เว็บ-jsptaglibrary_2_0.xsd"
รุ่น = "2.0">
<tlib-version>1.0</tlib-version>
<ชื่อย่อ>เจซี</ชื่อย่อ>
<uri>http://devsphere.com/articles/jspcache</uri>
<แท็ก>
<ชื่อ>แคช</ชื่อ>
<tag-class>com.devsphere.articles.jspcache.CacheTag</tag-class>
<เนื้อหาเนื้อหา>ไม่มีสคริปต์</เนื้อหาเนื้อหา>
<คุณสมบัติ>
<ชื่อ>รหัส</ชื่อ>
<จำเป็น>จริง</จำเป็น>
<rtexprvalue>จริง</rtexprvalue>
</คุณสมบัติ>
<คุณสมบัติ>
<ชื่อ>ขอบเขต</ชื่อ>
<จำเป็น>เท็จ</จำเป็น>
<rtexprvalue>เท็จ</rtexprvalue>
</คุณสมบัติ>
</แท็ก>
<แท็ก>
<ชื่อ>ไดนามิก</ชื่อ>
<tag-class>com.devsphere.articles.jspcache.DynamicTag</tag-class>
<เนื้อหาเนื้อหา>ว่างเปล่า</เนื้อหาเนื้อหา>
<คุณสมบัติ>
<ชื่อ>อธิบาย</ชื่อ>
<จำเป็น>จริง</จำเป็น>
<rtexprvalue>เท็จ</rtexprvalue>
</คุณสมบัติ>
</tag></taglib>
ไฟล์ TLD รวมอยู่ในไฟล์อธิบายแอปพลิเคชันเว็บ (web.xml) ไฟล์ทั้งห้านี้ยังมีพารามิเตอร์เริ่มต้นที่ระบุว่าแคชพร้อมใช้งานหรือไม่
<?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns=" http://java.sun.com/xml/ns/j2ee "
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance "
xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee เว็บแอป_2_4.xsd"
รุ่น = "2.4">
<บริบท-พารามิเตอร์>
<param-name>com.devsphere.articles.jspcache.enabled</param-name>
<param-value>จริง</param-value>
</บริบท-พารามิเตอร์>
<jsp-config>
<แท็กลิบ>
<taglib-uri>http://devsphere.com/articles/jspcache</taglib-uri>
<taglib-location>/WEB-INF/jspcache.tld</taglib-location>
</taglib>
</jsp-config></เว็บแอป>
ทำความเข้าใจกลไกการทำงานของ <jc:cache> คอนเทนเนอร์ JSP จะสร้างอินสแตนซ์ CacheTag สำหรับแท็ก <jc:cache> แต่ละรายการในหน้า JSP เพื่อประมวลผล คอนเทนเนอร์ JSP มีหน้าที่เรียกเมธอด setJsp (), setParent () และ setJspBody () ซึ่งเป็นคลาส CacheTag ที่สืบทอดมาจาก SimpleTagSupport คอนเทนเนอร์ JSP ยังเรียกเมธอด setter สำหรับแต่ละแอตทริบิวต์ของแท็กที่ถูกจัดการ เมธอด SetId() และ setScope() เก็บค่าแอตทริบิวต์ลงในฟิลด์ส่วนตัว ค่านี้ได้รับการเตรียมใช้งานด้วยค่าเริ่มต้นโดยใช้ตัวสร้าง CacheTag()
แพ็คเกจ com.devsphere.articles.jspcache;
นำเข้า javax.servlet.ServletContext;
นำเข้า javax.servlet.jsp.JspContext;
นำเข้า javax.servlet.jsp.JspException;
นำเข้า javax.servlet.jsp.PageContext;
นำเข้า javax.servlet.jsp.tagext.SimpleTagSupport;
นำเข้า java.io.IOException; นำเข้า java.io.StringWriter;
CacheTag คลาสสาธารณะขยาย SimpleTagSupport {
สตริงสุดท้ายแบบคงที่สาธารณะ CACHE_ENABLED
= "com.devsphere.articles.jspcache.enabled";
รหัสสตริงส่วนตัว;
ขอบเขต int ส่วนตัว
แคชบูลีนส่วนตัวเปิดใช้งาน; CacheTag สาธารณะ () {
id = null; ขอบเขต = PageContext.APPLICATION_SCOPE;
} setId โมฆะสาธารณะ (รหัสสตริง) {
this.id = ไอดี;
} setScope โมฆะสาธารณะ (ขอบเขตสตริง) {
this.scope = JspUtils.checkScope (ขอบเขต);
-
-
เมธอด setScope() เรียก JspUtils.checkScope() เพื่อตรวจสอบค่าคุณสมบัติของขอบเขตที่ถูกแปลงจาก String เป็นประเภท int
...JspUtils คลาสสาธารณะ {
-
int checkScope แบบคงที่สาธารณะ (ขอบเขตสตริง) {
ถ้า ("หน้า".equalsIgnoreCase(ขอบเขต))
กลับ PageContext.PAGE_SCOPE;
อื่นถ้า ("คำขอ".equalsIgnoreCase(ขอบเขต))
กลับ PageContext.REQUEST_SCOPE;
อื่นถ้า ("เซสชัน".equalsIgnoreCase(ขอบเขต))
กลับ PageContext.SESSION_SCOPE;
อย่างอื่นถ้า ("application".equalsIgnoreCase(scope))
กลับ PageContext.APPLICATION_SCOPE;
อื่น
โยน IllegalArgumentException ใหม่ (
"ขอบเขตไม่ถูกต้อง: " + ขอบเขต);
-
เมื่ออินสแตนซ์ CacheTag พร้อมที่จะทำงานกับแท็ก คอนเทนเนอร์ JSP จะเรียกใช้เมธอด doTag() และรับบริบท JSP โดยใช้ getJspContext() ออบเจ็กต์นี้ถูกส่งเป็น PageContext เพื่อให้สามารถเรียกใช้เมธอด getServletContext() ได้ บริบทเซิร์ฟเล็ตถูกใช้เพื่อรับค่าของพารามิเตอร์การกำหนดค่าเริ่มต้น ซึ่งบ่งชี้ว่ากลไกการแคชถูกเปิดใช้งานหรือไม่ หากเปิดใช้งานการแคช doTag() จะพยายามรับส่วนของหน้าที่แคชไว้โดยใช้ค่าแอตทริบิวต์ id และขอบเขต หากส่วนของหน้าไม่ได้รับการแคช doTag() จะใช้ getJspBody().inrigg() เพื่อรันโค้ด JSP ที่ห่อหุ้มด้วย <jc:cache> และ </jc:cache> เอาต์พุตที่สร้างโดยเนื้อหา JSP จะถูกบัฟเฟอร์ใน StringWriter และดึงข้อมูลโดยเมธอด toStirng() ด้วยวิธีนี้ doTag() เรียกเมธอด setAttribute() ของบริบท JSP เพื่อสร้างตัวแปร JSP ใหม่ ตัวแปรนี้ควบคุมเนื้อหาแคชที่อาจมีนิพจน์ JSP (${…}) นิพจน์เหล่านี้ถูกกำหนดโดย JspUtils.eval() ก่อนที่จะส่งออกเนื้อหาโดยใช้ jspContext.getOut().print() ลักษณะการทำงานนี้เกิดขึ้นเมื่อเปิดใช้งานแคชเท่านั้น มิฉะนั้น doTag() จะเรียกใช้เนื้อหา JSP ผ่าน getJspBody().invoid(null) และผลลัพธ์เอาต์พุตจะไม่ถูกแคช
...CacheTag คลาสสาธารณะขยาย SimpleTagSupport {
-
โมฆะสาธารณะ doTag() พ่น JspException, IOException {
JspContext jspContext = getJspContext();
แอปพลิเคชัน ServletContext
= ((PageContext) jspContext).getServletContext();
สตริงแคชEnabledParam
= application.getInitParameter (CACHE_ENABLED);
cacheEnabled = cacheEnabledParam != null
&& cacheEnabledParam.equals("จริง");
ถ้า (เปิดใช้งานแคช) {
สตริงแคชเอาท์พุต
= (สตริง) jspContext.getAttribute(id, ขอบเขต);
ถ้า (cachedOutput == null) {
StringWriter buffer = StringWriter ใหม่ ();
getJspBody().เรียก(บัฟเฟอร์);
cachedOutput = buffer.toString();
jspContext.setAttribute(id, cachedOutput, ขอบเขต);
} สตริงประเมินผลเอาท์พุต = (สตริง) JspUtils.eval(
cachedOutput, String.class, jspContext);
jspContext.getOut().print(ประเมินผลลัพธ์);
} อื่น
getJspBody().เรียก(null);
-
-
โปรดทราบว่าการเรียก JspUtils.eval() เพียงครั้งเดียวจะประเมินนิพจน์ ${…} ทั้งหมด เนื่องจากข้อความที่มีโครงสร้าง ${...} จำนวนมากก็เป็นนิพจน์เช่นกัน แต่ละส่วนของแคชสามารถประมวลผลเป็นนิพจน์ JSP ที่ซับซ้อนได้
วิธีการ IsCacheEnabled() ส่งกลับค่าของ cacheEnabled ซึ่งได้รับการเตรียมใช้งานโดย doTag()
...CacheTag คลาสสาธารณะขยาย SimpleTagSupport {
... บูลีนสาธารณะ isCacheEnabled() {
ส่งคืนแคชเปิดใช้งาน;
-
แท็ก <jc:cache> ช่วยให้นักพัฒนาเพจสามารถเลือก ID ของส่วนของเพจที่แคชไว้ได้ ซึ่งอนุญาตให้แบ่งใช้ส่วนของเพจที่แคชไว้โดยเพจ JSP หลายเพจ ซึ่งมีประโยชน์เมื่อใช้โค้ด JSP ซ้ำ แต่โปรโตคอลการตั้งชื่อบางอย่างยังจำเป็นเพื่อหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้น ผลข้างเคียงนี้สามารถหลีกเลี่ยงได้โดยการแก้ไขคลาส CacheTag เพื่อรวม URL ไว้ใน ID อัตโนมัติ
การทำความเข้าใจว่า <jc:dynamic> กำลังทำอะไร แต่ละ <jc:dynamic> ได้รับการจัดการโดยอินสแตนซ์ของคลาส DynamicTag และเมธอด setExpr() จะจัดเก็บค่าแอตทริบิวต์ expr ลงในฟิลด์ส่วนตัว เมธอด DoTag() สร้างนิพจน์ JSP และเพิ่มส่วนต่อท้าย ${ และ } ให้กับค่าแอตทริบิวต์ expr จากนั้น doTag() ใช้ findAncestorWithClass() เพื่อค้นหา CacheTag handler ของ <jc:cache> ที่มีองค์ประกอบแท็ก <jc:dynamic> หากไม่พบหรือปิดใช้งานการแคช นิพจน์ JSP จะถูกประเมินด้วย JspUtils.eval() และค่าจะเป็นเอาต์พุต มิฉะนั้น doTag() จะแสดงผลลัพธ์เป็นนิพจน์ที่ไม่มีค่า
แพ็คเกจ com.devsphere.articles.jspcache;
นำเข้า javax.servlet.jsp.JspException;
นำเข้า javax.servlet.jsp.tagext.SimpleTagSupport;
นำเข้า java.io.IOException;
DynamicTag ระดับสาธารณะขยาย SimpleTagSupport {
สตริงส่วนตัว expr;
โมฆะสาธารณะ setExpr (สตริง expr) {
นี้.expr = expr;
} โมฆะสาธารณะ doTag() พ่น JspException, IOException {
เอาต์พุตสตริง = "${" + expr + "}";
บรรพบุรุษ CacheTag = (CacheTag) findAncestorWithClass(
นี่ CacheTag.class);
ถ้า (บรรพบุรุษ == null || !ancestor.isCacheEnabled())
เอาท์พุท = (สตริง) JspUtils.eval(
เอาท์พุท, String.class, getJspContext());
getJspContext().getOut().พิมพ์(เอาท์พุท);
-
จากการวิเคราะห์โค้ดข้างต้น คุณจะสังเกตเห็นว่า <jc:cache> และ <jc:dynamic> ร่วมมือกันเพื่อให้ได้โซลูชันที่มีประสิทธิภาพที่สุดเท่าที่จะเป็นไปได้ หากมีแคช ส่วนของหน้าจะถูกใส่ลงในบัฟเฟอร์ร่วมกับนิพจน์ JSP ที่สร้างโดย <jc:dynamic> และกำหนดค่า CacheTag หากปิดใช้งานการแคช การแคชจะไม่มีความหมายและ <jc:cache> เพียงดำเนินการส่วนเนื้อหา JSP โดยปล่อยให้ DynamicTag กำหนดค่าให้กับนิพจน์ JSP บางครั้งการปิดใช้งานการแคชเป็นสิ่งจำเป็น โดยเฉพาะอย่างยิ่งในระหว่างกระบวนการพัฒนา เมื่อเนื้อหาเปลี่ยนแปลงและเพจ JSP ถูกคอมไพล์ใหม่ แน่นอนว่าต้องเปิดใช้งานการแคชในสภาพแวดล้อมการผลิตหลังการพัฒนา
สรุป
สำหรับการพัฒนาแอปพลิเคชันระดับองค์กรขนาดใหญ่ คุณควรพิจารณาใช้เฟรมเวิร์กที่รองรับกลไกการแคชที่ดีกว่า แทนที่จะใช้เพียงตัวแปร JSP แต่ไม่ต้องสงสัยเลยว่าการทำความเข้าใจเทคโนโลยีการปรับแต่งตาม EL API นั้นมีประโยชน์อย่างแน่นอน