บทความนี้ปรับปรุงเทคนิคที่อธิบายไว้ข้างต้นโดยใช้ 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:if> |
ส่วนของเพจที่แคชไว้จะแสดงผลลัพธ์โดยใช้คำสั่งต่อไปนี้:
${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:if> |
คุณสามารถใช้คำสั่งต่อไปนี้เพื่อส่งออกเนื้อหาแคช:
${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/articles/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="session"/> <jc:cache id="cachedFragmentWithCounter"> - <jc:dynamic expr="sessionScope.counter"/> - </jc:cache"> |
ตัวแปร JSP นั้นใช้งานง่ายและเป็นโซลูชันการแคชเนื้อหาที่ดีสำหรับเว็บแอปทั่วไป อย่างไรก็ตาม หากแอปพลิเคชันสร้างเนื้อหาไดนามิกจำนวนมาก การไม่สามารถควบคุมขนาดแคชได้ถือเป็นปัญหาอย่างแน่นอน เฟรมเวิร์กแคชเฉพาะสามารถมอบโซลูชันที่มีประสิทธิภาพยิ่งขึ้น ช่วยให้สามารถตรวจสอบแคช การจำกัดขนาดแคช การควบคุมนโยบายแคช ฯลฯ...
การใช้คอนเทนเนอร์ JSP 2.0 Expression Language API
JSP (เช่น Tomcat) เพื่อใช้ EL API Expressions ใน JSP หน้าเป็นค่าที่กำหนดและสามารถใช้ได้โดยโค้ด 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" version="2.0"> <เวอร์ชัน tlib">1.0</เวอร์ชัน tlib"> <ชื่อสั้น">jc</ชื่อสั้น> <uri>http://devsphere.com/articles/jspcache</uri> <แท็ก> <ชื่อ>แคช</ชื่อ> <tag-class>com.devsphere.articles.jspcache.CacheTag </tag-class> <เนื้อหาเนื้อหา><ไม่มีสคริปต์<//เนื้อหาเนื้อหา> <แอตทริบิวต์> <ชื่อ>id</ชื่อ> <จำเป็น>จริง</จำเป็น> <rtexprvalue>true</rtexprvalue> </attribute> <attribute"> <ชื่อ>ขอบเขต</ชื่อ> <จำเป็น>เท็จ</จำเป็น> <rtexprvalue><f/rtexprvalue> </attribute> </tag> <tag> <ชื่อ><ไดนามิก</ชื่อ> <แท็กคลาส> com.devsphere.articles.jspcache.DynamicTag</tag-class> <เนื้อหาในร่างกาย>ว่างเปล่า</เนื้อหาในร่างกาย> <แอตทริบิวต์> <ชื่อ>expr</ชื่อ> <จำเป็น>จริง</จำเป็น> <rtexprvalue><f/rtexprvalue> </attribute> </tag><</taglib> |
ไฟล์ TLD รวมอยู่ในไฟล์อธิบายแอปพลิเคชันเว็บ (web.xml) ไฟล์ทั้งห้านี้ยังมีพารามิเตอร์เริ่มต้นที่ระบุว่าแคชพร้อมใช้งานหรือไม่
<?xml version="1.0" encoding="ISO-8859-1"?> <เว็บแอป 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" version="2.4"> <context-param> <param-name> com.devsphere.articles.jspcache.enabled</param-name> <ค่าพารามิเตอร์>จริง</ค่าพารามิเตอร์> </บริบท-พารามิเตอร์> <jsp-config"> <taglib"> <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 ส่วนตัว แคชบูลีนส่วนตัวEnabled; 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(); สตริง cacheEnabledParam= application.getInitParameter(CACHE_ENABLED); cacheEnabled = cacheEnabledParam != null && cacheEnabledParam.equals("จริง"); ถ้า (เปิดใช้งานแคช) - สตริง cachedOutput= (สตริง) 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().invoke(null); - - - |
โปรดทราบว่าการเรียก JspUtils.eval() เพียงครั้งเดียวจะประเมินนิพจน์ ${…} ทั้งหมด เนื่องจากข้อความที่มีโครงสร้าง ${...} จำนวนมากก็เป็นนิพจน์เช่นกัน แต่ละส่วนของแคชสามารถประมวลผลเป็นนิพจน์ JSP ที่ซับซ้อนได้ วิธีการ IsCacheEnabled() ส่งกลับค่าของ cacheEnabled ซึ่งได้รับการเตรียมใช้งานโดย doTag()
วิธีการ IsCacheEnabled() ส่งกลับค่าของ cacheEnabled ซึ่งได้รับการเตรียมใช้งานโดย doTag() ...CacheTag คลาสสาธารณะขยาย SimpleTagSupport - - isCacheEnabled บูลีนสาธารณะ () { ส่งคืน cacheEnabled; - - |
แท็ก <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) ค้นหา AncestorWithClass (นี่คือ 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 เพื่อปรับแต่งเนื้อหาแคชสำหรับผู้ใช้แต่ละรายหรือคำขอ ไลบรารีแท็กที่แนะนำโดยย่อในบทความนี้เหมาะสำหรับเว็บแอปขนาดเล็กและสามารถปรับปรุงประสิทธิภาพของแอปพลิเคชันขนาดกลางได้ สำหรับการพัฒนาแอปพลิเคชันระดับองค์กรขนาดใหญ่ คุณควรพิจารณาใช้เฟรมเวิร์กที่รองรับกลไกการแคชที่ดีกว่า แทนที่จะใช้เพียงตัวแปร JSP