In Web applications, content caching is one of the most common optimization techniques and can be easily implemented. For example, you can use a custom JSP tag--we'll name it --by and encapsulate each page fragment that needs to be cached. Any custom label can control when the part (or the pre-packaged page fragment) it contains is executed, and the dynamic output can be captured. The label makes the JSP container (for example, Tomcat) produce only the content once, and serves as the application-scoped JSP variable to store each cached fragment. Each time a JSP page is executed, the custom label loads the page fragment without having to execute the JSP code again to produce the output. As part of the Jakarta Project, the development of tag libraries uses this technique. When cached content does not need to be customized by every user or request, it works very well.
This article improves on the techniques described above, allowing JSP pages to customize cached content for each request and user by using the JSP 2.0 Expression language (EL). A cached page fragment can contain a JSP expression that is not assigned to a JSP container, and the value of those expressions is determined by the custom label each time the page is executed. As a result, the creation of dynamic content is optimized, but the cached fragment can contain part of the content produced by each request using native JSP expression language. With the help of the JSP 2.0 EL API, Java Developers can make it possible with an expression language.
Content Caching vs Data caching
Content caching is not the only option. For example, data extracted from a database can also be cached. In fact, because the stored information contains no HTML markup and requires less memory, the data cache may be more efficient. In many cases, however, the memory cache is easier to implement. Suppose in a case total, an application is a large number of transaction objects, occupy important CPU resources, produce complex data, and use JSP pages to render the data. Work everything well until one day suddenly the load on the server increases and requires an emergency solution. A very good and effective solution is to create a cache layer between the transaction object and the rendering expression layer. However, JSP pages that cache dynamic content must be modified very quickly and smoothly. As opposed to simple JSP page edits, the application's business logic changes often require more effort and testing, and if a page aggregates information from multiple composite sources, the Web layer has only a small amount of change. The problem is that cache space needs to be freed when cached information becomes lost, and the transaction object should know when this happens. However, choosing whether to implement content caching or data caching, or other optimization techniques, has many factors to consider, sometimes the particular requirements of the program being developed.
There is no need for data caching and content caching to be mutually exclusive, and they can be used together. For example, in a database-driven application, the data extracted from the database and the HTML that renders the data are cached separately. This is somewhat similar to the template that is generated in real time using JSP. The El API technology discussed in this article demonstrates how to use JSP el to load data into the rendering template.
Caching dynamic content with JSP variables
Whenever you implement a caching mechanism, you need a way to store the cached object, and in this article is a string type of object. One option is to use an object-cache frame structure, or use Java maps to implement a custom caching scheme. JSP already has the name "scoped attributes" or "JSP variables" to provide id--object mapping, which is what the caching mechanism needs. This is meaningless for using page or request scope, and it is a good place to store cached content within the scope of the application, because it is shared by all users and pages. Session scope can also be used when each user needs to be cached separately, but this is not very efficient. The JSTL tag library can be cached with that content by using a JSP variable as shown in the following example:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><c:if test="${empty cachedFragment}">
<c:set var="cachedFragment" scope="application">
...
</c:set></c:if>
The cached page fragment outputs the result with the following statement:
${applicationscope.cachedfragment}
What happens when a cached fragment needs to be customized by each request? For example, if you want to include a counter, you need to cache two fragments:
<%@ taglib prefix="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>
You can output the cached content using the following statement:
${CACHEDFRAGMENT1} ${counter} ${cachedfragment2}
With the help of a dedicated tag library, it is much easier to customize the caching of page fragments. As mentioned above, the cached content can be encapsulated by the start tag ( ) and the end tag ( ). Each customization can use another tag (
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ taglib prefix="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 variables are easy to use, which is a good content caching scheme for simple web apps. However, if the application produces a large amount of dynamic content, no control of the cache size is a problem. A dedicated caching framework structure can provide a more robust scenario, allowing for caching monitoring, limiting cache size, controlling caching policies, and so on.